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 24using namespace clang; 25using namespace ento; 26 27//===----------------------------------------------------------------------===// 28// DominatorsTreeDumper 29//===----------------------------------------------------------------------===// 30 31namespace { 32class DominatorsTreeDumper : public Checker<check::ASTCodeBody> { 33public: 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 45void ento::registerDominatorsTreeDumper(CheckerManager &mgr) { 46 mgr.registerChecker<DominatorsTreeDumper>(); 47} 48 49//===----------------------------------------------------------------------===// 50// LiveVariablesDumper 51//===----------------------------------------------------------------------===// 52 53namespace { 54class LiveVariablesDumper : public Checker<check::ASTCodeBody> { 55public: 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 65void ento::registerLiveVariablesDumper(CheckerManager &mgr) { 66 mgr.registerChecker<LiveVariablesDumper>(); 67} 68 69//===----------------------------------------------------------------------===// 70// CFGViewer 71//===----------------------------------------------------------------------===// 72 73namespace { 74class CFGViewer : public Checker<check::ASTCodeBody> { 75public: 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 85void ento::registerCFGViewer(CheckerManager &mgr) { 86 mgr.registerChecker<CFGViewer>(); 87} 88 89//===----------------------------------------------------------------------===// 90// CFGDumper 91//===----------------------------------------------------------------------===// 92 93namespace { 94class CFGDumper : public Checker<check::ASTCodeBody> { 95public: 96 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 111void ento::registerCFGDumper(CheckerManager &mgr) { 112 mgr.registerChecker<CFGDumper>(); 113} 114 115//===----------------------------------------------------------------------===// 116// CallGraphViewer 117//===----------------------------------------------------------------------===// 118 119namespace { 120class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > { 121public: 122 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 131void ento::registerCallGraphViewer(CheckerManager &mgr) { 132 mgr.registerChecker<CallGraphViewer>(); 133} 134 135//===----------------------------------------------------------------------===// 136// CallGraphDumper 137//===----------------------------------------------------------------------===// 138 139namespace { 140class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > { 141public: 142 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 151void ento::registerCallGraphDumper(CheckerManager &mgr) { 152 mgr.registerChecker<CallGraphDumper>(); 153} 154 155 156//===----------------------------------------------------------------------===// 157// ConfigDumper 158//===----------------------------------------------------------------------===// 159 160namespace { 161class ConfigDumper : public Checker< check::EndOfTranslationUnit > { 162 typedef AnalyzerOptions::ConfigTable Table; 163 164 static int compareEntry(const Table::MapEntryTy *const *LHS, 165 const Table::MapEntryTy *const *RHS) { 166 return (*LHS)->getKey().compare((*RHS)->getKey()); 167 } 168 169public: 170 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 190void ento::registerConfigDumper(CheckerManager &mgr) { 191 mgr.registerChecker<ConfigDumper>(); 192} 193 194//===----------------------------------------------------------------------===// 195// ExplodedGraph Viewer 196//===----------------------------------------------------------------------===// 197 198namespace { 199class ExplodedGraphViewer : public Checker< check::EndAnalysis > { 200public: 201 ExplodedGraphViewer() {} 202 void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const { 203 Eng.ViewGraph(0); 204 } 205}; 206 207} 208 209void ento::registerExplodedGraphViewer(CheckerManager &mgr) { 210 mgr.registerChecker<ExplodedGraphViewer>(); 211} 212