clang 18.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
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:1211
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:85
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:83
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:584
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
void ViewGraph(bool trim=false)
Visualize the ExplodedGraph created by executing the simulation.
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57