• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines checkers that display debugging information.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "ClangSACheckers.h"
15 #include "clang/Analysis/Analyses/Dominators.h"
16 #include "clang/Analysis/Analyses/LiveVariables.h"
17 #include "clang/Analysis/CallGraph.h"
18 #include "clang/StaticAnalyzer/Core/Checker.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
21 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
22 #include "llvm/Support/Process.h"
23 
24 using namespace clang;
25 using namespace ento;
26 
27 //===----------------------------------------------------------------------===//
28 // DominatorsTreeDumper
29 //===----------------------------------------------------------------------===//
30 
31 namespace {
32 class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
33 public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const34   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
35                         BugReporter &BR) const {
36     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
37       DominatorTree dom;
38       dom.buildDominatorTree(*AC);
39       dom.dump();
40     }
41   }
42 };
43 }
44 
registerDominatorsTreeDumper(CheckerManager & mgr)45 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
46   mgr.registerChecker<DominatorsTreeDumper>();
47 }
48 
49 //===----------------------------------------------------------------------===//
50 // LiveVariablesDumper
51 //===----------------------------------------------------------------------===//
52 
53 namespace {
54 class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
55 public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const56   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
57                         BugReporter &BR) const {
58     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
59       L->dumpBlockLiveness(mgr.getSourceManager());
60     }
61   }
62 };
63 }
64 
registerLiveVariablesDumper(CheckerManager & mgr)65 void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
66   mgr.registerChecker<LiveVariablesDumper>();
67 }
68 
69 //===----------------------------------------------------------------------===//
70 // CFGViewer
71 //===----------------------------------------------------------------------===//
72 
73 namespace {
74 class CFGViewer : public Checker<check::ASTCodeBody> {
75 public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const76   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
77                         BugReporter &BR) const {
78     if (CFG *cfg = mgr.getCFG(D)) {
79       cfg->viewCFG(mgr.getLangOpts());
80     }
81   }
82 };
83 }
84 
registerCFGViewer(CheckerManager & mgr)85 void ento::registerCFGViewer(CheckerManager &mgr) {
86   mgr.registerChecker<CFGViewer>();
87 }
88 
89 //===----------------------------------------------------------------------===//
90 // CFGDumper
91 //===----------------------------------------------------------------------===//
92 
93 namespace {
94 class CFGDumper : public Checker<check::ASTCodeBody> {
95 public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const96   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
97                         BugReporter &BR) const {
98     if (CFG *cfg = mgr.getCFG(D)) {
99       cfg->dump(mgr.getLangOpts(),
100                 llvm::sys::Process::StandardErrHasColors());
101     }
102   }
103 };
104 }
105 
registerCFGDumper(CheckerManager & mgr)106 void ento::registerCFGDumper(CheckerManager &mgr) {
107   mgr.registerChecker<CFGDumper>();
108 }
109 
110 //===----------------------------------------------------------------------===//
111 // CallGraphViewer
112 //===----------------------------------------------------------------------===//
113 
114 namespace {
115 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
116 public:
checkASTDecl(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const117   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
118                     BugReporter &BR) const {
119     CallGraph CG;
120     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
121     CG.viewGraph();
122   }
123 };
124 }
125 
registerCallGraphViewer(CheckerManager & mgr)126 void ento::registerCallGraphViewer(CheckerManager &mgr) {
127   mgr.registerChecker<CallGraphViewer>();
128 }
129 
130 //===----------------------------------------------------------------------===//
131 // CallGraphDumper
132 //===----------------------------------------------------------------------===//
133 
134 namespace {
135 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
136 public:
checkASTDecl(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const137   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
138                     BugReporter &BR) const {
139     CallGraph CG;
140     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
141     CG.dump();
142   }
143 };
144 }
145 
registerCallGraphDumper(CheckerManager & mgr)146 void ento::registerCallGraphDumper(CheckerManager &mgr) {
147   mgr.registerChecker<CallGraphDumper>();
148 }
149 
150 
151 //===----------------------------------------------------------------------===//
152 // ConfigDumper
153 //===----------------------------------------------------------------------===//
154 
155 namespace {
156 class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
157 public:
checkEndOfTranslationUnit(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const158   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
159                                  AnalysisManager& mgr,
160                                  BugReporter &BR) const {
161 
162     const AnalyzerOptions::ConfigTable &Config = mgr.options.Config;
163     AnalyzerOptions::ConfigTable::const_iterator I =
164       Config.begin(), E = Config.end();
165 
166     std::vector<StringRef> Keys;
167     for (; I != E ; ++I) { Keys.push_back(I->getKey()); }
168     sort(Keys.begin(), Keys.end());
169 
170     llvm::errs() << "[config]\n";
171     for (unsigned i = 0, n = Keys.size(); i < n ; ++i) {
172       StringRef Key = Keys[i];
173       I = Config.find(Key);
174       llvm::errs() << Key << " = " << I->second << '\n';
175     }
176     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
177   }
178 };
179 }
180 
registerConfigDumper(CheckerManager & mgr)181 void ento::registerConfigDumper(CheckerManager &mgr) {
182   mgr.registerChecker<ConfigDumper>();
183 }
184 
185 //===----------------------------------------------------------------------===//
186 // ExplodedGraph Viewer
187 //===----------------------------------------------------------------------===//
188 
189 namespace {
190 class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
191 public:
ExplodedGraphViewer()192   ExplodedGraphViewer() {}
checkEndAnalysis(ExplodedGraph & G,BugReporter & B,ExprEngine & Eng) const193   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
194     Eng.ViewGraph(0);
195   }
196 };
197 
198 }
199 
registerExplodedGraphViewer(CheckerManager & mgr)200 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
201   mgr.registerChecker<ExplodedGraphViewer>();
202 }
203