clang 20.0.0git
DebugCheckers.cpp
Go to the documentation of this file.
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
23#include "llvm/Support/Process.h"
24
25using namespace clang;
26using namespace ento;
27
28//===----------------------------------------------------------------------===//
29// DominatorsTreeDumper
30//===----------------------------------------------------------------------===//
31
32namespace {
33class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
34public:
35 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
36 BugReporter &BR) const {
38 CFGDomTree Dom;
39 Dom.buildDominatorTree(AC->getCFG());
40 Dom.dump();
41 }
42 }
43};
44}
45
46void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
47 mgr.registerChecker<DominatorsTreeDumper>();
48}
49
50bool ento::shouldRegisterDominatorsTreeDumper(const CheckerManager &mgr) {
51 return true;
52}
53
54//===----------------------------------------------------------------------===//
55// PostDominatorsTreeDumper
56//===----------------------------------------------------------------------===//
57
58namespace {
59class PostDominatorsTreeDumper : public Checker<check::ASTCodeBody> {
60public:
61 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
62 BugReporter &BR) const {
65 Dom.buildDominatorTree(AC->getCFG());
66 Dom.dump();
67 }
68 }
69};
70}
71
72void ento::registerPostDominatorsTreeDumper(CheckerManager &mgr) {
73 mgr.registerChecker<PostDominatorsTreeDumper>();
74}
75
76bool ento::shouldRegisterPostDominatorsTreeDumper(const CheckerManager &mgr) {
77 return true;
78}
79
80//===----------------------------------------------------------------------===//
81// ControlDependencyTreeDumper
82//===----------------------------------------------------------------------===//
83
84namespace {
85class ControlDependencyTreeDumper : public Checker<check::ASTCodeBody> {
86public:
87 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
88 BugReporter &BR) const {
90 ControlDependencyCalculator Dom(AC->getCFG());
91 Dom.dump();
92 }
93 }
94};
95}
96
97void ento::registerControlDependencyTreeDumper(CheckerManager &mgr) {
98 mgr.registerChecker<ControlDependencyTreeDumper>();
99}
100
101bool ento::shouldRegisterControlDependencyTreeDumper(const CheckerManager &mgr) {
102 return true;
103}
104
105//===----------------------------------------------------------------------===//
106// LiveVariablesDumper
107//===----------------------------------------------------------------------===//
108
109namespace {
110class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
111public:
112 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
113 BugReporter &BR) const {
114 if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
115 L->dumpBlockLiveness(mgr.getSourceManager());
116 }
117 }
118};
119}
120
121void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
122 mgr.registerChecker<LiveVariablesDumper>();
123}
124
125bool ento::shouldRegisterLiveVariablesDumper(const CheckerManager &mgr) {
126 return true;
127}
128
129//===----------------------------------------------------------------------===//
130// LiveStatementsDumper
131//===----------------------------------------------------------------------===//
132
133namespace {
134class LiveExpressionsDumper : public Checker<check::ASTCodeBody> {
135public:
136 void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
137 BugReporter &BR) const {
139 L->dumpExprLiveness(Mgr.getSourceManager());
140 }
141};
142}
143
144void ento::registerLiveExpressionsDumper(CheckerManager &mgr) {
145 mgr.registerChecker<LiveExpressionsDumper>();
146}
147
148bool ento::shouldRegisterLiveExpressionsDumper(const CheckerManager &mgr) {
149 return true;
150}
151
152//===----------------------------------------------------------------------===//
153// CFGViewer
154//===----------------------------------------------------------------------===//
155
156namespace {
157class CFGViewer : public Checker<check::ASTCodeBody> {
158public:
159 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
160 BugReporter &BR) const {
161 if (CFG *cfg = mgr.getCFG(D)) {
162 cfg->viewCFG(mgr.getLangOpts());
163 }
164 }
165};
166}
167
168void ento::registerCFGViewer(CheckerManager &mgr) {
169 mgr.registerChecker<CFGViewer>();
170}
171
172bool ento::shouldRegisterCFGViewer(const CheckerManager &mgr) {
173 return true;
174}
175
176//===----------------------------------------------------------------------===//
177// CFGDumper
178//===----------------------------------------------------------------------===//
179
180namespace {
181class CFGDumper : public Checker<check::ASTCodeBody> {
182public:
183 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
184 BugReporter &BR) const {
185 PrintingPolicy Policy(mgr.getLangOpts());
186 Policy.TerseOutput = true;
187 Policy.PolishForDeclaration = true;
188 D->print(llvm::errs(), Policy);
189
190 if (CFG *cfg = mgr.getCFG(D)) {
191 cfg->dump(mgr.getLangOpts(),
192 llvm::sys::Process::StandardErrHasColors());
193 }
194 }
195};
196}
197
198void ento::registerCFGDumper(CheckerManager &mgr) {
199 mgr.registerChecker<CFGDumper>();
200}
201
202bool ento::shouldRegisterCFGDumper(const CheckerManager &mgr) {
203 return true;
204}
205
206//===----------------------------------------------------------------------===//
207// CallGraphViewer
208//===----------------------------------------------------------------------===//
209
210namespace {
211class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
212public:
213 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
214 BugReporter &BR) const {
215 CallGraph CG;
216 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
217 CG.viewGraph();
218 }
219};
220}
221
222void ento::registerCallGraphViewer(CheckerManager &mgr) {
223 mgr.registerChecker<CallGraphViewer>();
224}
225
226bool ento::shouldRegisterCallGraphViewer(const CheckerManager &mgr) {
227 return true;
228}
229
230//===----------------------------------------------------------------------===//
231// CallGraphDumper
232//===----------------------------------------------------------------------===//
233
234namespace {
235class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
236public:
237 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
238 BugReporter &BR) const {
239 CallGraph CG;
240 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
241 CG.dump();
242 }
243};
244}
245
246void ento::registerCallGraphDumper(CheckerManager &mgr) {
247 mgr.registerChecker<CallGraphDumper>();
248}
249
250bool ento::shouldRegisterCallGraphDumper(const CheckerManager &mgr) {
251 return true;
252}
253
254//===----------------------------------------------------------------------===//
255// ConfigDumper
256//===----------------------------------------------------------------------===//
257
258namespace {
259class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
260 typedef AnalyzerOptions::ConfigTable Table;
261
262 static int compareEntry(const Table::MapEntryTy *const *LHS,
263 const Table::MapEntryTy *const *RHS) {
264 return (*LHS)->getKey().compare((*RHS)->getKey());
265 }
266
267public:
268 void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
269 AnalysisManager& mgr,
270 BugReporter &BR) const {
271 const Table &Config = mgr.options.Config;
272
274 for (const auto &Entry : Config)
275 Keys.push_back(&Entry);
276 llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
277
278 llvm::errs() << "[config]\n";
279 for (unsigned I = 0, E = Keys.size(); I != E; ++I)
280 llvm::errs() << Keys[I]->getKey() << " = "
281 << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
282 << '\n';
283 }
284};
285}
286
287void ento::registerConfigDumper(CheckerManager &mgr) {
288 mgr.registerChecker<ConfigDumper>();
289}
290
291bool ento::shouldRegisterConfigDumper(const CheckerManager &mgr) {
292 return true;
293}
294
295//===----------------------------------------------------------------------===//
296// ExplodedGraph Viewer
297//===----------------------------------------------------------------------===//
298
299namespace {
300class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
301public:
302 ExplodedGraphViewer() {}
303 void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
304 Eng.ViewGraph(false);
305 }
306};
307
308}
309
310void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
311 mgr.registerChecker<ExplodedGraphViewer>();
312}
313
314bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager &mgr) {
315 return true;
316}
317
318//===----------------------------------------------------------------------===//
319// Emits a report for every Stmt that the analyzer visits.
320//===----------------------------------------------------------------------===//
321
322namespace {
323
324class ReportStmts : public Checker<check::PreStmt<Stmt>> {
325 BugType BT_stmtLoc{this, "Statement"};
326
327public:
328 void checkPreStmt(const Stmt *S, CheckerContext &C) const {
329 ExplodedNode *Node = C.generateNonFatalErrorNode();
330 if (!Node)
331 return;
332
333 auto Report =
334 std::make_unique<PathSensitiveBugReport>(BT_stmtLoc, "Statement", Node);
335
336 C.emitReport(std::move(Report));
337 }
338};
339
340} // end of anonymous namespace
341
342void ento::registerReportStmts(CheckerManager &mgr) {
343 mgr.registerChecker<ReportStmts>();
344}
345
346bool ento::shouldRegisterReportStmts(const CheckerManager &mgr) {
347 return true;
348}
DynTypedNode Node
const Decl * D
Expr * E
AnalysisDeclContext contains the context data for the function, method or block under analysis.
ConfigTable Config
A key-value table of use-specified configuration values.
llvm::StringMap< std::string > ConfigTable
Dominator tree builder for Clang's CFG based on llvm::DominatorTreeBase.
Definition: Dominators.h:42
void dump()
Dumps immediate dominators for each block.
Definition: Dominators.h:94
void buildDominatorTree(CFG *cfg)
Builds the dominator tree for a given CFG.
Definition: Dominators.h:87
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition: CFG.h:1214
The AST-based call graph.
Definition: CallGraph.h:42
void viewGraph() const
Definition: CallGraph.cpp:250
void addToCallGraph(Decl *D)
Populate the call graph with the functions in the given declaration.
Definition: CallGraph.h:62
void dump() const
Definition: CallGraph.cpp:246
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
Stmt - This represents one statement.
Definition: Stmt.h:84
The top declaration context.
Definition: Decl.h:84
const LangOptions & getLangOpts() const
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
SourceManager & getSourceManager() override
T * getAnalysis(Decl const *D)
CFG * getCFG(Decl const *D)
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:585
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
void ViewGraph(bool trim=false)
Visualize the ExplodedGraph created by executing the simulation.
The JSON file list parser is used to communicate input to InstallAPI.
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57