clang  14.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 
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 
274  for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
275  ++I)
276  Keys.push_back(&*I);
277  llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
278 
279  llvm::errs() << "[config]\n";
280  for (unsigned I = 0, E = Keys.size(); I != E; ++I)
281  llvm::errs() << Keys[I]->getKey() << " = "
282  << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
283  << '\n';
284  }
285 };
286 }
287 
288 void ento::registerConfigDumper(CheckerManager &mgr) {
289  mgr.registerChecker<ConfigDumper>();
290 }
291 
292 bool ento::shouldRegisterConfigDumper(const CheckerManager &mgr) {
293  return true;
294 }
295 
296 //===----------------------------------------------------------------------===//
297 // ExplodedGraph Viewer
298 //===----------------------------------------------------------------------===//
299 
300 namespace {
301 class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
302 public:
303  ExplodedGraphViewer() {}
304  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
305  Eng.ViewGraph(0);
306  }
307 };
308 
309 }
310 
311 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
312  mgr.registerChecker<ExplodedGraphViewer>();
313 }
314 
315 bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager &mgr) {
316  return true;
317 }
318 
319 //===----------------------------------------------------------------------===//
320 // Emits a report for every Stmt that the analyzer visits.
321 //===----------------------------------------------------------------------===//
322 
323 namespace {
324 
325 class ReportStmts : public Checker<check::PreStmt<Stmt>> {
326  BuiltinBug BT_stmtLoc{this, "Statement"};
327 
328 public:
329  void checkPreStmt(const Stmt *S, CheckerContext &C) const {
330  ExplodedNode *Node = C.generateNonFatalErrorNode();
331  if (!Node)
332  return;
333 
334  auto Report =
335  std::make_unique<PathSensitiveBugReport>(BT_stmtLoc, "Statement", Node);
336 
337  C.emitReport(std::move(Report));
338  }
339 };
340 
341 } // end of anonymous namespace
342 
343 void ento::registerReportStmts(CheckerManager &mgr) {
344  mgr.registerChecker<ReportStmts>();
345 }
346 
347 bool ento::shouldRegisterReportStmts(const CheckerManager &mgr) {
348  return true;
349 }
clang::CallGraph::dump
void dump() const
Definition: CallGraph.cpp:246
llvm::SmallVector
Definition: LLVM.h:38
AttributeLangSupport::C
@ C
Definition: SemaDeclAttr.cpp:54
clang::AnalysisDeclContext
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Definition: AnalysisDeclContext.h:72
clang::PrintingPolicy
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:59
clang::CFG
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Definition: CFG.h:1225
clang::AnalyzerOptions::ConfigTable
llvm::StringMap< std::string > ConfigTable
Definition: AnalyzerOptions.h:165
clang::TranslationUnitDecl
The top declaration context.
Definition: Decl.h:82
BuiltinCheckerRegistration.h
Node
DynTypedNode Node
Definition: ASTMatchFinder.cpp:67
LiveVariables.h
clang::LiveVariables
Definition: LiveVariables.h:28
clang::CFGDominatorTreeImpl::buildDominatorTree
void buildDominatorTree(CFG *cfg)
Builds the dominator tree for a given CFG.
Definition: Dominators.h:87
ExplodedGraph.h
clang::CFGDominatorTreeImpl::dump
void dump()
Dumps immediate dominators for each block.
Definition: Dominators.h:94
BugType.h
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:89
CheckerContext.h
Checker.h
ExprEngine.h
clang::CallGraph::addToCallGraph
void addToCallGraph(Decl *D)
Populate the call graph with the functions in the given declaration.
Definition: CallGraph.h:62
clang
Definition: CalledOnceCheck.h:17
clang::Stmt
Stmt - This represents one statement.
Definition: Stmt.h:69
clang::Decl::print
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
Definition: DeclPrinter.cpp:126
CallGraph.h
clang::RelaxedLiveVariables
Definition: LiveVariables.h:112
clang::ControlDependencyCalculator
Definition: Dominators.h:215
Dominators.h
clang::CFGDominatorTreeImpl
Dominator tree builder for Clang's CFG based on llvm::DominatorTreeBase.
Definition: Dominators.h:42
clang::CallGraph::viewGraph
void viewGraph() const
Definition: CallGraph.cpp:250
AnalysisManager.h
clang::CallGraph
The AST-based call graph.
Definition: CallGraph.h:42