1218887Sdim//==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10251662Sdim// This file defines checkers that display debugging information. 11218887Sdim// 12218887Sdim//===----------------------------------------------------------------------===// 13218887Sdim 14218887Sdim#include "ClangSACheckers.h" 15249423Sdim#include "clang/Analysis/Analyses/Dominators.h" 16249423Sdim#include "clang/Analysis/Analyses/LiveVariables.h" 17249423Sdim#include "clang/Analysis/CallGraph.h" 18221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h" 19296417Sdim#include "clang/StaticAnalyzer/Core/IssueHash.h" 20296417Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 21218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 22296417Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 23261991Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 24261991Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 25234353Sdim#include "llvm/Support/Process.h" 26218887Sdim 27218887Sdimusing namespace clang; 28218887Sdimusing namespace ento; 29218887Sdim 30218887Sdim//===----------------------------------------------------------------------===// 31234353Sdim// DominatorsTreeDumper 32234353Sdim//===----------------------------------------------------------------------===// 33234353Sdim 34234353Sdimnamespace { 35234353Sdimclass DominatorsTreeDumper : public Checker<check::ASTCodeBody> { 36234353Sdimpublic: 37234353Sdim void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 38234353Sdim BugReporter &BR) const { 39234353Sdim if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) { 40234353Sdim DominatorTree dom; 41234353Sdim dom.buildDominatorTree(*AC); 42234353Sdim dom.dump(); 43234353Sdim } 44234353Sdim } 45234353Sdim}; 46234353Sdim} 47234353Sdim 48234353Sdimvoid ento::registerDominatorsTreeDumper(CheckerManager &mgr) { 49234353Sdim mgr.registerChecker<DominatorsTreeDumper>(); 50234353Sdim} 51234353Sdim 52234353Sdim//===----------------------------------------------------------------------===// 53218887Sdim// LiveVariablesDumper 54218887Sdim//===----------------------------------------------------------------------===// 55218887Sdim 56218887Sdimnamespace { 57221345Sdimclass LiveVariablesDumper : public Checker<check::ASTCodeBody> { 58218887Sdimpublic: 59218887Sdim void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 60218887Sdim BugReporter &BR) const { 61226633Sdim if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) { 62218887Sdim L->dumpBlockLiveness(mgr.getSourceManager()); 63218887Sdim } 64218887Sdim } 65218887Sdim}; 66218887Sdim} 67218887Sdim 68218887Sdimvoid ento::registerLiveVariablesDumper(CheckerManager &mgr) { 69218887Sdim mgr.registerChecker<LiveVariablesDumper>(); 70218887Sdim} 71218887Sdim 72218887Sdim//===----------------------------------------------------------------------===// 73218887Sdim// CFGViewer 74218887Sdim//===----------------------------------------------------------------------===// 75218887Sdim 76218887Sdimnamespace { 77221345Sdimclass CFGViewer : public Checker<check::ASTCodeBody> { 78218887Sdimpublic: 79218887Sdim void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 80218887Sdim BugReporter &BR) const { 81218887Sdim if (CFG *cfg = mgr.getCFG(D)) { 82234353Sdim cfg->viewCFG(mgr.getLangOpts()); 83218887Sdim } 84218887Sdim } 85218887Sdim}; 86218887Sdim} 87218887Sdim 88218887Sdimvoid ento::registerCFGViewer(CheckerManager &mgr) { 89218887Sdim mgr.registerChecker<CFGViewer>(); 90218887Sdim} 91218887Sdim 92218887Sdim//===----------------------------------------------------------------------===// 93218887Sdim// CFGDumper 94218887Sdim//===----------------------------------------------------------------------===// 95218887Sdim 96218887Sdimnamespace { 97221345Sdimclass CFGDumper : public Checker<check::ASTCodeBody> { 98218887Sdimpublic: 99218887Sdim void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 100218887Sdim BugReporter &BR) const { 101276479Sdim PrintingPolicy Policy(mgr.getLangOpts()); 102276479Sdim Policy.TerseOutput = true; 103276479Sdim Policy.PolishForDeclaration = true; 104276479Sdim D->print(llvm::errs(), Policy); 105276479Sdim 106218887Sdim if (CFG *cfg = mgr.getCFG(D)) { 107234353Sdim cfg->dump(mgr.getLangOpts(), 108234353Sdim llvm::sys::Process::StandardErrHasColors()); 109218887Sdim } 110218887Sdim } 111218887Sdim}; 112218887Sdim} 113218887Sdim 114218887Sdimvoid ento::registerCFGDumper(CheckerManager &mgr) { 115218887Sdim mgr.registerChecker<CFGDumper>(); 116218887Sdim} 117234353Sdim 118234353Sdim//===----------------------------------------------------------------------===// 119234353Sdim// CallGraphViewer 120234353Sdim//===----------------------------------------------------------------------===// 121234353Sdim 122234353Sdimnamespace { 123234353Sdimclass CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > { 124234353Sdimpublic: 125234353Sdim void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr, 126234353Sdim BugReporter &BR) const { 127234353Sdim CallGraph CG; 128234353Sdim CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU)); 129234353Sdim CG.viewGraph(); 130234353Sdim } 131234353Sdim}; 132234353Sdim} 133234353Sdim 134234353Sdimvoid ento::registerCallGraphViewer(CheckerManager &mgr) { 135234353Sdim mgr.registerChecker<CallGraphViewer>(); 136234353Sdim} 137234353Sdim 138234353Sdim//===----------------------------------------------------------------------===// 139234353Sdim// CallGraphDumper 140234353Sdim//===----------------------------------------------------------------------===// 141234353Sdim 142234353Sdimnamespace { 143234353Sdimclass CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > { 144234353Sdimpublic: 145234353Sdim void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr, 146234353Sdim BugReporter &BR) const { 147234353Sdim CallGraph CG; 148234353Sdim CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU)); 149234353Sdim CG.dump(); 150234353Sdim } 151234353Sdim}; 152234353Sdim} 153234353Sdim 154234353Sdimvoid ento::registerCallGraphDumper(CheckerManager &mgr) { 155234353Sdim mgr.registerChecker<CallGraphDumper>(); 156234353Sdim} 157243830Sdim 158243830Sdim 159243830Sdim//===----------------------------------------------------------------------===// 160243830Sdim// ConfigDumper 161243830Sdim//===----------------------------------------------------------------------===// 162243830Sdim 163243830Sdimnamespace { 164243830Sdimclass ConfigDumper : public Checker< check::EndOfTranslationUnit > { 165261991Sdim typedef AnalyzerOptions::ConfigTable Table; 166261991Sdim 167261991Sdim static int compareEntry(const Table::MapEntryTy *const *LHS, 168261991Sdim const Table::MapEntryTy *const *RHS) { 169261991Sdim return (*LHS)->getKey().compare((*RHS)->getKey()); 170261991Sdim } 171261991Sdim 172243830Sdimpublic: 173243830Sdim void checkEndOfTranslationUnit(const TranslationUnitDecl *TU, 174243830Sdim AnalysisManager& mgr, 175243830Sdim BugReporter &BR) const { 176261991Sdim const Table &Config = mgr.options.Config; 177243830Sdim 178261991Sdim SmallVector<const Table::MapEntryTy *, 32> Keys; 179261991Sdim for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E; 180261991Sdim ++I) 181261991Sdim Keys.push_back(&*I); 182261991Sdim llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry); 183243830Sdim 184243830Sdim llvm::errs() << "[config]\n"; 185261991Sdim for (unsigned I = 0, E = Keys.size(); I != E; ++I) 186261991Sdim llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n'; 187261991Sdim 188243830Sdim llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n'; 189243830Sdim } 190243830Sdim}; 191243830Sdim} 192243830Sdim 193243830Sdimvoid ento::registerConfigDumper(CheckerManager &mgr) { 194243830Sdim mgr.registerChecker<ConfigDumper>(); 195243830Sdim} 196261991Sdim 197261991Sdim//===----------------------------------------------------------------------===// 198261991Sdim// ExplodedGraph Viewer 199261991Sdim//===----------------------------------------------------------------------===// 200261991Sdim 201261991Sdimnamespace { 202261991Sdimclass ExplodedGraphViewer : public Checker< check::EndAnalysis > { 203261991Sdimpublic: 204261991Sdim ExplodedGraphViewer() {} 205261991Sdim void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const { 206261991Sdim Eng.ViewGraph(0); 207261991Sdim } 208261991Sdim}; 209261991Sdim 210261991Sdim} 211261991Sdim 212261991Sdimvoid ento::registerExplodedGraphViewer(CheckerManager &mgr) { 213261991Sdim mgr.registerChecker<ExplodedGraphViewer>(); 214261991Sdim} 215296417Sdim 216296417Sdim//===----------------------------------------------------------------------===// 217296417Sdim// DumpBugHash 218296417Sdim//===----------------------------------------------------------------------===// 219296417Sdim 220296417Sdimnamespace { 221296417Sdimclass BugHashDumper : public Checker<check::PostStmt<Stmt>> { 222296417Sdimpublic: 223296417Sdim mutable std::unique_ptr<BugType> BT; 224296417Sdim 225296417Sdim void checkPostStmt(const Stmt *S, CheckerContext &C) const { 226296417Sdim if (!BT) 227296417Sdim BT.reset(new BugType(this, "Dump hash components", "debug")); 228296417Sdim 229296417Sdim ExplodedNode *N = C.generateNonFatalErrorNode(); 230296417Sdim if (!N) 231296417Sdim return; 232296417Sdim 233296417Sdim const LangOptions &Opts = C.getLangOpts(); 234296417Sdim const SourceManager &SM = C.getSourceManager(); 235296417Sdim FullSourceLoc FL(S->getLocStart(), SM); 236296417Sdim std::string HashContent = 237296417Sdim GetIssueString(SM, FL, getCheckName().getName(), BT->getCategory(), 238296417Sdim C.getLocationContext()->getDecl(), Opts); 239296417Sdim 240296417Sdim C.emitReport(llvm::make_unique<BugReport>(*BT, HashContent, N)); 241296417Sdim } 242296417Sdim}; 243296417Sdim} 244296417Sdim 245296417Sdimvoid ento::registerBugHashDumper(CheckerManager &mgr) { 246296417Sdim mgr.registerChecker<BugHashDumper>(); 247296417Sdim} 248