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 PrintingPolicy Policy(mgr.getLangOpts());
99 Policy.TerseOutput = true;
100 Policy.PolishForDeclaration = true;
101 D->print(llvm::errs(), Policy);
102
103 if (CFG *cfg = mgr.getCFG(D)) {
104 cfg->dump(mgr.getLangOpts(),
105 llvm::sys::Process::StandardErrHasColors());
106 }
107 }
108 };
109 }
110
registerCFGDumper(CheckerManager & mgr)111 void ento::registerCFGDumper(CheckerManager &mgr) {
112 mgr.registerChecker<CFGDumper>();
113 }
114
115 //===----------------------------------------------------------------------===//
116 // CallGraphViewer
117 //===----------------------------------------------------------------------===//
118
119 namespace {
120 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
121 public:
checkASTDecl(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const122 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
123 BugReporter &BR) const {
124 CallGraph CG;
125 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
126 CG.viewGraph();
127 }
128 };
129 }
130
registerCallGraphViewer(CheckerManager & mgr)131 void ento::registerCallGraphViewer(CheckerManager &mgr) {
132 mgr.registerChecker<CallGraphViewer>();
133 }
134
135 //===----------------------------------------------------------------------===//
136 // CallGraphDumper
137 //===----------------------------------------------------------------------===//
138
139 namespace {
140 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
141 public:
checkASTDecl(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const142 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
143 BugReporter &BR) const {
144 CallGraph CG;
145 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
146 CG.dump();
147 }
148 };
149 }
150
registerCallGraphDumper(CheckerManager & mgr)151 void ento::registerCallGraphDumper(CheckerManager &mgr) {
152 mgr.registerChecker<CallGraphDumper>();
153 }
154
155
156 //===----------------------------------------------------------------------===//
157 // ConfigDumper
158 //===----------------------------------------------------------------------===//
159
160 namespace {
161 class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
162 typedef AnalyzerOptions::ConfigTable Table;
163
compareEntry(const Table::MapEntryTy * const * LHS,const Table::MapEntryTy * const * RHS)164 static int compareEntry(const Table::MapEntryTy *const *LHS,
165 const Table::MapEntryTy *const *RHS) {
166 return (*LHS)->getKey().compare((*RHS)->getKey());
167 }
168
169 public:
checkEndOfTranslationUnit(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const170 void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
171 AnalysisManager& mgr,
172 BugReporter &BR) const {
173 const Table &Config = mgr.options.Config;
174
175 SmallVector<const Table::MapEntryTy *, 32> Keys;
176 for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
177 ++I)
178 Keys.push_back(&*I);
179 llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
180
181 llvm::errs() << "[config]\n";
182 for (unsigned I = 0, E = Keys.size(); I != E; ++I)
183 llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
184
185 llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
186 }
187 };
188 }
189
registerConfigDumper(CheckerManager & mgr)190 void ento::registerConfigDumper(CheckerManager &mgr) {
191 mgr.registerChecker<ConfigDumper>();
192 }
193
194 //===----------------------------------------------------------------------===//
195 // ExplodedGraph Viewer
196 //===----------------------------------------------------------------------===//
197
198 namespace {
199 class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
200 public:
ExplodedGraphViewer()201 ExplodedGraphViewer() {}
checkEndAnalysis(ExplodedGraph & G,BugReporter & B,ExprEngine & Eng) const202 void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
203 Eng.ViewGraph(0);
204 }
205 };
206
207 }
208
registerExplodedGraphViewer(CheckerManager & mgr)209 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
210 mgr.registerChecker<ExplodedGraphViewer>();
211 }
212