xref: /llvm-project/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp (revision 2946cd701067404b99c39fb29dc9c74bd7193eb3)
1 //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file defines checkers that display debugging information.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
14 #include "clang/Analysis/Analyses/Dominators.h"
15 #include "clang/Analysis/Analyses/LiveVariables.h"
16 #include "clang/Analysis/CallGraph.h"
17 #include "clang/StaticAnalyzer/Core/Checker.h"
18 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
22 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
23 #include "llvm/Support/Process.h"
24 
25 using namespace clang;
26 using namespace ento;
27 
28 //===----------------------------------------------------------------------===//
29 // DominatorsTreeDumper
30 //===----------------------------------------------------------------------===//
31 
32 namespace {
33 class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
34 public:
35   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
36                         BugReporter &BR) const {
37     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
38       DominatorTree dom;
39       dom.buildDominatorTree(*AC);
40       dom.dump();
41     }
42   }
43 };
44 }
45 
46 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
47   mgr.registerChecker<DominatorsTreeDumper>();
48 }
49 
50 //===----------------------------------------------------------------------===//
51 // LiveVariablesDumper
52 //===----------------------------------------------------------------------===//
53 
54 namespace {
55 class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
56 public:
57   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
58                         BugReporter &BR) const {
59     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
60       L->dumpBlockLiveness(mgr.getSourceManager());
61     }
62   }
63 };
64 }
65 
66 void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
67   mgr.registerChecker<LiveVariablesDumper>();
68 }
69 
70 //===----------------------------------------------------------------------===//
71 // LiveStatementsDumper
72 //===----------------------------------------------------------------------===//
73 
74 namespace {
75 class LiveStatementsDumper : public Checker<check::ASTCodeBody> {
76 public:
77   void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
78                         BugReporter &BR) const {
79     if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))
80       L->dumpStmtLiveness(Mgr.getSourceManager());
81   }
82 };
83 }
84 
85 void ento::registerLiveStatementsDumper(CheckerManager &mgr) {
86   mgr.registerChecker<LiveStatementsDumper>();
87 }
88 
89 //===----------------------------------------------------------------------===//
90 // CFGViewer
91 //===----------------------------------------------------------------------===//
92 
93 namespace {
94 class CFGViewer : public Checker<check::ASTCodeBody> {
95 public:
96   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
97                         BugReporter &BR) const {
98     if (CFG *cfg = mgr.getCFG(D)) {
99       cfg->viewCFG(mgr.getLangOpts());
100     }
101   }
102 };
103 }
104 
105 void ento::registerCFGViewer(CheckerManager &mgr) {
106   mgr.registerChecker<CFGViewer>();
107 }
108 
109 //===----------------------------------------------------------------------===//
110 // CFGDumper
111 //===----------------------------------------------------------------------===//
112 
113 namespace {
114 class CFGDumper : public Checker<check::ASTCodeBody> {
115 public:
116   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
117                         BugReporter &BR) const {
118     PrintingPolicy Policy(mgr.getLangOpts());
119     Policy.TerseOutput = true;
120     Policy.PolishForDeclaration = true;
121     D->print(llvm::errs(), Policy);
122 
123     if (CFG *cfg = mgr.getCFG(D)) {
124       cfg->dump(mgr.getLangOpts(),
125                 llvm::sys::Process::StandardErrHasColors());
126     }
127   }
128 };
129 }
130 
131 void ento::registerCFGDumper(CheckerManager &mgr) {
132   mgr.registerChecker<CFGDumper>();
133 }
134 
135 //===----------------------------------------------------------------------===//
136 // CallGraphViewer
137 //===----------------------------------------------------------------------===//
138 
139 namespace {
140 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
141 public:
142   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
143                     BugReporter &BR) const {
144     CallGraph CG;
145     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
146     CG.viewGraph();
147   }
148 };
149 }
150 
151 void ento::registerCallGraphViewer(CheckerManager &mgr) {
152   mgr.registerChecker<CallGraphViewer>();
153 }
154 
155 //===----------------------------------------------------------------------===//
156 // CallGraphDumper
157 //===----------------------------------------------------------------------===//
158 
159 namespace {
160 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
161 public:
162   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
163                     BugReporter &BR) const {
164     CallGraph CG;
165     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
166     CG.dump();
167   }
168 };
169 }
170 
171 void ento::registerCallGraphDumper(CheckerManager &mgr) {
172   mgr.registerChecker<CallGraphDumper>();
173 }
174 
175 
176 //===----------------------------------------------------------------------===//
177 // ConfigDumper
178 //===----------------------------------------------------------------------===//
179 
180 namespace {
181 class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
182   typedef AnalyzerOptions::ConfigTable Table;
183 
184   static int compareEntry(const Table::MapEntryTy *const *LHS,
185                           const Table::MapEntryTy *const *RHS) {
186     return (*LHS)->getKey().compare((*RHS)->getKey());
187   }
188 
189 public:
190   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
191                                  AnalysisManager& mgr,
192                                  BugReporter &BR) const {
193     const Table &Config = mgr.options.Config;
194 
195     SmallVector<const Table::MapEntryTy *, 32> Keys;
196     for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
197          ++I)
198       Keys.push_back(&*I);
199     llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
200 
201     llvm::errs() << "[config]\n";
202     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
203       llvm::errs() << Keys[I]->getKey() << " = "
204                    << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
205                    << '\n';
206 
207     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
208   }
209 };
210 }
211 
212 void ento::registerConfigDumper(CheckerManager &mgr) {
213   mgr.registerChecker<ConfigDumper>();
214 }
215 
216 //===----------------------------------------------------------------------===//
217 // ExplodedGraph Viewer
218 //===----------------------------------------------------------------------===//
219 
220 namespace {
221 class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
222 public:
223   ExplodedGraphViewer() {}
224   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
225     Eng.ViewGraph(0);
226   }
227 };
228 
229 }
230 
231 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
232   mgr.registerChecker<ExplodedGraphViewer>();
233 }
234 
235