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: 34 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 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: 56 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 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: 76 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 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: 96 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 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: 117 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 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: 137 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 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: 158 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 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: 192 ExplodedGraphViewer() {} 193 void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const { 194 Eng.ViewGraph(0); 195 } 196 }; 197 198 } 199 200 void ento::registerExplodedGraphViewer(CheckerManager &mgr) { 201 mgr.registerChecker<ExplodedGraphViewer>(); 202 } 203