clang API Documentation

DebugCheckers.cpp
Go to the documentation of this file.
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 }