Home | History | Annotate | Download | only in Checkers
      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     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 
    111 void ento::registerCFGDumper(CheckerManager &mgr) {
    112   mgr.registerChecker<CFGDumper>();
    113 }
    114 
    115 //===----------------------------------------------------------------------===//
    116 // CallGraphViewer
    117 //===----------------------------------------------------------------------===//
    118 
    119 namespace {
    120 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
    121 public:
    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 
    131 void ento::registerCallGraphViewer(CheckerManager &mgr) {
    132   mgr.registerChecker<CallGraphViewer>();
    133 }
    134 
    135 //===----------------------------------------------------------------------===//
    136 // CallGraphDumper
    137 //===----------------------------------------------------------------------===//
    138 
    139 namespace {
    140 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
    141 public:
    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 
    151 void ento::registerCallGraphDumper(CheckerManager &mgr) {
    152   mgr.registerChecker<CallGraphDumper>();
    153 }
    154 
    155 
    156 //===----------------------------------------------------------------------===//
    157 // ConfigDumper
    158 //===----------------------------------------------------------------------===//
    159 
    160 namespace {
    161 class 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 
    169 public:
    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 
    190 void ento::registerConfigDumper(CheckerManager &mgr) {
    191   mgr.registerChecker<ConfigDumper>();
    192 }
    193 
    194 //===----------------------------------------------------------------------===//
    195 // ExplodedGraph Viewer
    196 //===----------------------------------------------------------------------===//
    197 
    198 namespace {
    199 class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
    200 public:
    201   ExplodedGraphViewer() {}
    202   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
    203     Eng.ViewGraph(0);
    204   }
    205 };
    206 
    207 }
    208 
    209 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
    210   mgr.registerChecker<ExplodedGraphViewer>();
    211 }
    212