1 //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines checkers that display debugging information.
11 //===----------------------------------------------------------------------===//
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"
25 using namespace clang
;
28 //===----------------------------------------------------------------------===//
29 // DominatorsTreeDumper
30 //===----------------------------------------------------------------------===//
33 class DominatorsTreeDumper
: public Checker
<check::ASTCodeBody
> {
35 void checkASTCodeBody(const Decl
*D
, AnalysisManager
& mgr
,
36 BugReporter
&BR
) const {
37 if (AnalysisDeclContext
*AC
= mgr
.getAnalysisDeclContext(D
)) {
39 Dom
.buildDominatorTree(AC
->getCFG());
46 void ento::registerDominatorsTreeDumper(CheckerManager
&mgr
) {
47 mgr
.registerChecker
<DominatorsTreeDumper
>();
50 bool ento::shouldRegisterDominatorsTreeDumper(const CheckerManager
&mgr
) {
54 //===----------------------------------------------------------------------===//
55 // PostDominatorsTreeDumper
56 //===----------------------------------------------------------------------===//
59 class PostDominatorsTreeDumper
: public Checker
<check::ASTCodeBody
> {
61 void checkASTCodeBody(const Decl
*D
, AnalysisManager
& mgr
,
62 BugReporter
&BR
) const {
63 if (AnalysisDeclContext
*AC
= mgr
.getAnalysisDeclContext(D
)) {
65 Dom
.buildDominatorTree(AC
->getCFG());
72 void ento::registerPostDominatorsTreeDumper(CheckerManager
&mgr
) {
73 mgr
.registerChecker
<PostDominatorsTreeDumper
>();
76 bool ento::shouldRegisterPostDominatorsTreeDumper(const CheckerManager
&mgr
) {
80 //===----------------------------------------------------------------------===//
81 // ControlDependencyTreeDumper
82 //===----------------------------------------------------------------------===//
85 class ControlDependencyTreeDumper
: public Checker
<check::ASTCodeBody
> {
87 void checkASTCodeBody(const Decl
*D
, AnalysisManager
& mgr
,
88 BugReporter
&BR
) const {
89 if (AnalysisDeclContext
*AC
= mgr
.getAnalysisDeclContext(D
)) {
90 ControlDependencyCalculator
Dom(AC
->getCFG());
97 void ento::registerControlDependencyTreeDumper(CheckerManager
&mgr
) {
98 mgr
.registerChecker
<ControlDependencyTreeDumper
>();
101 bool ento::shouldRegisterControlDependencyTreeDumper(const CheckerManager
&mgr
) {
105 //===----------------------------------------------------------------------===//
106 // LiveVariablesDumper
107 //===----------------------------------------------------------------------===//
110 class LiveVariablesDumper
: public Checker
<check::ASTCodeBody
> {
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());
121 void ento::registerLiveVariablesDumper(CheckerManager
&mgr
) {
122 mgr
.registerChecker
<LiveVariablesDumper
>();
125 bool ento::shouldRegisterLiveVariablesDumper(const CheckerManager
&mgr
) {
129 //===----------------------------------------------------------------------===//
130 // LiveStatementsDumper
131 //===----------------------------------------------------------------------===//
134 class LiveExpressionsDumper
: public Checker
<check::ASTCodeBody
> {
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());
144 void ento::registerLiveExpressionsDumper(CheckerManager
&mgr
) {
145 mgr
.registerChecker
<LiveExpressionsDumper
>();
148 bool ento::shouldRegisterLiveExpressionsDumper(const CheckerManager
&mgr
) {
152 //===----------------------------------------------------------------------===//
154 //===----------------------------------------------------------------------===//
157 class CFGViewer
: public Checker
<check::ASTCodeBody
> {
159 void checkASTCodeBody(const Decl
*D
, AnalysisManager
& mgr
,
160 BugReporter
&BR
) const {
161 if (CFG
*cfg
= mgr
.getCFG(D
)) {
162 cfg
->viewCFG(mgr
.getLangOpts());
168 void ento::registerCFGViewer(CheckerManager
&mgr
) {
169 mgr
.registerChecker
<CFGViewer
>();
172 bool ento::shouldRegisterCFGViewer(const CheckerManager
&mgr
) {
176 //===----------------------------------------------------------------------===//
178 //===----------------------------------------------------------------------===//
181 class CFGDumper
: public Checker
<check::ASTCodeBody
> {
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
);
190 if (CFG
*cfg
= mgr
.getCFG(D
)) {
191 cfg
->dump(mgr
.getLangOpts(),
192 llvm::sys::Process::StandardErrHasColors());
198 void ento::registerCFGDumper(CheckerManager
&mgr
) {
199 mgr
.registerChecker
<CFGDumper
>();
202 bool ento::shouldRegisterCFGDumper(const CheckerManager
&mgr
) {
206 //===----------------------------------------------------------------------===//
208 //===----------------------------------------------------------------------===//
211 class CallGraphViewer
: public Checker
< check::ASTDecl
<TranslationUnitDecl
> > {
213 void checkASTDecl(const TranslationUnitDecl
*TU
, AnalysisManager
& mgr
,
214 BugReporter
&BR
) const {
216 CG
.addToCallGraph(const_cast<TranslationUnitDecl
*>(TU
));
222 void ento::registerCallGraphViewer(CheckerManager
&mgr
) {
223 mgr
.registerChecker
<CallGraphViewer
>();
226 bool ento::shouldRegisterCallGraphViewer(const CheckerManager
&mgr
) {
230 //===----------------------------------------------------------------------===//
232 //===----------------------------------------------------------------------===//
235 class CallGraphDumper
: public Checker
< check::ASTDecl
<TranslationUnitDecl
> > {
237 void checkASTDecl(const TranslationUnitDecl
*TU
, AnalysisManager
& mgr
,
238 BugReporter
&BR
) const {
240 CG
.addToCallGraph(const_cast<TranslationUnitDecl
*>(TU
));
246 void ento::registerCallGraphDumper(CheckerManager
&mgr
) {
247 mgr
.registerChecker
<CallGraphDumper
>();
250 bool ento::shouldRegisterCallGraphDumper(const CheckerManager
&mgr
) {
254 //===----------------------------------------------------------------------===//
256 //===----------------------------------------------------------------------===//
259 class ConfigDumper
: public Checker
< check::EndOfTranslationUnit
> {
260 typedef AnalyzerOptions::ConfigTable Table
;
262 static int compareEntry(const Table::MapEntryTy
*const *LHS
,
263 const Table::MapEntryTy
*const *RHS
) {
264 return (*LHS
)->getKey().compare((*RHS
)->getKey());
268 void checkEndOfTranslationUnit(const TranslationUnitDecl
*TU
,
269 AnalysisManager
& mgr
,
270 BugReporter
&BR
) const {
271 const Table
&Config
= mgr
.options
.Config
;
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
);
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
)
287 void ento::registerConfigDumper(CheckerManager
&mgr
) {
288 mgr
.registerChecker
<ConfigDumper
>();
291 bool ento::shouldRegisterConfigDumper(const CheckerManager
&mgr
) {
295 //===----------------------------------------------------------------------===//
296 // ExplodedGraph Viewer
297 //===----------------------------------------------------------------------===//
300 class ExplodedGraphViewer
: public Checker
< check::EndAnalysis
> {
302 ExplodedGraphViewer() {}
303 void checkEndAnalysis(ExplodedGraph
&G
, BugReporter
&B
,ExprEngine
&Eng
) const {
304 Eng
.ViewGraph(false);
310 void ento::registerExplodedGraphViewer(CheckerManager
&mgr
) {
311 mgr
.registerChecker
<ExplodedGraphViewer
>();
314 bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager
&mgr
) {
318 //===----------------------------------------------------------------------===//
319 // Emits a report for every Stmt that the analyzer visits.
320 //===----------------------------------------------------------------------===//
324 class ReportStmts
: public Checker
<check::PreStmt
<Stmt
>> {
325 BugType BT_stmtLoc
{this, "Statement"};
328 void checkPreStmt(const Stmt
*S
, CheckerContext
&C
) const {
329 ExplodedNode
*Node
= C
.generateNonFatalErrorNode();
334 std::make_unique
<PathSensitiveBugReport
>(BT_stmtLoc
, "Statement", Node
);
336 C
.emitReport(std::move(Report
));
340 } // end of anonymous namespace
342 void ento::registerReportStmts(CheckerManager
&mgr
) {
343 mgr
.registerChecker
<ReportStmts
>();
346 bool ento::shouldRegisterReportStmts(const CheckerManager
&mgr
) {