157d736fdSArgyrios Kyrtzidis //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==// 257d736fdSArgyrios Kyrtzidis // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 657d736fdSArgyrios Kyrtzidis // 757d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===// 857d736fdSArgyrios Kyrtzidis // 973b75e01SJordan Rose // This file defines checkers that display debugging information. 1057d736fdSArgyrios Kyrtzidis // 1157d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===// 1257d736fdSArgyrios Kyrtzidis 1376a21502SKristof Umann #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 143a02247dSChandler Carruth #include "clang/Analysis/Analyses/Dominators.h" 153a02247dSChandler Carruth #include "clang/Analysis/Analyses/LiveVariables.h" 163a02247dSChandler Carruth #include "clang/Analysis/CallGraph.h" 176a5674ffSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/Checker.h" 18efec1630SGabor Horvath #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 1957d736fdSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 20efec1630SGabor Horvath #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 217925e3dbSAnna Zaks #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" 227925e3dbSAnna Zaks #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" 2372be32afSTed Kremenek #include "llvm/Support/Process.h" 2457d736fdSArgyrios Kyrtzidis 2557d736fdSArgyrios Kyrtzidis using namespace clang; 2657d736fdSArgyrios Kyrtzidis using namespace ento; 2757d736fdSArgyrios Kyrtzidis 2857d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===// 290062e749STed Kremenek // DominatorsTreeDumper 300062e749STed Kremenek //===----------------------------------------------------------------------===// 310062e749STed Kremenek 320062e749STed Kremenek namespace { 330062e749STed Kremenek class DominatorsTreeDumper : public Checker<check::ASTCodeBody> { 340062e749STed Kremenek public: 350062e749STed Kremenek void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 360062e749STed Kremenek BugReporter &BR) const { 370062e749STed Kremenek if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) { 3802a1fc1dSAnna Zaks DominatorTree dom; 3902a1fc1dSAnna Zaks dom.buildDominatorTree(*AC); 400062e749STed Kremenek dom.dump(); 410062e749STed Kremenek } 420062e749STed Kremenek } 430062e749STed Kremenek }; 44ab9db510SAlexander Kornienko } 450062e749STed Kremenek 460062e749STed Kremenek void ento::registerDominatorsTreeDumper(CheckerManager &mgr) { 470062e749STed Kremenek mgr.registerChecker<DominatorsTreeDumper>(); 480062e749STed Kremenek } 490062e749STed Kremenek 500062e749STed Kremenek //===----------------------------------------------------------------------===// 5157d736fdSArgyrios Kyrtzidis // LiveVariablesDumper 5257d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===// 5357d736fdSArgyrios Kyrtzidis 5457d736fdSArgyrios Kyrtzidis namespace { 556a5674ffSArgyrios Kyrtzidis class LiveVariablesDumper : public Checker<check::ASTCodeBody> { 5657d736fdSArgyrios Kyrtzidis public: 5757d736fdSArgyrios Kyrtzidis void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 5857d736fdSArgyrios Kyrtzidis BugReporter &BR) const { 59dccc2b22STed Kremenek if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) { 6057d736fdSArgyrios Kyrtzidis L->dumpBlockLiveness(mgr.getSourceManager()); 6157d736fdSArgyrios Kyrtzidis } 6257d736fdSArgyrios Kyrtzidis } 6357d736fdSArgyrios Kyrtzidis }; 64ab9db510SAlexander Kornienko } 6557d736fdSArgyrios Kyrtzidis 6657d736fdSArgyrios Kyrtzidis void ento::registerLiveVariablesDumper(CheckerManager &mgr) { 6757d736fdSArgyrios Kyrtzidis mgr.registerChecker<LiveVariablesDumper>(); 6857d736fdSArgyrios Kyrtzidis } 6957d736fdSArgyrios Kyrtzidis 7057d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===// 71dda42164SArtem Dergachev // LiveStatementsDumper 72dda42164SArtem Dergachev //===----------------------------------------------------------------------===// 73dda42164SArtem Dergachev 74dda42164SArtem Dergachev namespace { 75dda42164SArtem Dergachev class LiveStatementsDumper : public Checker<check::ASTCodeBody> { 76dda42164SArtem Dergachev public: 77dda42164SArtem Dergachev void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr, 78dda42164SArtem Dergachev BugReporter &BR) const { 79dda42164SArtem Dergachev if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D)) 80dda42164SArtem Dergachev L->dumpStmtLiveness(Mgr.getSourceManager()); 81dda42164SArtem Dergachev } 82dda42164SArtem Dergachev }; 83dda42164SArtem Dergachev } 84dda42164SArtem Dergachev 85dda42164SArtem Dergachev void ento::registerLiveStatementsDumper(CheckerManager &mgr) { 86dda42164SArtem Dergachev mgr.registerChecker<LiveStatementsDumper>(); 87dda42164SArtem Dergachev } 88dda42164SArtem Dergachev 89dda42164SArtem Dergachev //===----------------------------------------------------------------------===// 9057d736fdSArgyrios Kyrtzidis // CFGViewer 9157d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===// 9257d736fdSArgyrios Kyrtzidis 9357d736fdSArgyrios Kyrtzidis namespace { 946a5674ffSArgyrios Kyrtzidis class CFGViewer : public Checker<check::ASTCodeBody> { 9557d736fdSArgyrios Kyrtzidis public: 9657d736fdSArgyrios Kyrtzidis void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 9757d736fdSArgyrios Kyrtzidis BugReporter &BR) const { 9857d736fdSArgyrios Kyrtzidis if (CFG *cfg = mgr.getCFG(D)) { 99bbafb8a7SDavid Blaikie cfg->viewCFG(mgr.getLangOpts()); 10057d736fdSArgyrios Kyrtzidis } 10157d736fdSArgyrios Kyrtzidis } 10257d736fdSArgyrios Kyrtzidis }; 103ab9db510SAlexander Kornienko } 10457d736fdSArgyrios Kyrtzidis 10557d736fdSArgyrios Kyrtzidis void ento::registerCFGViewer(CheckerManager &mgr) { 10657d736fdSArgyrios Kyrtzidis mgr.registerChecker<CFGViewer>(); 10757d736fdSArgyrios Kyrtzidis } 10857d736fdSArgyrios Kyrtzidis 10957d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===// 11057d736fdSArgyrios Kyrtzidis // CFGDumper 11157d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===// 11257d736fdSArgyrios Kyrtzidis 11357d736fdSArgyrios Kyrtzidis namespace { 1146a5674ffSArgyrios Kyrtzidis class CFGDumper : public Checker<check::ASTCodeBody> { 11557d736fdSArgyrios Kyrtzidis public: 11657d736fdSArgyrios Kyrtzidis void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, 11757d736fdSArgyrios Kyrtzidis BugReporter &BR) const { 118e02e96a6SJordan Rose PrintingPolicy Policy(mgr.getLangOpts()); 119e02e96a6SJordan Rose Policy.TerseOutput = true; 120e02e96a6SJordan Rose Policy.PolishForDeclaration = true; 121e02e96a6SJordan Rose D->print(llvm::errs(), Policy); 122e02e96a6SJordan Rose 12357d736fdSArgyrios Kyrtzidis if (CFG *cfg = mgr.getCFG(D)) { 124bbafb8a7SDavid Blaikie cfg->dump(mgr.getLangOpts(), 12572be32afSTed Kremenek llvm::sys::Process::StandardErrHasColors()); 12657d736fdSArgyrios Kyrtzidis } 12757d736fdSArgyrios Kyrtzidis } 12857d736fdSArgyrios Kyrtzidis }; 129ab9db510SAlexander Kornienko } 13057d736fdSArgyrios Kyrtzidis 13157d736fdSArgyrios Kyrtzidis void ento::registerCFGDumper(CheckerManager &mgr) { 13257d736fdSArgyrios Kyrtzidis mgr.registerChecker<CFGDumper>(); 13357d736fdSArgyrios Kyrtzidis } 134c000e7edSAnna Zaks 135c000e7edSAnna Zaks //===----------------------------------------------------------------------===// 136c000e7edSAnna Zaks // CallGraphViewer 137c000e7edSAnna Zaks //===----------------------------------------------------------------------===// 138c000e7edSAnna Zaks 139c000e7edSAnna Zaks namespace { 140c000e7edSAnna Zaks class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > { 141c000e7edSAnna Zaks public: 142c000e7edSAnna Zaks void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr, 143c000e7edSAnna Zaks BugReporter &BR) const { 144c000e7edSAnna Zaks CallGraph CG; 145c000e7edSAnna Zaks CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU)); 146c000e7edSAnna Zaks CG.viewGraph(); 147c000e7edSAnna Zaks } 148c000e7edSAnna Zaks }; 149ab9db510SAlexander Kornienko } 150c000e7edSAnna Zaks 151c000e7edSAnna Zaks void ento::registerCallGraphViewer(CheckerManager &mgr) { 152c000e7edSAnna Zaks mgr.registerChecker<CallGraphViewer>(); 153c000e7edSAnna Zaks } 154c000e7edSAnna Zaks 155c000e7edSAnna Zaks //===----------------------------------------------------------------------===// 156c000e7edSAnna Zaks // CallGraphDumper 157c000e7edSAnna Zaks //===----------------------------------------------------------------------===// 158c000e7edSAnna Zaks 159c000e7edSAnna Zaks namespace { 160c000e7edSAnna Zaks class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > { 161c000e7edSAnna Zaks public: 162c000e7edSAnna Zaks void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr, 163c000e7edSAnna Zaks BugReporter &BR) const { 164c000e7edSAnna Zaks CallGraph CG; 165c000e7edSAnna Zaks CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU)); 166c000e7edSAnna Zaks CG.dump(); 167c000e7edSAnna Zaks } 168c000e7edSAnna Zaks }; 169ab9db510SAlexander Kornienko } 170c000e7edSAnna Zaks 171c000e7edSAnna Zaks void ento::registerCallGraphDumper(CheckerManager &mgr) { 172c000e7edSAnna Zaks mgr.registerChecker<CallGraphDumper>(); 173c000e7edSAnna Zaks } 17486917fdbSTed Kremenek 17586917fdbSTed Kremenek 17686917fdbSTed Kremenek //===----------------------------------------------------------------------===// 17786917fdbSTed Kremenek // ConfigDumper 17886917fdbSTed Kremenek //===----------------------------------------------------------------------===// 17986917fdbSTed Kremenek 18086917fdbSTed Kremenek namespace { 18186917fdbSTed Kremenek class ConfigDumper : public Checker< check::EndOfTranslationUnit > { 182a92b80f8SBenjamin Kramer typedef AnalyzerOptions::ConfigTable Table; 183a92b80f8SBenjamin Kramer 1844cadf292SBenjamin Kramer static int compareEntry(const Table::MapEntryTy *const *LHS, 1854cadf292SBenjamin Kramer const Table::MapEntryTy *const *RHS) { 1864cadf292SBenjamin Kramer return (*LHS)->getKey().compare((*RHS)->getKey()); 1874cadf292SBenjamin Kramer } 1884cadf292SBenjamin Kramer 18986917fdbSTed Kremenek public: 19086917fdbSTed Kremenek void checkEndOfTranslationUnit(const TranslationUnitDecl *TU, 19186917fdbSTed Kremenek AnalysisManager& mgr, 19286917fdbSTed Kremenek BugReporter &BR) const { 193a92b80f8SBenjamin Kramer const Table &Config = mgr.options.Config; 19486917fdbSTed Kremenek 195a92b80f8SBenjamin Kramer SmallVector<const Table::MapEntryTy *, 32> Keys; 196a92b80f8SBenjamin Kramer for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E; 197a92b80f8SBenjamin Kramer ++I) 198a92b80f8SBenjamin Kramer Keys.push_back(&*I); 1994cadf292SBenjamin Kramer llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry); 20086917fdbSTed Kremenek 20186917fdbSTed Kremenek llvm::errs() << "[config]\n"; 202a92b80f8SBenjamin Kramer for (unsigned I = 0, E = Keys.size(); I != E; ++I) 203549f9cd4SKristof Umann llvm::errs() << Keys[I]->getKey() << " = " 204549f9cd4SKristof Umann << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second) 205549f9cd4SKristof Umann << '\n'; 206a92b80f8SBenjamin Kramer 20786917fdbSTed Kremenek llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n'; 20886917fdbSTed Kremenek } 20986917fdbSTed Kremenek }; 210ab9db510SAlexander Kornienko } 21186917fdbSTed Kremenek 21286917fdbSTed Kremenek void ento::registerConfigDumper(CheckerManager &mgr) { 21386917fdbSTed Kremenek mgr.registerChecker<ConfigDumper>(); 21486917fdbSTed Kremenek } 2157925e3dbSAnna Zaks 2167925e3dbSAnna Zaks //===----------------------------------------------------------------------===// 2177925e3dbSAnna Zaks // ExplodedGraph Viewer 2187925e3dbSAnna Zaks //===----------------------------------------------------------------------===// 2197925e3dbSAnna Zaks 2207925e3dbSAnna Zaks namespace { 2217925e3dbSAnna Zaks class ExplodedGraphViewer : public Checker< check::EndAnalysis > { 2227925e3dbSAnna Zaks public: 2237925e3dbSAnna Zaks ExplodedGraphViewer() {} 2247925e3dbSAnna Zaks void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const { 2257925e3dbSAnna Zaks Eng.ViewGraph(0); 2267925e3dbSAnna Zaks } 2277925e3dbSAnna Zaks }; 2287925e3dbSAnna Zaks 2297925e3dbSAnna Zaks } 2307925e3dbSAnna Zaks 2317925e3dbSAnna Zaks void ento::registerExplodedGraphViewer(CheckerManager &mgr) { 2327925e3dbSAnna Zaks mgr.registerChecker<ExplodedGraphViewer>(); 2337925e3dbSAnna Zaks } 234efec1630SGabor Horvath 235