Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
35266 views
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
CFGDomTree Dom;
39
Dom.buildDominatorTree(AC->getCFG());
40
Dom.dump();
41
}
42
}
43
};
44
}
45
46
void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
47
mgr.registerChecker<DominatorsTreeDumper>();
48
}
49
50
bool ento::shouldRegisterDominatorsTreeDumper(const CheckerManager &mgr) {
51
return true;
52
}
53
54
//===----------------------------------------------------------------------===//
55
// PostDominatorsTreeDumper
56
//===----------------------------------------------------------------------===//
57
58
namespace {
59
class PostDominatorsTreeDumper : public Checker<check::ASTCodeBody> {
60
public:
61
void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
62
BugReporter &BR) const {
63
if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
64
CFGPostDomTree Dom;
65
Dom.buildDominatorTree(AC->getCFG());
66
Dom.dump();
67
}
68
}
69
};
70
}
71
72
void ento::registerPostDominatorsTreeDumper(CheckerManager &mgr) {
73
mgr.registerChecker<PostDominatorsTreeDumper>();
74
}
75
76
bool ento::shouldRegisterPostDominatorsTreeDumper(const CheckerManager &mgr) {
77
return true;
78
}
79
80
//===----------------------------------------------------------------------===//
81
// ControlDependencyTreeDumper
82
//===----------------------------------------------------------------------===//
83
84
namespace {
85
class ControlDependencyTreeDumper : public Checker<check::ASTCodeBody> {
86
public:
87
void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
88
BugReporter &BR) const {
89
if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
90
ControlDependencyCalculator Dom(AC->getCFG());
91
Dom.dump();
92
}
93
}
94
};
95
}
96
97
void ento::registerControlDependencyTreeDumper(CheckerManager &mgr) {
98
mgr.registerChecker<ControlDependencyTreeDumper>();
99
}
100
101
bool ento::shouldRegisterControlDependencyTreeDumper(const CheckerManager &mgr) {
102
return true;
103
}
104
105
//===----------------------------------------------------------------------===//
106
// LiveVariablesDumper
107
//===----------------------------------------------------------------------===//
108
109
namespace {
110
class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
111
public:
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
121
void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
122
mgr.registerChecker<LiveVariablesDumper>();
123
}
124
125
bool ento::shouldRegisterLiveVariablesDumper(const CheckerManager &mgr) {
126
return true;
127
}
128
129
//===----------------------------------------------------------------------===//
130
// LiveStatementsDumper
131
//===----------------------------------------------------------------------===//
132
133
namespace {
134
class LiveExpressionsDumper : public Checker<check::ASTCodeBody> {
135
public:
136
void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
137
BugReporter &BR) const {
138
if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))
139
L->dumpExprLiveness(Mgr.getSourceManager());
140
}
141
};
142
}
143
144
void ento::registerLiveExpressionsDumper(CheckerManager &mgr) {
145
mgr.registerChecker<LiveExpressionsDumper>();
146
}
147
148
bool ento::shouldRegisterLiveExpressionsDumper(const CheckerManager &mgr) {
149
return true;
150
}
151
152
//===----------------------------------------------------------------------===//
153
// CFGViewer
154
//===----------------------------------------------------------------------===//
155
156
namespace {
157
class CFGViewer : public Checker<check::ASTCodeBody> {
158
public:
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
168
void ento::registerCFGViewer(CheckerManager &mgr) {
169
mgr.registerChecker<CFGViewer>();
170
}
171
172
bool ento::shouldRegisterCFGViewer(const CheckerManager &mgr) {
173
return true;
174
}
175
176
//===----------------------------------------------------------------------===//
177
// CFGDumper
178
//===----------------------------------------------------------------------===//
179
180
namespace {
181
class CFGDumper : public Checker<check::ASTCodeBody> {
182
public:
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
198
void ento::registerCFGDumper(CheckerManager &mgr) {
199
mgr.registerChecker<CFGDumper>();
200
}
201
202
bool ento::shouldRegisterCFGDumper(const CheckerManager &mgr) {
203
return true;
204
}
205
206
//===----------------------------------------------------------------------===//
207
// CallGraphViewer
208
//===----------------------------------------------------------------------===//
209
210
namespace {
211
class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
212
public:
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
222
void ento::registerCallGraphViewer(CheckerManager &mgr) {
223
mgr.registerChecker<CallGraphViewer>();
224
}
225
226
bool ento::shouldRegisterCallGraphViewer(const CheckerManager &mgr) {
227
return true;
228
}
229
230
//===----------------------------------------------------------------------===//
231
// CallGraphDumper
232
//===----------------------------------------------------------------------===//
233
234
namespace {
235
class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
236
public:
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
246
void ento::registerCallGraphDumper(CheckerManager &mgr) {
247
mgr.registerChecker<CallGraphDumper>();
248
}
249
250
bool ento::shouldRegisterCallGraphDumper(const CheckerManager &mgr) {
251
return true;
252
}
253
254
//===----------------------------------------------------------------------===//
255
// ConfigDumper
256
//===----------------------------------------------------------------------===//
257
258
namespace {
259
class 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
267
public:
268
void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
269
AnalysisManager& mgr,
270
BugReporter &BR) const {
271
const Table &Config = mgr.options.Config;
272
273
SmallVector<const Table::MapEntryTy *, 32> Keys;
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
287
void ento::registerConfigDumper(CheckerManager &mgr) {
288
mgr.registerChecker<ConfigDumper>();
289
}
290
291
bool ento::shouldRegisterConfigDumper(const CheckerManager &mgr) {
292
return true;
293
}
294
295
//===----------------------------------------------------------------------===//
296
// ExplodedGraph Viewer
297
//===----------------------------------------------------------------------===//
298
299
namespace {
300
class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
301
public:
302
ExplodedGraphViewer() {}
303
void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
304
Eng.ViewGraph(false);
305
}
306
};
307
308
}
309
310
void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
311
mgr.registerChecker<ExplodedGraphViewer>();
312
}
313
314
bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager &mgr) {
315
return true;
316
}
317
318
//===----------------------------------------------------------------------===//
319
// Emits a report for every Stmt that the analyzer visits.
320
//===----------------------------------------------------------------------===//
321
322
namespace {
323
324
class ReportStmts : public Checker<check::PreStmt<Stmt>> {
325
BugType BT_stmtLoc{this, "Statement"};
326
327
public:
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
342
void ento::registerReportStmts(CheckerManager &mgr) {
343
mgr.registerChecker<ReportStmts>();
344
}
345
346
bool ento::shouldRegisterReportStmts(const CheckerManager &mgr) {
347
return true;
348
}
349
350