157d736fdSArgyrios Kyrtzidis //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
257d736fdSArgyrios Kyrtzidis //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler 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)) {
38*71a9dc39SKristof Umann       CFGDomTree dom;
39*71a9dc39SKristof Umann       dom.buildDominatorTree(AC->getCFG());
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 
50058a7a45SKristof Umann bool ento::shouldRegisterDominatorsTreeDumper(const LangOptions &LO) {
51058a7a45SKristof Umann   return true;
52058a7a45SKristof Umann }
53058a7a45SKristof Umann 
540062e749STed Kremenek //===----------------------------------------------------------------------===//
55*71a9dc39SKristof Umann // PostDominatorsTreeDumper
56*71a9dc39SKristof Umann //===----------------------------------------------------------------------===//
57*71a9dc39SKristof Umann 
58*71a9dc39SKristof Umann namespace {
59*71a9dc39SKristof Umann class PostDominatorsTreeDumper : public Checker<check::ASTCodeBody> {
60*71a9dc39SKristof Umann public:
61*71a9dc39SKristof Umann   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
62*71a9dc39SKristof Umann                         BugReporter &BR) const {
63*71a9dc39SKristof Umann     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
64*71a9dc39SKristof Umann       CFGPostDomTree dom;
65*71a9dc39SKristof Umann       dom.buildDominatorTree(AC->getCFG());
66*71a9dc39SKristof Umann       dom.dump();
67*71a9dc39SKristof Umann     }
68*71a9dc39SKristof Umann   }
69*71a9dc39SKristof Umann };
70*71a9dc39SKristof Umann }
71*71a9dc39SKristof Umann 
72*71a9dc39SKristof Umann void ento::registerPostDominatorsTreeDumper(CheckerManager &mgr) {
73*71a9dc39SKristof Umann   mgr.registerChecker<PostDominatorsTreeDumper>();
74*71a9dc39SKristof Umann }
75*71a9dc39SKristof Umann 
76*71a9dc39SKristof Umann bool ento::shouldRegisterPostDominatorsTreeDumper(const LangOptions &LO) {
77*71a9dc39SKristof Umann   return true;
78*71a9dc39SKristof Umann }
79*71a9dc39SKristof Umann 
80*71a9dc39SKristof Umann //===----------------------------------------------------------------------===//
8157d736fdSArgyrios Kyrtzidis // LiveVariablesDumper
8257d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
8357d736fdSArgyrios Kyrtzidis 
8457d736fdSArgyrios Kyrtzidis namespace {
856a5674ffSArgyrios Kyrtzidis class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
8657d736fdSArgyrios Kyrtzidis public:
8757d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
8857d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
89dccc2b22STed Kremenek     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
9057d736fdSArgyrios Kyrtzidis       L->dumpBlockLiveness(mgr.getSourceManager());
9157d736fdSArgyrios Kyrtzidis     }
9257d736fdSArgyrios Kyrtzidis   }
9357d736fdSArgyrios Kyrtzidis };
94ab9db510SAlexander Kornienko }
9557d736fdSArgyrios Kyrtzidis 
9657d736fdSArgyrios Kyrtzidis void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
9757d736fdSArgyrios Kyrtzidis   mgr.registerChecker<LiveVariablesDumper>();
9857d736fdSArgyrios Kyrtzidis }
9957d736fdSArgyrios Kyrtzidis 
100058a7a45SKristof Umann bool ento::shouldRegisterLiveVariablesDumper(const LangOptions &LO) {
101058a7a45SKristof Umann   return true;
102058a7a45SKristof Umann }
103058a7a45SKristof Umann 
10457d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
105dda42164SArtem Dergachev // LiveStatementsDumper
106dda42164SArtem Dergachev //===----------------------------------------------------------------------===//
107dda42164SArtem Dergachev 
108dda42164SArtem Dergachev namespace {
109dda42164SArtem Dergachev class LiveStatementsDumper : public Checker<check::ASTCodeBody> {
110dda42164SArtem Dergachev public:
111dda42164SArtem Dergachev   void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
112dda42164SArtem Dergachev                         BugReporter &BR) const {
113dda42164SArtem Dergachev     if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))
114dda42164SArtem Dergachev       L->dumpStmtLiveness(Mgr.getSourceManager());
115dda42164SArtem Dergachev   }
116dda42164SArtem Dergachev };
117dda42164SArtem Dergachev }
118dda42164SArtem Dergachev 
119dda42164SArtem Dergachev void ento::registerLiveStatementsDumper(CheckerManager &mgr) {
120dda42164SArtem Dergachev   mgr.registerChecker<LiveStatementsDumper>();
121dda42164SArtem Dergachev }
122dda42164SArtem Dergachev 
123058a7a45SKristof Umann bool ento::shouldRegisterLiveStatementsDumper(const LangOptions &LO) {
124058a7a45SKristof Umann   return true;
125058a7a45SKristof Umann }
126058a7a45SKristof Umann 
127dda42164SArtem Dergachev //===----------------------------------------------------------------------===//
12857d736fdSArgyrios Kyrtzidis // CFGViewer
12957d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
13057d736fdSArgyrios Kyrtzidis 
13157d736fdSArgyrios Kyrtzidis namespace {
1326a5674ffSArgyrios Kyrtzidis class CFGViewer : public Checker<check::ASTCodeBody> {
13357d736fdSArgyrios Kyrtzidis public:
13457d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
13557d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
13657d736fdSArgyrios Kyrtzidis     if (CFG *cfg = mgr.getCFG(D)) {
137bbafb8a7SDavid Blaikie       cfg->viewCFG(mgr.getLangOpts());
13857d736fdSArgyrios Kyrtzidis     }
13957d736fdSArgyrios Kyrtzidis   }
14057d736fdSArgyrios Kyrtzidis };
141ab9db510SAlexander Kornienko }
14257d736fdSArgyrios Kyrtzidis 
14357d736fdSArgyrios Kyrtzidis void ento::registerCFGViewer(CheckerManager &mgr) {
14457d736fdSArgyrios Kyrtzidis   mgr.registerChecker<CFGViewer>();
14557d736fdSArgyrios Kyrtzidis }
14657d736fdSArgyrios Kyrtzidis 
147058a7a45SKristof Umann bool ento::shouldRegisterCFGViewer(const LangOptions &LO) {
148058a7a45SKristof Umann   return true;
149058a7a45SKristof Umann }
150058a7a45SKristof Umann 
15157d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
15257d736fdSArgyrios Kyrtzidis // CFGDumper
15357d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
15457d736fdSArgyrios Kyrtzidis 
15557d736fdSArgyrios Kyrtzidis namespace {
1566a5674ffSArgyrios Kyrtzidis class CFGDumper : public Checker<check::ASTCodeBody> {
15757d736fdSArgyrios Kyrtzidis public:
15857d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
15957d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
160e02e96a6SJordan Rose     PrintingPolicy Policy(mgr.getLangOpts());
161e02e96a6SJordan Rose     Policy.TerseOutput = true;
162e02e96a6SJordan Rose     Policy.PolishForDeclaration = true;
163e02e96a6SJordan Rose     D->print(llvm::errs(), Policy);
164e02e96a6SJordan Rose 
16557d736fdSArgyrios Kyrtzidis     if (CFG *cfg = mgr.getCFG(D)) {
166bbafb8a7SDavid Blaikie       cfg->dump(mgr.getLangOpts(),
16772be32afSTed Kremenek                 llvm::sys::Process::StandardErrHasColors());
16857d736fdSArgyrios Kyrtzidis     }
16957d736fdSArgyrios Kyrtzidis   }
17057d736fdSArgyrios Kyrtzidis };
171ab9db510SAlexander Kornienko }
17257d736fdSArgyrios Kyrtzidis 
17357d736fdSArgyrios Kyrtzidis void ento::registerCFGDumper(CheckerManager &mgr) {
17457d736fdSArgyrios Kyrtzidis   mgr.registerChecker<CFGDumper>();
17557d736fdSArgyrios Kyrtzidis }
176c000e7edSAnna Zaks 
177058a7a45SKristof Umann bool ento::shouldRegisterCFGDumper(const LangOptions &LO) {
178058a7a45SKristof Umann   return true;
179058a7a45SKristof Umann }
180058a7a45SKristof Umann 
181c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
182c000e7edSAnna Zaks // CallGraphViewer
183c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
184c000e7edSAnna Zaks 
185c000e7edSAnna Zaks namespace {
186c000e7edSAnna Zaks class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
187c000e7edSAnna Zaks public:
188c000e7edSAnna Zaks   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
189c000e7edSAnna Zaks                     BugReporter &BR) const {
190c000e7edSAnna Zaks     CallGraph CG;
191c000e7edSAnna Zaks     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
192c000e7edSAnna Zaks     CG.viewGraph();
193c000e7edSAnna Zaks   }
194c000e7edSAnna Zaks };
195ab9db510SAlexander Kornienko }
196c000e7edSAnna Zaks 
197c000e7edSAnna Zaks void ento::registerCallGraphViewer(CheckerManager &mgr) {
198c000e7edSAnna Zaks   mgr.registerChecker<CallGraphViewer>();
199c000e7edSAnna Zaks }
200c000e7edSAnna Zaks 
201058a7a45SKristof Umann bool ento::shouldRegisterCallGraphViewer(const LangOptions &LO) {
202058a7a45SKristof Umann   return true;
203058a7a45SKristof Umann }
204058a7a45SKristof Umann 
205c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
206c000e7edSAnna Zaks // CallGraphDumper
207c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
208c000e7edSAnna Zaks 
209c000e7edSAnna Zaks namespace {
210c000e7edSAnna Zaks class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
211c000e7edSAnna Zaks public:
212c000e7edSAnna Zaks   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
213c000e7edSAnna Zaks                     BugReporter &BR) const {
214c000e7edSAnna Zaks     CallGraph CG;
215c000e7edSAnna Zaks     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
216c000e7edSAnna Zaks     CG.dump();
217c000e7edSAnna Zaks   }
218c000e7edSAnna Zaks };
219ab9db510SAlexander Kornienko }
220c000e7edSAnna Zaks 
221c000e7edSAnna Zaks void ento::registerCallGraphDumper(CheckerManager &mgr) {
222c000e7edSAnna Zaks   mgr.registerChecker<CallGraphDumper>();
223c000e7edSAnna Zaks }
22486917fdbSTed Kremenek 
225058a7a45SKristof Umann bool ento::shouldRegisterCallGraphDumper(const LangOptions &LO) {
226058a7a45SKristof Umann   return true;
227058a7a45SKristof Umann }
22886917fdbSTed Kremenek 
22986917fdbSTed Kremenek //===----------------------------------------------------------------------===//
23086917fdbSTed Kremenek // ConfigDumper
23186917fdbSTed Kremenek //===----------------------------------------------------------------------===//
23286917fdbSTed Kremenek 
23386917fdbSTed Kremenek namespace {
23486917fdbSTed Kremenek class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
235a92b80f8SBenjamin Kramer   typedef AnalyzerOptions::ConfigTable Table;
236a92b80f8SBenjamin Kramer 
2374cadf292SBenjamin Kramer   static int compareEntry(const Table::MapEntryTy *const *LHS,
2384cadf292SBenjamin Kramer                           const Table::MapEntryTy *const *RHS) {
2394cadf292SBenjamin Kramer     return (*LHS)->getKey().compare((*RHS)->getKey());
2404cadf292SBenjamin Kramer   }
2414cadf292SBenjamin Kramer 
24286917fdbSTed Kremenek public:
24386917fdbSTed Kremenek   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
24486917fdbSTed Kremenek                                  AnalysisManager& mgr,
24586917fdbSTed Kremenek                                  BugReporter &BR) const {
246a92b80f8SBenjamin Kramer     const Table &Config = mgr.options.Config;
24786917fdbSTed Kremenek 
248a92b80f8SBenjamin Kramer     SmallVector<const Table::MapEntryTy *, 32> Keys;
249a92b80f8SBenjamin Kramer     for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
250a92b80f8SBenjamin Kramer          ++I)
251a92b80f8SBenjamin Kramer       Keys.push_back(&*I);
2524cadf292SBenjamin Kramer     llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
25386917fdbSTed Kremenek 
25486917fdbSTed Kremenek     llvm::errs() << "[config]\n";
255a92b80f8SBenjamin Kramer     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
256549f9cd4SKristof Umann       llvm::errs() << Keys[I]->getKey() << " = "
257549f9cd4SKristof Umann                    << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
258549f9cd4SKristof Umann                    << '\n';
259a92b80f8SBenjamin Kramer 
26086917fdbSTed Kremenek     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
26186917fdbSTed Kremenek   }
26286917fdbSTed Kremenek };
263ab9db510SAlexander Kornienko }
26486917fdbSTed Kremenek 
26586917fdbSTed Kremenek void ento::registerConfigDumper(CheckerManager &mgr) {
26686917fdbSTed Kremenek   mgr.registerChecker<ConfigDumper>();
26786917fdbSTed Kremenek }
2687925e3dbSAnna Zaks 
269058a7a45SKristof Umann bool ento::shouldRegisterConfigDumper(const LangOptions &LO) {
270058a7a45SKristof Umann   return true;
271058a7a45SKristof Umann }
272058a7a45SKristof Umann 
2737925e3dbSAnna Zaks //===----------------------------------------------------------------------===//
2747925e3dbSAnna Zaks // ExplodedGraph Viewer
2757925e3dbSAnna Zaks //===----------------------------------------------------------------------===//
2767925e3dbSAnna Zaks 
2777925e3dbSAnna Zaks namespace {
2787925e3dbSAnna Zaks class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
2797925e3dbSAnna Zaks public:
2807925e3dbSAnna Zaks   ExplodedGraphViewer() {}
2817925e3dbSAnna Zaks   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
2827925e3dbSAnna Zaks     Eng.ViewGraph(0);
2837925e3dbSAnna Zaks   }
2847925e3dbSAnna Zaks };
2857925e3dbSAnna Zaks 
2867925e3dbSAnna Zaks }
2877925e3dbSAnna Zaks 
2887925e3dbSAnna Zaks void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
2897925e3dbSAnna Zaks   mgr.registerChecker<ExplodedGraphViewer>();
2907925e3dbSAnna Zaks }
291efec1630SGabor Horvath 
292058a7a45SKristof Umann bool ento::shouldRegisterExplodedGraphViewer(const LangOptions &LO) {
293058a7a45SKristof Umann   return true;
294058a7a45SKristof Umann }
2954962816eSKristof Umann 
2964962816eSKristof Umann //===----------------------------------------------------------------------===//
2974962816eSKristof Umann // Emits a report for every Stmt that the analyzer visits.
2984962816eSKristof Umann //===----------------------------------------------------------------------===//
2994962816eSKristof Umann 
3004962816eSKristof Umann namespace {
3014962816eSKristof Umann 
3024962816eSKristof Umann class ReportStmts : public Checker<check::PreStmt<Stmt>> {
3034962816eSKristof Umann   BuiltinBug BT_stmtLoc{this, "Statement"};
3044962816eSKristof Umann 
3054962816eSKristof Umann public:
3064962816eSKristof Umann   void checkPreStmt(const Stmt *S, CheckerContext &C) const {
3074962816eSKristof Umann     ExplodedNode *Node = C.generateNonFatalErrorNode();
3084962816eSKristof Umann     if (!Node)
3094962816eSKristof Umann       return;
3104962816eSKristof Umann 
3114962816eSKristof Umann     auto Report = llvm::make_unique<BugReport>(BT_stmtLoc, "Statement", Node);
3124962816eSKristof Umann 
3134962816eSKristof Umann     C.emitReport(std::move(Report));
3144962816eSKristof Umann   }
3154962816eSKristof Umann };
3164962816eSKristof Umann 
3174962816eSKristof Umann } // end of anonymous namespace
3184962816eSKristof Umann 
3194962816eSKristof Umann void ento::registerReportStmts(CheckerManager &mgr) {
3204962816eSKristof Umann   mgr.registerChecker<ReportStmts>();
3214962816eSKristof Umann }
3224962816eSKristof Umann 
3234962816eSKristof Umann bool ento::shouldRegisterReportStmts(const LangOptions &LO) {
3244962816eSKristof Umann   return true;
3254962816eSKristof Umann }
326