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/IssueHash.h"
     20 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
     21 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
     22 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
     23 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
     24 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
     25 #include "llvm/Support/Process.h"
     26 
     27 using namespace clang;
     28 using namespace ento;
     29 
     30 //===----------------------------------------------------------------------===//
     31 // DominatorsTreeDumper
     32 //===----------------------------------------------------------------------===//
     33 
     34 namespace {
     35 class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
     36 public:
     37   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
     38                         BugReporter &BR) const {
     39     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
     40       DominatorTree dom;
     41       dom.buildDominatorTree(*AC);
     42       dom.dump();
     43     }
     44   }
     45 };
     46 }
     47 
     48 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
     49   mgr.registerChecker<DominatorsTreeDumper>();
     50 }
     51 
     52 //===----------------------------------------------------------------------===//
     53 // LiveVariablesDumper
     54 //===----------------------------------------------------------------------===//
     55 
     56 namespace {
     57 class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
     58 public:
     59   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
     60                         BugReporter &BR) const {
     61     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
     62       L->dumpBlockLiveness(mgr.getSourceManager());
     63     }
     64   }
     65 };
     66 }
     67 
     68 void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
     69   mgr.registerChecker<LiveVariablesDumper>();
     70 }
     71 
     72 //===----------------------------------------------------------------------===//
     73 // CFGViewer
     74 //===----------------------------------------------------------------------===//
     75 
     76 namespace {
     77 class CFGViewer : public Checker<check::ASTCodeBody> {
     78 public:
     79   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
     80                         BugReporter &BR) const {
     81     if (CFG *cfg = mgr.getCFG(D)) {
     82       cfg->viewCFG(mgr.getLangOpts());
     83     }
     84   }
     85 };
     86 }
     87 
     88 void ento::registerCFGViewer(CheckerManager &mgr) {
     89   mgr.registerChecker<CFGViewer>();
     90 }
     91 
     92 //===----------------------------------------------------------------------===//
     93 // CFGDumper
     94 //===----------------------------------------------------------------------===//
     95 
     96 namespace {
     97 class CFGDumper : public Checker<check::ASTCodeBody> {
     98 public:
     99   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
    100                         BugReporter &BR) const {
    101     PrintingPolicy Policy(mgr.getLangOpts());
    102     Policy.TerseOutput = true;
    103     Policy.PolishForDeclaration = true;
    104     D->print(llvm::errs(), Policy);
    105 
    106     if (CFG *cfg = mgr.getCFG(D)) {
    107       cfg->dump(mgr.getLangOpts(),
    108                 llvm::sys::Process::StandardErrHasColors());
    109     }
    110   }
    111 };
    112 }
    113 
    114 void ento::registerCFGDumper(CheckerManager &mgr) {
    115   mgr.registerChecker<CFGDumper>();
    116 }
    117 
    118 //===----------------------------------------------------------------------===//
    119 // CallGraphViewer
    120 //===----------------------------------------------------------------------===//
    121 
    122 namespace {
    123 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
    124 public:
    125   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
    126                     BugReporter &BR) const {
    127     CallGraph CG;
    128     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
    129     CG.viewGraph();
    130   }
    131 };
    132 }
    133 
    134 void ento::registerCallGraphViewer(CheckerManager &mgr) {
    135   mgr.registerChecker<CallGraphViewer>();
    136 }
    137 
    138 //===----------------------------------------------------------------------===//
    139 // CallGraphDumper
    140 //===----------------------------------------------------------------------===//
    141 
    142 namespace {
    143 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
    144 public:
    145   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
    146                     BugReporter &BR) const {
    147     CallGraph CG;
    148     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
    149     CG.dump();
    150   }
    151 };
    152 }
    153 
    154 void ento::registerCallGraphDumper(CheckerManager &mgr) {
    155   mgr.registerChecker<CallGraphDumper>();
    156 }
    157 
    158 
    159 //===----------------------------------------------------------------------===//
    160 // ConfigDumper
    161 //===----------------------------------------------------------------------===//
    162 
    163 namespace {
    164 class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
    165   typedef AnalyzerOptions::ConfigTable Table;
    166 
    167   static int compareEntry(const Table::MapEntryTy *const *LHS,
    168                           const Table::MapEntryTy *const *RHS) {
    169     return (*LHS)->getKey().compare((*RHS)->getKey());
    170   }
    171 
    172 public:
    173   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
    174                                  AnalysisManager& mgr,
    175                                  BugReporter &BR) const {
    176     const Table &Config = mgr.options.Config;
    177 
    178     SmallVector<const Table::MapEntryTy *, 32> Keys;
    179     for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
    180          ++I)
    181       Keys.push_back(&*I);
    182     llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
    183 
    184     llvm::errs() << "[config]\n";
    185     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
    186       llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
    187 
    188     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
    189   }
    190 };
    191 }
    192 
    193 void ento::registerConfigDumper(CheckerManager &mgr) {
    194   mgr.registerChecker<ConfigDumper>();
    195 }
    196 
    197 //===----------------------------------------------------------------------===//
    198 // ExplodedGraph Viewer
    199 //===----------------------------------------------------------------------===//
    200 
    201 namespace {
    202 class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
    203 public:
    204   ExplodedGraphViewer() {}
    205   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
    206     Eng.ViewGraph(0);
    207   }
    208 };
    209 
    210 }
    211 
    212 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
    213   mgr.registerChecker<ExplodedGraphViewer>();
    214 }
    215 
    216 //===----------------------------------------------------------------------===//
    217 // DumpBugHash
    218 //===----------------------------------------------------------------------===//
    219 
    220 namespace {
    221 class BugHashDumper : public Checker<check::PostStmt<Stmt>> {
    222 public:
    223   mutable std::unique_ptr<BugType> BT;
    224 
    225   void checkPostStmt(const Stmt *S, CheckerContext &C) const {
    226     if (!BT)
    227       BT.reset(new BugType(this, "Dump hash components", "debug"));
    228 
    229     ExplodedNode *N = C.generateNonFatalErrorNode();
    230     if (!N)
    231       return;
    232 
    233     const LangOptions &Opts = C.getLangOpts();
    234     const SourceManager &SM = C.getSourceManager();
    235     FullSourceLoc FL(S->getLocStart(), SM);
    236     std::string HashContent =
    237         GetIssueString(SM, FL, getCheckName().getName(), BT->getCategory(),
    238                        C.getLocationContext()->getDecl(), Opts);
    239 
    240     C.emitReport(llvm::make_unique<BugReport>(*BT, HashContent, N));
    241   }
    242 };
    243 }
    244 
    245 void ento::registerBugHashDumper(CheckerManager &mgr) {
    246   mgr.registerChecker<BugHashDumper>();
    247 }
    248