clang API Documentation
00001 //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines checkers that display debugging information. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "ClangSACheckers.h" 00015 #include "clang/Analysis/Analyses/Dominators.h" 00016 #include "clang/Analysis/Analyses/LiveVariables.h" 00017 #include "clang/Analysis/CallGraph.h" 00018 #include "clang/StaticAnalyzer/Core/Checker.h" 00019 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 00020 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 00021 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 00022 #include "llvm/Support/Process.h" 00023 00024 using namespace clang; 00025 using namespace ento; 00026 00027 //===----------------------------------------------------------------------===// 00028 // DominatorsTreeDumper 00029 //===----------------------------------------------------------------------===// 00030 00031 namespace { 00032 class DominatorsTreeDumper : public Checker<check::ASTCodeBody> { 00033 public: 00034 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 00035 BugReporter &BR) const { 00036 if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) { 00037 DominatorTree dom; 00038 dom.buildDominatorTree(*AC); 00039 dom.dump(); 00040 } 00041 } 00042 }; 00043 } 00044 00045 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) { 00046 mgr.registerChecker<DominatorsTreeDumper>(); 00047 } 00048 00049 //===----------------------------------------------------------------------===// 00050 // LiveVariablesDumper 00051 //===----------------------------------------------------------------------===// 00052 00053 namespace { 00054 class LiveVariablesDumper : public Checker<check::ASTCodeBody> { 00055 public: 00056 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 00057 BugReporter &BR) const { 00058 if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) { 00059 L->dumpBlockLiveness(mgr.getSourceManager()); 00060 } 00061 } 00062 }; 00063 } 00064 00065 void ento::registerLiveVariablesDumper(CheckerManager &mgr) { 00066 mgr.registerChecker<LiveVariablesDumper>(); 00067 } 00068 00069 //===----------------------------------------------------------------------===// 00070 // CFGViewer 00071 //===----------------------------------------------------------------------===// 00072 00073 namespace { 00074 class CFGViewer : public Checker<check::ASTCodeBody> { 00075 public: 00076 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 00077 BugReporter &BR) const { 00078 if (CFG *cfg = mgr.getCFG(D)) { 00079 cfg->viewCFG(mgr.getLangOpts()); 00080 } 00081 } 00082 }; 00083 } 00084 00085 void ento::registerCFGViewer(CheckerManager &mgr) { 00086 mgr.registerChecker<CFGViewer>(); 00087 } 00088 00089 //===----------------------------------------------------------------------===// 00090 // CFGDumper 00091 //===----------------------------------------------------------------------===// 00092 00093 namespace { 00094 class CFGDumper : public Checker<check::ASTCodeBody> { 00095 public: 00096 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 00097 BugReporter &BR) const { 00098 PrintingPolicy Policy(mgr.getLangOpts()); 00099 Policy.TerseOutput = true; 00100 Policy.PolishForDeclaration = true; 00101 D->print(llvm::errs(), Policy); 00102 00103 if (CFG *cfg = mgr.getCFG(D)) { 00104 cfg->dump(mgr.getLangOpts(), 00105 llvm::sys::Process::StandardErrHasColors()); 00106 } 00107 } 00108 }; 00109 } 00110 00111 void ento::registerCFGDumper(CheckerManager &mgr) { 00112 mgr.registerChecker<CFGDumper>(); 00113 } 00114 00115 //===----------------------------------------------------------------------===// 00116 // CallGraphViewer 00117 //===----------------------------------------------------------------------===// 00118 00119 namespace { 00120 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > { 00121 public: 00122 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr, 00123 BugReporter &BR) const { 00124 CallGraph CG; 00125 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU)); 00126 CG.viewGraph(); 00127 } 00128 }; 00129 } 00130 00131 void ento::registerCallGraphViewer(CheckerManager &mgr) { 00132 mgr.registerChecker<CallGraphViewer>(); 00133 } 00134 00135 //===----------------------------------------------------------------------===// 00136 // CallGraphDumper 00137 //===----------------------------------------------------------------------===// 00138 00139 namespace { 00140 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > { 00141 public: 00142 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr, 00143 BugReporter &BR) const { 00144 CallGraph CG; 00145 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU)); 00146 CG.dump(); 00147 } 00148 }; 00149 } 00150 00151 void ento::registerCallGraphDumper(CheckerManager &mgr) { 00152 mgr.registerChecker<CallGraphDumper>(); 00153 } 00154 00155 00156 //===----------------------------------------------------------------------===// 00157 // ConfigDumper 00158 //===----------------------------------------------------------------------===// 00159 00160 namespace { 00161 class ConfigDumper : public Checker< check::EndOfTranslationUnit > { 00162 typedef AnalyzerOptions::ConfigTable Table; 00163 00164 static int compareEntry(const Table::MapEntryTy *const *LHS, 00165 const Table::MapEntryTy *const *RHS) { 00166 return (*LHS)->getKey().compare((*RHS)->getKey()); 00167 } 00168 00169 public: 00170 void checkEndOfTranslationUnit(const TranslationUnitDecl *TU, 00171 AnalysisManager& mgr, 00172 BugReporter &BR) const { 00173 const Table &Config = mgr.options.Config; 00174 00175 SmallVector<const Table::MapEntryTy *, 32> Keys; 00176 for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E; 00177 ++I) 00178 Keys.push_back(&*I); 00179 llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry); 00180 00181 llvm::errs() << "[config]\n"; 00182 for (unsigned I = 0, E = Keys.size(); I != E; ++I) 00183 llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n'; 00184 00185 llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n'; 00186 } 00187 }; 00188 } 00189 00190 void ento::registerConfigDumper(CheckerManager &mgr) { 00191 mgr.registerChecker<ConfigDumper>(); 00192 } 00193 00194 //===----------------------------------------------------------------------===// 00195 // ExplodedGraph Viewer 00196 //===----------------------------------------------------------------------===// 00197 00198 namespace { 00199 class ExplodedGraphViewer : public Checker< check::EndAnalysis > { 00200 public: 00201 ExplodedGraphViewer() {} 00202 void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const { 00203 Eng.ViewGraph(0); 00204 } 00205 }; 00206 00207 } 00208 00209 void ento::registerExplodedGraphViewer(CheckerManager &mgr) { 00210 mgr.registerChecker<ExplodedGraphViewer>(); 00211 }