1e5dd7070Spatrick //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick //  This file defines checkers that display debugging information.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick 
13e5dd7070Spatrick #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
14e5dd7070Spatrick #include "clang/Analysis/Analyses/Dominators.h"
15e5dd7070Spatrick #include "clang/Analysis/Analyses/LiveVariables.h"
16e5dd7070Spatrick #include "clang/Analysis/CallGraph.h"
17e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/Checker.h"
18e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
19e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
20e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
22e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
23e5dd7070Spatrick #include "llvm/Support/Process.h"
24e5dd7070Spatrick 
25e5dd7070Spatrick using namespace clang;
26e5dd7070Spatrick using namespace ento;
27e5dd7070Spatrick 
28e5dd7070Spatrick //===----------------------------------------------------------------------===//
29e5dd7070Spatrick // DominatorsTreeDumper
30e5dd7070Spatrick //===----------------------------------------------------------------------===//
31e5dd7070Spatrick 
32e5dd7070Spatrick namespace {
33e5dd7070Spatrick class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
34e5dd7070Spatrick public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const35e5dd7070Spatrick   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
36e5dd7070Spatrick                         BugReporter &BR) const {
37e5dd7070Spatrick     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
38e5dd7070Spatrick       CFGDomTree Dom;
39e5dd7070Spatrick       Dom.buildDominatorTree(AC->getCFG());
40e5dd7070Spatrick       Dom.dump();
41e5dd7070Spatrick     }
42e5dd7070Spatrick   }
43e5dd7070Spatrick };
44e5dd7070Spatrick }
45e5dd7070Spatrick 
registerDominatorsTreeDumper(CheckerManager & mgr)46e5dd7070Spatrick void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
47e5dd7070Spatrick   mgr.registerChecker<DominatorsTreeDumper>();
48e5dd7070Spatrick }
49e5dd7070Spatrick 
shouldRegisterDominatorsTreeDumper(const CheckerManager & mgr)50ec727ea7Spatrick bool ento::shouldRegisterDominatorsTreeDumper(const CheckerManager &mgr) {
51e5dd7070Spatrick   return true;
52e5dd7070Spatrick }
53e5dd7070Spatrick 
54e5dd7070Spatrick //===----------------------------------------------------------------------===//
55e5dd7070Spatrick // PostDominatorsTreeDumper
56e5dd7070Spatrick //===----------------------------------------------------------------------===//
57e5dd7070Spatrick 
58e5dd7070Spatrick namespace {
59e5dd7070Spatrick class PostDominatorsTreeDumper : public Checker<check::ASTCodeBody> {
60e5dd7070Spatrick public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const61e5dd7070Spatrick   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
62e5dd7070Spatrick                         BugReporter &BR) const {
63e5dd7070Spatrick     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
64e5dd7070Spatrick       CFGPostDomTree Dom;
65e5dd7070Spatrick       Dom.buildDominatorTree(AC->getCFG());
66e5dd7070Spatrick       Dom.dump();
67e5dd7070Spatrick     }
68e5dd7070Spatrick   }
69e5dd7070Spatrick };
70e5dd7070Spatrick }
71e5dd7070Spatrick 
registerPostDominatorsTreeDumper(CheckerManager & mgr)72e5dd7070Spatrick void ento::registerPostDominatorsTreeDumper(CheckerManager &mgr) {
73e5dd7070Spatrick   mgr.registerChecker<PostDominatorsTreeDumper>();
74e5dd7070Spatrick }
75e5dd7070Spatrick 
shouldRegisterPostDominatorsTreeDumper(const CheckerManager & mgr)76ec727ea7Spatrick bool ento::shouldRegisterPostDominatorsTreeDumper(const CheckerManager &mgr) {
77e5dd7070Spatrick   return true;
78e5dd7070Spatrick }
79e5dd7070Spatrick 
80e5dd7070Spatrick //===----------------------------------------------------------------------===//
81e5dd7070Spatrick // ControlDependencyTreeDumper
82e5dd7070Spatrick //===----------------------------------------------------------------------===//
83e5dd7070Spatrick 
84e5dd7070Spatrick namespace {
85e5dd7070Spatrick class ControlDependencyTreeDumper : public Checker<check::ASTCodeBody> {
86e5dd7070Spatrick public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const87e5dd7070Spatrick   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
88e5dd7070Spatrick                         BugReporter &BR) const {
89e5dd7070Spatrick     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
90e5dd7070Spatrick       ControlDependencyCalculator Dom(AC->getCFG());
91e5dd7070Spatrick       Dom.dump();
92e5dd7070Spatrick     }
93e5dd7070Spatrick   }
94e5dd7070Spatrick };
95e5dd7070Spatrick }
96e5dd7070Spatrick 
registerControlDependencyTreeDumper(CheckerManager & mgr)97e5dd7070Spatrick void ento::registerControlDependencyTreeDumper(CheckerManager &mgr) {
98e5dd7070Spatrick   mgr.registerChecker<ControlDependencyTreeDumper>();
99e5dd7070Spatrick }
100e5dd7070Spatrick 
shouldRegisterControlDependencyTreeDumper(const CheckerManager & mgr)101ec727ea7Spatrick bool ento::shouldRegisterControlDependencyTreeDumper(const CheckerManager &mgr) {
102e5dd7070Spatrick   return true;
103e5dd7070Spatrick }
104e5dd7070Spatrick 
105e5dd7070Spatrick //===----------------------------------------------------------------------===//
106e5dd7070Spatrick // LiveVariablesDumper
107e5dd7070Spatrick //===----------------------------------------------------------------------===//
108e5dd7070Spatrick 
109e5dd7070Spatrick namespace {
110e5dd7070Spatrick class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
111e5dd7070Spatrick public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const112e5dd7070Spatrick   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
113e5dd7070Spatrick                         BugReporter &BR) const {
114e5dd7070Spatrick     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
115e5dd7070Spatrick       L->dumpBlockLiveness(mgr.getSourceManager());
116e5dd7070Spatrick     }
117e5dd7070Spatrick   }
118e5dd7070Spatrick };
119e5dd7070Spatrick }
120e5dd7070Spatrick 
registerLiveVariablesDumper(CheckerManager & mgr)121e5dd7070Spatrick void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
122e5dd7070Spatrick   mgr.registerChecker<LiveVariablesDumper>();
123e5dd7070Spatrick }
124e5dd7070Spatrick 
shouldRegisterLiveVariablesDumper(const CheckerManager & mgr)125ec727ea7Spatrick bool ento::shouldRegisterLiveVariablesDumper(const CheckerManager &mgr) {
126e5dd7070Spatrick   return true;
127e5dd7070Spatrick }
128e5dd7070Spatrick 
129e5dd7070Spatrick //===----------------------------------------------------------------------===//
130e5dd7070Spatrick // LiveStatementsDumper
131e5dd7070Spatrick //===----------------------------------------------------------------------===//
132e5dd7070Spatrick 
133e5dd7070Spatrick namespace {
134a9ac8606Spatrick class LiveExpressionsDumper : public Checker<check::ASTCodeBody> {
135e5dd7070Spatrick public:
checkASTCodeBody(const Decl * D,AnalysisManager & Mgr,BugReporter & BR) const136e5dd7070Spatrick   void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
137e5dd7070Spatrick                         BugReporter &BR) const {
138e5dd7070Spatrick     if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))
139a9ac8606Spatrick       L->dumpExprLiveness(Mgr.getSourceManager());
140e5dd7070Spatrick   }
141e5dd7070Spatrick };
142e5dd7070Spatrick }
143e5dd7070Spatrick 
registerLiveExpressionsDumper(CheckerManager & mgr)144a9ac8606Spatrick void ento::registerLiveExpressionsDumper(CheckerManager &mgr) {
145a9ac8606Spatrick   mgr.registerChecker<LiveExpressionsDumper>();
146e5dd7070Spatrick }
147e5dd7070Spatrick 
shouldRegisterLiveExpressionsDumper(const CheckerManager & mgr)148a9ac8606Spatrick bool ento::shouldRegisterLiveExpressionsDumper(const CheckerManager &mgr) {
149e5dd7070Spatrick   return true;
150e5dd7070Spatrick }
151e5dd7070Spatrick 
152e5dd7070Spatrick //===----------------------------------------------------------------------===//
153e5dd7070Spatrick // CFGViewer
154e5dd7070Spatrick //===----------------------------------------------------------------------===//
155e5dd7070Spatrick 
156e5dd7070Spatrick namespace {
157e5dd7070Spatrick class CFGViewer : public Checker<check::ASTCodeBody> {
158e5dd7070Spatrick public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const159e5dd7070Spatrick   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
160e5dd7070Spatrick                         BugReporter &BR) const {
161e5dd7070Spatrick     if (CFG *cfg = mgr.getCFG(D)) {
162e5dd7070Spatrick       cfg->viewCFG(mgr.getLangOpts());
163e5dd7070Spatrick     }
164e5dd7070Spatrick   }
165e5dd7070Spatrick };
166e5dd7070Spatrick }
167e5dd7070Spatrick 
registerCFGViewer(CheckerManager & mgr)168e5dd7070Spatrick void ento::registerCFGViewer(CheckerManager &mgr) {
169e5dd7070Spatrick   mgr.registerChecker<CFGViewer>();
170e5dd7070Spatrick }
171e5dd7070Spatrick 
shouldRegisterCFGViewer(const CheckerManager & mgr)172ec727ea7Spatrick bool ento::shouldRegisterCFGViewer(const CheckerManager &mgr) {
173e5dd7070Spatrick   return true;
174e5dd7070Spatrick }
175e5dd7070Spatrick 
176e5dd7070Spatrick //===----------------------------------------------------------------------===//
177e5dd7070Spatrick // CFGDumper
178e5dd7070Spatrick //===----------------------------------------------------------------------===//
179e5dd7070Spatrick 
180e5dd7070Spatrick namespace {
181e5dd7070Spatrick class CFGDumper : public Checker<check::ASTCodeBody> {
182e5dd7070Spatrick public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const183e5dd7070Spatrick   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
184e5dd7070Spatrick                         BugReporter &BR) const {
185e5dd7070Spatrick     PrintingPolicy Policy(mgr.getLangOpts());
186e5dd7070Spatrick     Policy.TerseOutput = true;
187e5dd7070Spatrick     Policy.PolishForDeclaration = true;
188e5dd7070Spatrick     D->print(llvm::errs(), Policy);
189e5dd7070Spatrick 
190e5dd7070Spatrick     if (CFG *cfg = mgr.getCFG(D)) {
191e5dd7070Spatrick       cfg->dump(mgr.getLangOpts(),
192e5dd7070Spatrick                 llvm::sys::Process::StandardErrHasColors());
193e5dd7070Spatrick     }
194e5dd7070Spatrick   }
195e5dd7070Spatrick };
196e5dd7070Spatrick }
197e5dd7070Spatrick 
registerCFGDumper(CheckerManager & mgr)198e5dd7070Spatrick void ento::registerCFGDumper(CheckerManager &mgr) {
199e5dd7070Spatrick   mgr.registerChecker<CFGDumper>();
200e5dd7070Spatrick }
201e5dd7070Spatrick 
shouldRegisterCFGDumper(const CheckerManager & mgr)202ec727ea7Spatrick bool ento::shouldRegisterCFGDumper(const CheckerManager &mgr) {
203e5dd7070Spatrick   return true;
204e5dd7070Spatrick }
205e5dd7070Spatrick 
206e5dd7070Spatrick //===----------------------------------------------------------------------===//
207e5dd7070Spatrick // CallGraphViewer
208e5dd7070Spatrick //===----------------------------------------------------------------------===//
209e5dd7070Spatrick 
210e5dd7070Spatrick namespace {
211e5dd7070Spatrick class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
212e5dd7070Spatrick public:
checkASTDecl(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const213e5dd7070Spatrick   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
214e5dd7070Spatrick                     BugReporter &BR) const {
215e5dd7070Spatrick     CallGraph CG;
216e5dd7070Spatrick     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
217e5dd7070Spatrick     CG.viewGraph();
218e5dd7070Spatrick   }
219e5dd7070Spatrick };
220e5dd7070Spatrick }
221e5dd7070Spatrick 
registerCallGraphViewer(CheckerManager & mgr)222e5dd7070Spatrick void ento::registerCallGraphViewer(CheckerManager &mgr) {
223e5dd7070Spatrick   mgr.registerChecker<CallGraphViewer>();
224e5dd7070Spatrick }
225e5dd7070Spatrick 
shouldRegisterCallGraphViewer(const CheckerManager & mgr)226ec727ea7Spatrick bool ento::shouldRegisterCallGraphViewer(const CheckerManager &mgr) {
227e5dd7070Spatrick   return true;
228e5dd7070Spatrick }
229e5dd7070Spatrick 
230e5dd7070Spatrick //===----------------------------------------------------------------------===//
231e5dd7070Spatrick // CallGraphDumper
232e5dd7070Spatrick //===----------------------------------------------------------------------===//
233e5dd7070Spatrick 
234e5dd7070Spatrick namespace {
235e5dd7070Spatrick class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
236e5dd7070Spatrick public:
checkASTDecl(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const237e5dd7070Spatrick   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
238e5dd7070Spatrick                     BugReporter &BR) const {
239e5dd7070Spatrick     CallGraph CG;
240e5dd7070Spatrick     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
241e5dd7070Spatrick     CG.dump();
242e5dd7070Spatrick   }
243e5dd7070Spatrick };
244e5dd7070Spatrick }
245e5dd7070Spatrick 
registerCallGraphDumper(CheckerManager & mgr)246e5dd7070Spatrick void ento::registerCallGraphDumper(CheckerManager &mgr) {
247e5dd7070Spatrick   mgr.registerChecker<CallGraphDumper>();
248e5dd7070Spatrick }
249e5dd7070Spatrick 
shouldRegisterCallGraphDumper(const CheckerManager & mgr)250ec727ea7Spatrick bool ento::shouldRegisterCallGraphDumper(const CheckerManager &mgr) {
251e5dd7070Spatrick   return true;
252e5dd7070Spatrick }
253e5dd7070Spatrick 
254e5dd7070Spatrick //===----------------------------------------------------------------------===//
255e5dd7070Spatrick // ConfigDumper
256e5dd7070Spatrick //===----------------------------------------------------------------------===//
257e5dd7070Spatrick 
258e5dd7070Spatrick namespace {
259e5dd7070Spatrick class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
260e5dd7070Spatrick   typedef AnalyzerOptions::ConfigTable Table;
261e5dd7070Spatrick 
compareEntry(const Table::MapEntryTy * const * LHS,const Table::MapEntryTy * const * RHS)262e5dd7070Spatrick   static int compareEntry(const Table::MapEntryTy *const *LHS,
263e5dd7070Spatrick                           const Table::MapEntryTy *const *RHS) {
264e5dd7070Spatrick     return (*LHS)->getKey().compare((*RHS)->getKey());
265e5dd7070Spatrick   }
266e5dd7070Spatrick 
267e5dd7070Spatrick public:
checkEndOfTranslationUnit(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const268e5dd7070Spatrick   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
269e5dd7070Spatrick                                  AnalysisManager& mgr,
270e5dd7070Spatrick                                  BugReporter &BR) const {
271e5dd7070Spatrick     const Table &Config = mgr.options.Config;
272e5dd7070Spatrick 
273e5dd7070Spatrick     SmallVector<const Table::MapEntryTy *, 32> Keys;
274e5dd7070Spatrick     for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
275e5dd7070Spatrick          ++I)
276e5dd7070Spatrick       Keys.push_back(&*I);
277e5dd7070Spatrick     llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
278e5dd7070Spatrick 
279e5dd7070Spatrick     llvm::errs() << "[config]\n";
280e5dd7070Spatrick     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
281e5dd7070Spatrick       llvm::errs() << Keys[I]->getKey() << " = "
282e5dd7070Spatrick                    << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
283e5dd7070Spatrick                    << '\n';
284e5dd7070Spatrick   }
285e5dd7070Spatrick };
286e5dd7070Spatrick }
287e5dd7070Spatrick 
registerConfigDumper(CheckerManager & mgr)288e5dd7070Spatrick void ento::registerConfigDumper(CheckerManager &mgr) {
289e5dd7070Spatrick   mgr.registerChecker<ConfigDumper>();
290e5dd7070Spatrick }
291e5dd7070Spatrick 
shouldRegisterConfigDumper(const CheckerManager & mgr)292ec727ea7Spatrick bool ento::shouldRegisterConfigDumper(const CheckerManager &mgr) {
293e5dd7070Spatrick   return true;
294e5dd7070Spatrick }
295e5dd7070Spatrick 
296e5dd7070Spatrick //===----------------------------------------------------------------------===//
297e5dd7070Spatrick // ExplodedGraph Viewer
298e5dd7070Spatrick //===----------------------------------------------------------------------===//
299e5dd7070Spatrick 
300e5dd7070Spatrick namespace {
301e5dd7070Spatrick class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
302e5dd7070Spatrick public:
ExplodedGraphViewer()303e5dd7070Spatrick   ExplodedGraphViewer() {}
checkEndAnalysis(ExplodedGraph & G,BugReporter & B,ExprEngine & Eng) const304e5dd7070Spatrick   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
305*12c85518Srobert     Eng.ViewGraph(false);
306e5dd7070Spatrick   }
307e5dd7070Spatrick };
308e5dd7070Spatrick 
309e5dd7070Spatrick }
310e5dd7070Spatrick 
registerExplodedGraphViewer(CheckerManager & mgr)311e5dd7070Spatrick void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
312e5dd7070Spatrick   mgr.registerChecker<ExplodedGraphViewer>();
313e5dd7070Spatrick }
314e5dd7070Spatrick 
shouldRegisterExplodedGraphViewer(const CheckerManager & mgr)315ec727ea7Spatrick bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager &mgr) {
316e5dd7070Spatrick   return true;
317e5dd7070Spatrick }
318e5dd7070Spatrick 
319e5dd7070Spatrick //===----------------------------------------------------------------------===//
320e5dd7070Spatrick // Emits a report for every Stmt that the analyzer visits.
321e5dd7070Spatrick //===----------------------------------------------------------------------===//
322e5dd7070Spatrick 
323e5dd7070Spatrick namespace {
324e5dd7070Spatrick 
325e5dd7070Spatrick class ReportStmts : public Checker<check::PreStmt<Stmt>> {
326e5dd7070Spatrick   BuiltinBug BT_stmtLoc{this, "Statement"};
327e5dd7070Spatrick 
328e5dd7070Spatrick public:
checkPreStmt(const Stmt * S,CheckerContext & C) const329e5dd7070Spatrick   void checkPreStmt(const Stmt *S, CheckerContext &C) const {
330e5dd7070Spatrick     ExplodedNode *Node = C.generateNonFatalErrorNode();
331e5dd7070Spatrick     if (!Node)
332e5dd7070Spatrick       return;
333e5dd7070Spatrick 
334e5dd7070Spatrick     auto Report =
335e5dd7070Spatrick         std::make_unique<PathSensitiveBugReport>(BT_stmtLoc, "Statement", Node);
336e5dd7070Spatrick 
337e5dd7070Spatrick     C.emitReport(std::move(Report));
338e5dd7070Spatrick   }
339e5dd7070Spatrick };
340e5dd7070Spatrick 
341e5dd7070Spatrick } // end of anonymous namespace
342e5dd7070Spatrick 
registerReportStmts(CheckerManager & mgr)343e5dd7070Spatrick void ento::registerReportStmts(CheckerManager &mgr) {
344e5dd7070Spatrick   mgr.registerChecker<ReportStmts>();
345e5dd7070Spatrick }
346e5dd7070Spatrick 
shouldRegisterReportStmts(const CheckerManager & mgr)347ec727ea7Spatrick bool ento::shouldRegisterReportStmts(const CheckerManager &mgr) {
348e5dd7070Spatrick   return true;
349e5dd7070Spatrick }
350