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 "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.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/BugReporter/BugType.h" 20 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 21 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 22 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 23 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 24 #include "llvm/Support/Process.h" 25 26 using namespace clang; 27 using namespace ento; 28 29 //===----------------------------------------------------------------------===// 30 // DominatorsTreeDumper 31 //===----------------------------------------------------------------------===// 32 33 namespace { 34 class DominatorsTreeDumper : public Checker<check::ASTCodeBody> { 35 public: 36 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 37 BugReporter &BR) const { 38 if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) { 39 DominatorTree dom; 40 dom.buildDominatorTree(*AC); 41 dom.dump(); 42 } 43 } 44 }; 45 } 46 47 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) { 48 mgr.registerChecker<DominatorsTreeDumper>(); 49 } 50 51 //===----------------------------------------------------------------------===// 52 // LiveVariablesDumper 53 //===----------------------------------------------------------------------===// 54 55 namespace { 56 class LiveVariablesDumper : public Checker<check::ASTCodeBody> { 57 public: 58 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 59 BugReporter &BR) const { 60 if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) { 61 L->dumpBlockLiveness(mgr.getSourceManager()); 62 } 63 } 64 }; 65 } 66 67 void ento::registerLiveVariablesDumper(CheckerManager &mgr) { 68 mgr.registerChecker<LiveVariablesDumper>(); 69 } 70 71 //===----------------------------------------------------------------------===// 72 // LiveStatementsDumper 73 //===----------------------------------------------------------------------===// 74 75 namespace { 76 class LiveStatementsDumper : public Checker<check::ASTCodeBody> { 77 public: 78 void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr, 79 BugReporter &BR) const { 80 if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D)) 81 L->dumpStmtLiveness(Mgr.getSourceManager()); 82 } 83 }; 84 } 85 86 void ento::registerLiveStatementsDumper(CheckerManager &mgr) { 87 mgr.registerChecker<LiveStatementsDumper>(); 88 } 89 90 //===----------------------------------------------------------------------===// 91 // CFGViewer 92 //===----------------------------------------------------------------------===// 93 94 namespace { 95 class CFGViewer : public Checker<check::ASTCodeBody> { 96 public: 97 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 98 BugReporter &BR) const { 99 if (CFG *cfg = mgr.getCFG(D)) { 100 cfg->viewCFG(mgr.getLangOpts()); 101 } 102 } 103 }; 104 } 105 106 void ento::registerCFGViewer(CheckerManager &mgr) { 107 mgr.registerChecker<CFGViewer>(); 108 } 109 110 //===----------------------------------------------------------------------===// 111 // CFGDumper 112 //===----------------------------------------------------------------------===// 113 114 namespace { 115 class CFGDumper : public Checker<check::ASTCodeBody> { 116 public: 117 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 118 BugReporter &BR) const { 119 PrintingPolicy Policy(mgr.getLangOpts()); 120 Policy.TerseOutput = true; 121 Policy.PolishForDeclaration = true; 122 D->print(llvm::errs(), Policy); 123 124 if (CFG *cfg = mgr.getCFG(D)) { 125 cfg->dump(mgr.getLangOpts(), 126 llvm::sys::Process::StandardErrHasColors()); 127 } 128 } 129 }; 130 } 131 132 void ento::registerCFGDumper(CheckerManager &mgr) { 133 mgr.registerChecker<CFGDumper>(); 134 } 135 136 //===----------------------------------------------------------------------===// 137 // CallGraphViewer 138 //===----------------------------------------------------------------------===// 139 140 namespace { 141 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > { 142 public: 143 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr, 144 BugReporter &BR) const { 145 CallGraph CG; 146 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU)); 147 CG.viewGraph(); 148 } 149 }; 150 } 151 152 void ento::registerCallGraphViewer(CheckerManager &mgr) { 153 mgr.registerChecker<CallGraphViewer>(); 154 } 155 156 //===----------------------------------------------------------------------===// 157 // CallGraphDumper 158 //===----------------------------------------------------------------------===// 159 160 namespace { 161 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > { 162 public: 163 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr, 164 BugReporter &BR) const { 165 CallGraph CG; 166 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU)); 167 CG.dump(); 168 } 169 }; 170 } 171 172 void ento::registerCallGraphDumper(CheckerManager &mgr) { 173 mgr.registerChecker<CallGraphDumper>(); 174 } 175 176 177 //===----------------------------------------------------------------------===// 178 // ConfigDumper 179 //===----------------------------------------------------------------------===// 180 181 namespace { 182 class ConfigDumper : public Checker< check::EndOfTranslationUnit > { 183 typedef AnalyzerOptions::ConfigTable Table; 184 185 static int compareEntry(const Table::MapEntryTy *const *LHS, 186 const Table::MapEntryTy *const *RHS) { 187 return (*LHS)->getKey().compare((*RHS)->getKey()); 188 } 189 190 public: 191 void checkEndOfTranslationUnit(const TranslationUnitDecl *TU, 192 AnalysisManager& mgr, 193 BugReporter &BR) const { 194 const Table &Config = mgr.options.Config; 195 196 SmallVector<const Table::MapEntryTy *, 32> Keys; 197 for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E; 198 ++I) 199 Keys.push_back(&*I); 200 llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry); 201 202 llvm::errs() << "[config]\n"; 203 for (unsigned I = 0, E = Keys.size(); I != E; ++I) 204 llvm::errs() << Keys[I]->getKey() << " = " 205 << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second) 206 << '\n'; 207 208 llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n'; 209 } 210 }; 211 } 212 213 void ento::registerConfigDumper(CheckerManager &mgr) { 214 mgr.registerChecker<ConfigDumper>(); 215 } 216 217 //===----------------------------------------------------------------------===// 218 // ExplodedGraph Viewer 219 //===----------------------------------------------------------------------===// 220 221 namespace { 222 class ExplodedGraphViewer : public Checker< check::EndAnalysis > { 223 public: 224 ExplodedGraphViewer() {} 225 void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const { 226 Eng.ViewGraph(0); 227 } 228 }; 229 230 } 231 232 void ento::registerExplodedGraphViewer(CheckerManager &mgr) { 233 mgr.registerChecker<ExplodedGraphViewer>(); 234 } 235 236