xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg //  This file defines checkers that display debugging information.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
147330f729Sjoerg #include "clang/Analysis/Analyses/Dominators.h"
157330f729Sjoerg #include "clang/Analysis/Analyses/LiveVariables.h"
167330f729Sjoerg #include "clang/Analysis/CallGraph.h"
177330f729Sjoerg #include "clang/StaticAnalyzer/Core/Checker.h"
187330f729Sjoerg #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
197330f729Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
207330f729Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
217330f729Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
227330f729Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
237330f729Sjoerg #include "llvm/Support/Process.h"
247330f729Sjoerg 
257330f729Sjoerg using namespace clang;
267330f729Sjoerg using namespace ento;
277330f729Sjoerg 
287330f729Sjoerg //===----------------------------------------------------------------------===//
297330f729Sjoerg // DominatorsTreeDumper
307330f729Sjoerg //===----------------------------------------------------------------------===//
317330f729Sjoerg 
327330f729Sjoerg namespace {
337330f729Sjoerg class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
347330f729Sjoerg public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const357330f729Sjoerg   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
367330f729Sjoerg                         BugReporter &BR) const {
377330f729Sjoerg     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
387330f729Sjoerg       CFGDomTree Dom;
397330f729Sjoerg       Dom.buildDominatorTree(AC->getCFG());
407330f729Sjoerg       Dom.dump();
417330f729Sjoerg     }
427330f729Sjoerg   }
437330f729Sjoerg };
447330f729Sjoerg }
457330f729Sjoerg 
registerDominatorsTreeDumper(CheckerManager & mgr)467330f729Sjoerg void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
477330f729Sjoerg   mgr.registerChecker<DominatorsTreeDumper>();
487330f729Sjoerg }
497330f729Sjoerg 
shouldRegisterDominatorsTreeDumper(const CheckerManager & mgr)50*e038c9c4Sjoerg bool ento::shouldRegisterDominatorsTreeDumper(const CheckerManager &mgr) {
517330f729Sjoerg   return true;
527330f729Sjoerg }
537330f729Sjoerg 
547330f729Sjoerg //===----------------------------------------------------------------------===//
557330f729Sjoerg // PostDominatorsTreeDumper
567330f729Sjoerg //===----------------------------------------------------------------------===//
577330f729Sjoerg 
587330f729Sjoerg namespace {
597330f729Sjoerg class PostDominatorsTreeDumper : public Checker<check::ASTCodeBody> {
607330f729Sjoerg public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const617330f729Sjoerg   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
627330f729Sjoerg                         BugReporter &BR) const {
637330f729Sjoerg     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
647330f729Sjoerg       CFGPostDomTree Dom;
657330f729Sjoerg       Dom.buildDominatorTree(AC->getCFG());
667330f729Sjoerg       Dom.dump();
677330f729Sjoerg     }
687330f729Sjoerg   }
697330f729Sjoerg };
707330f729Sjoerg }
717330f729Sjoerg 
registerPostDominatorsTreeDumper(CheckerManager & mgr)727330f729Sjoerg void ento::registerPostDominatorsTreeDumper(CheckerManager &mgr) {
737330f729Sjoerg   mgr.registerChecker<PostDominatorsTreeDumper>();
747330f729Sjoerg }
757330f729Sjoerg 
shouldRegisterPostDominatorsTreeDumper(const CheckerManager & mgr)76*e038c9c4Sjoerg bool ento::shouldRegisterPostDominatorsTreeDumper(const CheckerManager &mgr) {
777330f729Sjoerg   return true;
787330f729Sjoerg }
797330f729Sjoerg 
807330f729Sjoerg //===----------------------------------------------------------------------===//
817330f729Sjoerg // ControlDependencyTreeDumper
827330f729Sjoerg //===----------------------------------------------------------------------===//
837330f729Sjoerg 
847330f729Sjoerg namespace {
857330f729Sjoerg class ControlDependencyTreeDumper : public Checker<check::ASTCodeBody> {
867330f729Sjoerg public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const877330f729Sjoerg   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
887330f729Sjoerg                         BugReporter &BR) const {
897330f729Sjoerg     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
907330f729Sjoerg       ControlDependencyCalculator Dom(AC->getCFG());
917330f729Sjoerg       Dom.dump();
927330f729Sjoerg     }
937330f729Sjoerg   }
947330f729Sjoerg };
957330f729Sjoerg }
967330f729Sjoerg 
registerControlDependencyTreeDumper(CheckerManager & mgr)977330f729Sjoerg void ento::registerControlDependencyTreeDumper(CheckerManager &mgr) {
987330f729Sjoerg   mgr.registerChecker<ControlDependencyTreeDumper>();
997330f729Sjoerg }
1007330f729Sjoerg 
shouldRegisterControlDependencyTreeDumper(const CheckerManager & mgr)101*e038c9c4Sjoerg bool ento::shouldRegisterControlDependencyTreeDumper(const CheckerManager &mgr) {
1027330f729Sjoerg   return true;
1037330f729Sjoerg }
1047330f729Sjoerg 
1057330f729Sjoerg //===----------------------------------------------------------------------===//
1067330f729Sjoerg // LiveVariablesDumper
1077330f729Sjoerg //===----------------------------------------------------------------------===//
1087330f729Sjoerg 
1097330f729Sjoerg namespace {
1107330f729Sjoerg class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
1117330f729Sjoerg public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const1127330f729Sjoerg   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
1137330f729Sjoerg                         BugReporter &BR) const {
1147330f729Sjoerg     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
1157330f729Sjoerg       L->dumpBlockLiveness(mgr.getSourceManager());
1167330f729Sjoerg     }
1177330f729Sjoerg   }
1187330f729Sjoerg };
1197330f729Sjoerg }
1207330f729Sjoerg 
registerLiveVariablesDumper(CheckerManager & mgr)1217330f729Sjoerg void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
1227330f729Sjoerg   mgr.registerChecker<LiveVariablesDumper>();
1237330f729Sjoerg }
1247330f729Sjoerg 
shouldRegisterLiveVariablesDumper(const CheckerManager & mgr)125*e038c9c4Sjoerg bool ento::shouldRegisterLiveVariablesDumper(const CheckerManager &mgr) {
1267330f729Sjoerg   return true;
1277330f729Sjoerg }
1287330f729Sjoerg 
1297330f729Sjoerg //===----------------------------------------------------------------------===//
1307330f729Sjoerg // LiveStatementsDumper
1317330f729Sjoerg //===----------------------------------------------------------------------===//
1327330f729Sjoerg 
1337330f729Sjoerg namespace {
134*e038c9c4Sjoerg class LiveExpressionsDumper : public Checker<check::ASTCodeBody> {
1357330f729Sjoerg public:
checkASTCodeBody(const Decl * D,AnalysisManager & Mgr,BugReporter & BR) const1367330f729Sjoerg   void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
1377330f729Sjoerg                         BugReporter &BR) const {
1387330f729Sjoerg     if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))
139*e038c9c4Sjoerg       L->dumpExprLiveness(Mgr.getSourceManager());
1407330f729Sjoerg   }
1417330f729Sjoerg };
1427330f729Sjoerg }
1437330f729Sjoerg 
registerLiveExpressionsDumper(CheckerManager & mgr)144*e038c9c4Sjoerg void ento::registerLiveExpressionsDumper(CheckerManager &mgr) {
145*e038c9c4Sjoerg   mgr.registerChecker<LiveExpressionsDumper>();
1467330f729Sjoerg }
1477330f729Sjoerg 
shouldRegisterLiveExpressionsDumper(const CheckerManager & mgr)148*e038c9c4Sjoerg bool ento::shouldRegisterLiveExpressionsDumper(const CheckerManager &mgr) {
1497330f729Sjoerg   return true;
1507330f729Sjoerg }
1517330f729Sjoerg 
1527330f729Sjoerg //===----------------------------------------------------------------------===//
1537330f729Sjoerg // CFGViewer
1547330f729Sjoerg //===----------------------------------------------------------------------===//
1557330f729Sjoerg 
1567330f729Sjoerg namespace {
1577330f729Sjoerg class CFGViewer : public Checker<check::ASTCodeBody> {
1587330f729Sjoerg public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const1597330f729Sjoerg   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
1607330f729Sjoerg                         BugReporter &BR) const {
1617330f729Sjoerg     if (CFG *cfg = mgr.getCFG(D)) {
1627330f729Sjoerg       cfg->viewCFG(mgr.getLangOpts());
1637330f729Sjoerg     }
1647330f729Sjoerg   }
1657330f729Sjoerg };
1667330f729Sjoerg }
1677330f729Sjoerg 
registerCFGViewer(CheckerManager & mgr)1687330f729Sjoerg void ento::registerCFGViewer(CheckerManager &mgr) {
1697330f729Sjoerg   mgr.registerChecker<CFGViewer>();
1707330f729Sjoerg }
1717330f729Sjoerg 
shouldRegisterCFGViewer(const CheckerManager & mgr)172*e038c9c4Sjoerg bool ento::shouldRegisterCFGViewer(const CheckerManager &mgr) {
1737330f729Sjoerg   return true;
1747330f729Sjoerg }
1757330f729Sjoerg 
1767330f729Sjoerg //===----------------------------------------------------------------------===//
1777330f729Sjoerg // CFGDumper
1787330f729Sjoerg //===----------------------------------------------------------------------===//
1797330f729Sjoerg 
1807330f729Sjoerg namespace {
1817330f729Sjoerg class CFGDumper : public Checker<check::ASTCodeBody> {
1827330f729Sjoerg public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const1837330f729Sjoerg   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
1847330f729Sjoerg                         BugReporter &BR) const {
1857330f729Sjoerg     PrintingPolicy Policy(mgr.getLangOpts());
1867330f729Sjoerg     Policy.TerseOutput = true;
1877330f729Sjoerg     Policy.PolishForDeclaration = true;
1887330f729Sjoerg     D->print(llvm::errs(), Policy);
1897330f729Sjoerg 
1907330f729Sjoerg     if (CFG *cfg = mgr.getCFG(D)) {
1917330f729Sjoerg       cfg->dump(mgr.getLangOpts(),
1927330f729Sjoerg                 llvm::sys::Process::StandardErrHasColors());
1937330f729Sjoerg     }
1947330f729Sjoerg   }
1957330f729Sjoerg };
1967330f729Sjoerg }
1977330f729Sjoerg 
registerCFGDumper(CheckerManager & mgr)1987330f729Sjoerg void ento::registerCFGDumper(CheckerManager &mgr) {
1997330f729Sjoerg   mgr.registerChecker<CFGDumper>();
2007330f729Sjoerg }
2017330f729Sjoerg 
shouldRegisterCFGDumper(const CheckerManager & mgr)202*e038c9c4Sjoerg bool ento::shouldRegisterCFGDumper(const CheckerManager &mgr) {
2037330f729Sjoerg   return true;
2047330f729Sjoerg }
2057330f729Sjoerg 
2067330f729Sjoerg //===----------------------------------------------------------------------===//
2077330f729Sjoerg // CallGraphViewer
2087330f729Sjoerg //===----------------------------------------------------------------------===//
2097330f729Sjoerg 
2107330f729Sjoerg namespace {
2117330f729Sjoerg class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
2127330f729Sjoerg public:
checkASTDecl(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const2137330f729Sjoerg   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
2147330f729Sjoerg                     BugReporter &BR) const {
2157330f729Sjoerg     CallGraph CG;
2167330f729Sjoerg     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
2177330f729Sjoerg     CG.viewGraph();
2187330f729Sjoerg   }
2197330f729Sjoerg };
2207330f729Sjoerg }
2217330f729Sjoerg 
registerCallGraphViewer(CheckerManager & mgr)2227330f729Sjoerg void ento::registerCallGraphViewer(CheckerManager &mgr) {
2237330f729Sjoerg   mgr.registerChecker<CallGraphViewer>();
2247330f729Sjoerg }
2257330f729Sjoerg 
shouldRegisterCallGraphViewer(const CheckerManager & mgr)226*e038c9c4Sjoerg bool ento::shouldRegisterCallGraphViewer(const CheckerManager &mgr) {
2277330f729Sjoerg   return true;
2287330f729Sjoerg }
2297330f729Sjoerg 
2307330f729Sjoerg //===----------------------------------------------------------------------===//
2317330f729Sjoerg // CallGraphDumper
2327330f729Sjoerg //===----------------------------------------------------------------------===//
2337330f729Sjoerg 
2347330f729Sjoerg namespace {
2357330f729Sjoerg class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
2367330f729Sjoerg public:
checkASTDecl(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const2377330f729Sjoerg   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
2387330f729Sjoerg                     BugReporter &BR) const {
2397330f729Sjoerg     CallGraph CG;
2407330f729Sjoerg     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
2417330f729Sjoerg     CG.dump();
2427330f729Sjoerg   }
2437330f729Sjoerg };
2447330f729Sjoerg }
2457330f729Sjoerg 
registerCallGraphDumper(CheckerManager & mgr)2467330f729Sjoerg void ento::registerCallGraphDumper(CheckerManager &mgr) {
2477330f729Sjoerg   mgr.registerChecker<CallGraphDumper>();
2487330f729Sjoerg }
2497330f729Sjoerg 
shouldRegisterCallGraphDumper(const CheckerManager & mgr)250*e038c9c4Sjoerg bool ento::shouldRegisterCallGraphDumper(const CheckerManager &mgr) {
2517330f729Sjoerg   return true;
2527330f729Sjoerg }
2537330f729Sjoerg 
2547330f729Sjoerg //===----------------------------------------------------------------------===//
2557330f729Sjoerg // ConfigDumper
2567330f729Sjoerg //===----------------------------------------------------------------------===//
2577330f729Sjoerg 
2587330f729Sjoerg namespace {
2597330f729Sjoerg class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
2607330f729Sjoerg   typedef AnalyzerOptions::ConfigTable Table;
2617330f729Sjoerg 
compareEntry(const Table::MapEntryTy * const * LHS,const Table::MapEntryTy * const * RHS)2627330f729Sjoerg   static int compareEntry(const Table::MapEntryTy *const *LHS,
2637330f729Sjoerg                           const Table::MapEntryTy *const *RHS) {
2647330f729Sjoerg     return (*LHS)->getKey().compare((*RHS)->getKey());
2657330f729Sjoerg   }
2667330f729Sjoerg 
2677330f729Sjoerg public:
checkEndOfTranslationUnit(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const2687330f729Sjoerg   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
2697330f729Sjoerg                                  AnalysisManager& mgr,
2707330f729Sjoerg                                  BugReporter &BR) const {
2717330f729Sjoerg     const Table &Config = mgr.options.Config;
2727330f729Sjoerg 
2737330f729Sjoerg     SmallVector<const Table::MapEntryTy *, 32> Keys;
2747330f729Sjoerg     for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
2757330f729Sjoerg          ++I)
2767330f729Sjoerg       Keys.push_back(&*I);
2777330f729Sjoerg     llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
2787330f729Sjoerg 
2797330f729Sjoerg     llvm::errs() << "[config]\n";
2807330f729Sjoerg     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
2817330f729Sjoerg       llvm::errs() << Keys[I]->getKey() << " = "
2827330f729Sjoerg                    << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
2837330f729Sjoerg                    << '\n';
2847330f729Sjoerg   }
2857330f729Sjoerg };
2867330f729Sjoerg }
2877330f729Sjoerg 
registerConfigDumper(CheckerManager & mgr)2887330f729Sjoerg void ento::registerConfigDumper(CheckerManager &mgr) {
2897330f729Sjoerg   mgr.registerChecker<ConfigDumper>();
2907330f729Sjoerg }
2917330f729Sjoerg 
shouldRegisterConfigDumper(const CheckerManager & mgr)292*e038c9c4Sjoerg bool ento::shouldRegisterConfigDumper(const CheckerManager &mgr) {
2937330f729Sjoerg   return true;
2947330f729Sjoerg }
2957330f729Sjoerg 
2967330f729Sjoerg //===----------------------------------------------------------------------===//
2977330f729Sjoerg // ExplodedGraph Viewer
2987330f729Sjoerg //===----------------------------------------------------------------------===//
2997330f729Sjoerg 
3007330f729Sjoerg namespace {
3017330f729Sjoerg class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
3027330f729Sjoerg public:
ExplodedGraphViewer()3037330f729Sjoerg   ExplodedGraphViewer() {}
checkEndAnalysis(ExplodedGraph & G,BugReporter & B,ExprEngine & Eng) const3047330f729Sjoerg   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
3057330f729Sjoerg     Eng.ViewGraph(0);
3067330f729Sjoerg   }
3077330f729Sjoerg };
3087330f729Sjoerg 
3097330f729Sjoerg }
3107330f729Sjoerg 
registerExplodedGraphViewer(CheckerManager & mgr)3117330f729Sjoerg void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
3127330f729Sjoerg   mgr.registerChecker<ExplodedGraphViewer>();
3137330f729Sjoerg }
3147330f729Sjoerg 
shouldRegisterExplodedGraphViewer(const CheckerManager & mgr)315*e038c9c4Sjoerg bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager &mgr) {
3167330f729Sjoerg   return true;
3177330f729Sjoerg }
3187330f729Sjoerg 
3197330f729Sjoerg //===----------------------------------------------------------------------===//
3207330f729Sjoerg // Emits a report for every Stmt that the analyzer visits.
3217330f729Sjoerg //===----------------------------------------------------------------------===//
3227330f729Sjoerg 
3237330f729Sjoerg namespace {
3247330f729Sjoerg 
3257330f729Sjoerg class ReportStmts : public Checker<check::PreStmt<Stmt>> {
3267330f729Sjoerg   BuiltinBug BT_stmtLoc{this, "Statement"};
3277330f729Sjoerg 
3287330f729Sjoerg public:
checkPreStmt(const Stmt * S,CheckerContext & C) const3297330f729Sjoerg   void checkPreStmt(const Stmt *S, CheckerContext &C) const {
3307330f729Sjoerg     ExplodedNode *Node = C.generateNonFatalErrorNode();
3317330f729Sjoerg     if (!Node)
3327330f729Sjoerg       return;
3337330f729Sjoerg 
3347330f729Sjoerg     auto Report =
3357330f729Sjoerg         std::make_unique<PathSensitiveBugReport>(BT_stmtLoc, "Statement", Node);
3367330f729Sjoerg 
3377330f729Sjoerg     C.emitReport(std::move(Report));
3387330f729Sjoerg   }
3397330f729Sjoerg };
3407330f729Sjoerg 
3417330f729Sjoerg } // end of anonymous namespace
3427330f729Sjoerg 
registerReportStmts(CheckerManager & mgr)3437330f729Sjoerg void ento::registerReportStmts(CheckerManager &mgr) {
3447330f729Sjoerg   mgr.registerChecker<ReportStmts>();
3457330f729Sjoerg }
3467330f729Sjoerg 
shouldRegisterReportStmts(const CheckerManager & mgr)347*e038c9c4Sjoerg bool ento::shouldRegisterReportStmts(const CheckerManager &mgr) {
3487330f729Sjoerg   return true;
3497330f729Sjoerg }
350