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     if (CFG *cfg = mgr.getCFG(D)) {
     99       cfg->dump(mgr.getLangOpts(),
    100                 llvm::sys::Process::StandardErrHasColors());
    101     }
    102   }
    103 };
    104 }
    105 
    106 void ento::registerCFGDumper(CheckerManager &mgr) {
    107   mgr.registerChecker<CFGDumper>();
    108 }
    109 
    110 //===----------------------------------------------------------------------===//
    111 // CallGraphViewer
    112 //===----------------------------------------------------------------------===//
    113 
    114 namespace {
    115 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
    116 public:
    117   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
    118                     BugReporter &BR) const {
    119     CallGraph CG;
    120     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
    121     CG.viewGraph();
    122   }
    123 };
    124 }
    125 
    126 void ento::registerCallGraphViewer(CheckerManager &mgr) {
    127   mgr.registerChecker<CallGraphViewer>();
    128 }
    129 
    130 //===----------------------------------------------------------------------===//
    131 // CallGraphDumper
    132 //===----------------------------------------------------------------------===//
    133 
    134 namespace {
    135 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
    136 public:
    137   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
    138                     BugReporter &BR) const {
    139     CallGraph CG;
    140     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
    141     CG.dump();
    142   }
    143 };
    144 }
    145 
    146 void ento::registerCallGraphDumper(CheckerManager &mgr) {
    147   mgr.registerChecker<CallGraphDumper>();
    148 }
    149 
    150 
    151 //===----------------------------------------------------------------------===//
    152 // ConfigDumper
    153 //===----------------------------------------------------------------------===//
    154 
    155 namespace {
    156 class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
    157 public:
    158   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
    159                                  AnalysisManager& mgr,
    160                                  BugReporter &BR) const {
    161 
    162     const AnalyzerOptions::ConfigTable &Config = mgr.options.Config;
    163     AnalyzerOptions::ConfigTable::const_iterator I =
    164       Config.begin(), E = Config.end();
    165 
    166     std::vector<StringRef> Keys;
    167     for (; I != E ; ++I) { Keys.push_back(I->getKey()); }
    168     sort(Keys.begin(), Keys.end());
    169 
    170     llvm::errs() << "[config]\n";
    171     for (unsigned i = 0, n = Keys.size(); i < n ; ++i) {
    172       StringRef Key = Keys[i];
    173       I = Config.find(Key);
    174       llvm::errs() << Key << " = " << I->second << '\n';
    175     }
    176     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
    177   }
    178 };
    179 }
    180 
    181 void ento::registerConfigDumper(CheckerManager &mgr) {
    182   mgr.registerChecker<ConfigDumper>();
    183 }
    184 
    185 //===----------------------------------------------------------------------===//
    186 // ExplodedGraph Viewer
    187 //===----------------------------------------------------------------------===//
    188 
    189 namespace {
    190 class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
    191 public:
    192   ExplodedGraphViewer() {}
    193   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
    194     Eng.ViewGraph(0);
    195   }
    196 };
    197 
    198 }
    199 
    200 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
    201   mgr.registerChecker<ExplodedGraphViewer>();
    202 }
    203