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 a 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 "llvm/Support/Process.h" 21 22 using namespace clang; 23 using namespace ento; 24 25 //===----------------------------------------------------------------------===// 26 // DominatorsTreeDumper 27 //===----------------------------------------------------------------------===// 28 29 namespace { 30 class DominatorsTreeDumper : public Checker<check::ASTCodeBody> { 31 public: 32 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 33 BugReporter &BR) const { 34 if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) { 35 DominatorTree dom; 36 dom.buildDominatorTree(*AC); 37 dom.dump(); 38 } 39 } 40 }; 41 } 42 43 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) { 44 mgr.registerChecker<DominatorsTreeDumper>(); 45 } 46 47 //===----------------------------------------------------------------------===// 48 // LiveVariablesDumper 49 //===----------------------------------------------------------------------===// 50 51 namespace { 52 class LiveVariablesDumper : public Checker<check::ASTCodeBody> { 53 public: 54 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 55 BugReporter &BR) const { 56 if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) { 57 L->dumpBlockLiveness(mgr.getSourceManager()); 58 } 59 } 60 }; 61 } 62 63 void ento::registerLiveVariablesDumper(CheckerManager &mgr) { 64 mgr.registerChecker<LiveVariablesDumper>(); 65 } 66 67 //===----------------------------------------------------------------------===// 68 // CFGViewer 69 //===----------------------------------------------------------------------===// 70 71 namespace { 72 class CFGViewer : public Checker<check::ASTCodeBody> { 73 public: 74 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 75 BugReporter &BR) const { 76 if (CFG *cfg = mgr.getCFG(D)) { 77 cfg->viewCFG(mgr.getLangOpts()); 78 } 79 } 80 }; 81 } 82 83 void ento::registerCFGViewer(CheckerManager &mgr) { 84 mgr.registerChecker<CFGViewer>(); 85 } 86 87 //===----------------------------------------------------------------------===// 88 // CFGDumper 89 //===----------------------------------------------------------------------===// 90 91 namespace { 92 class CFGDumper : public Checker<check::ASTCodeBody> { 93 public: 94 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 95 BugReporter &BR) const { 96 if (CFG *cfg = mgr.getCFG(D)) { 97 cfg->dump(mgr.getLangOpts(), 98 llvm::sys::Process::StandardErrHasColors()); 99 } 100 } 101 }; 102 } 103 104 void ento::registerCFGDumper(CheckerManager &mgr) { 105 mgr.registerChecker<CFGDumper>(); 106 } 107 108 //===----------------------------------------------------------------------===// 109 // CallGraphViewer 110 //===----------------------------------------------------------------------===// 111 112 namespace { 113 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > { 114 public: 115 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr, 116 BugReporter &BR) const { 117 CallGraph CG; 118 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU)); 119 CG.viewGraph(); 120 } 121 }; 122 } 123 124 void ento::registerCallGraphViewer(CheckerManager &mgr) { 125 mgr.registerChecker<CallGraphViewer>(); 126 } 127 128 //===----------------------------------------------------------------------===// 129 // CallGraphDumper 130 //===----------------------------------------------------------------------===// 131 132 namespace { 133 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > { 134 public: 135 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr, 136 BugReporter &BR) const { 137 CallGraph CG; 138 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU)); 139 CG.dump(); 140 } 141 }; 142 } 143 144 void ento::registerCallGraphDumper(CheckerManager &mgr) { 145 mgr.registerChecker<CallGraphDumper>(); 146 } 147 148 149 //===----------------------------------------------------------------------===// 150 // ConfigDumper 151 //===----------------------------------------------------------------------===// 152 153 namespace { 154 class ConfigDumper : public Checker< check::EndOfTranslationUnit > { 155 public: 156 void checkEndOfTranslationUnit(const TranslationUnitDecl *TU, 157 AnalysisManager& mgr, 158 BugReporter &BR) const { 159 160 const AnalyzerOptions::ConfigTable &Config = mgr.options.Config; 161 AnalyzerOptions::ConfigTable::const_iterator I = 162 Config.begin(), E = Config.end(); 163 164 std::vector<StringRef> Keys; 165 for (; I != E ; ++I) { Keys.push_back(I->getKey()); } 166 sort(Keys.begin(), Keys.end()); 167 168 llvm::errs() << "[config]\n"; 169 for (unsigned i = 0, n = Keys.size(); i < n ; ++i) { 170 StringRef Key = Keys[i]; 171 I = Config.find(Key); 172 llvm::errs() << Key << " = " << I->second << '\n'; 173 } 174 llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n'; 175 } 176 }; 177 } 178 179 void ento::registerConfigDumper(CheckerManager &mgr) { 180 mgr.registerChecker<ConfigDumper>(); 181 } 182