[DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select...
[llvm-project.git] / clang / lib / StaticAnalyzer / Checkers / DebugCheckers.cpp
blob04bbe85473c0e0c154177f8ded398860c82a3de0
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.
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;
26 using namespace ento;
28 //===----------------------------------------------------------------------===//
29 // DominatorsTreeDumper
30 //===----------------------------------------------------------------------===//
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();
46 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
47 mgr.registerChecker<DominatorsTreeDumper>();
50 bool ento::shouldRegisterDominatorsTreeDumper(const CheckerManager &mgr) {
51 return true;
54 //===----------------------------------------------------------------------===//
55 // PostDominatorsTreeDumper
56 //===----------------------------------------------------------------------===//
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();
72 void ento::registerPostDominatorsTreeDumper(CheckerManager &mgr) {
73 mgr.registerChecker<PostDominatorsTreeDumper>();
76 bool ento::shouldRegisterPostDominatorsTreeDumper(const CheckerManager &mgr) {
77 return true;
80 //===----------------------------------------------------------------------===//
81 // ControlDependencyTreeDumper
82 //===----------------------------------------------------------------------===//
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();
97 void ento::registerControlDependencyTreeDumper(CheckerManager &mgr) {
98 mgr.registerChecker<ControlDependencyTreeDumper>();
101 bool ento::shouldRegisterControlDependencyTreeDumper(const CheckerManager &mgr) {
102 return true;
105 //===----------------------------------------------------------------------===//
106 // LiveVariablesDumper
107 //===----------------------------------------------------------------------===//
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());
121 void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
122 mgr.registerChecker<LiveVariablesDumper>();
125 bool ento::shouldRegisterLiveVariablesDumper(const CheckerManager &mgr) {
126 return true;
129 //===----------------------------------------------------------------------===//
130 // LiveStatementsDumper
131 //===----------------------------------------------------------------------===//
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());
144 void ento::registerLiveExpressionsDumper(CheckerManager &mgr) {
145 mgr.registerChecker<LiveExpressionsDumper>();
148 bool ento::shouldRegisterLiveExpressionsDumper(const CheckerManager &mgr) {
149 return true;
152 //===----------------------------------------------------------------------===//
153 // CFGViewer
154 //===----------------------------------------------------------------------===//
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());
168 void ento::registerCFGViewer(CheckerManager &mgr) {
169 mgr.registerChecker<CFGViewer>();
172 bool ento::shouldRegisterCFGViewer(const CheckerManager &mgr) {
173 return true;
176 //===----------------------------------------------------------------------===//
177 // CFGDumper
178 //===----------------------------------------------------------------------===//
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);
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) {
203 return true;
206 //===----------------------------------------------------------------------===//
207 // CallGraphViewer
208 //===----------------------------------------------------------------------===//
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();
222 void ento::registerCallGraphViewer(CheckerManager &mgr) {
223 mgr.registerChecker<CallGraphViewer>();
226 bool ento::shouldRegisterCallGraphViewer(const CheckerManager &mgr) {
227 return true;
230 //===----------------------------------------------------------------------===//
231 // CallGraphDumper
232 //===----------------------------------------------------------------------===//
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();
246 void ento::registerCallGraphDumper(CheckerManager &mgr) {
247 mgr.registerChecker<CallGraphDumper>();
250 bool ento::shouldRegisterCallGraphDumper(const CheckerManager &mgr) {
251 return true;
254 //===----------------------------------------------------------------------===//
255 // ConfigDumper
256 //===----------------------------------------------------------------------===//
258 namespace {
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());
267 public:
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)
282 << '\n';
287 void ento::registerConfigDumper(CheckerManager &mgr) {
288 mgr.registerChecker<ConfigDumper>();
291 bool ento::shouldRegisterConfigDumper(const CheckerManager &mgr) {
292 return true;
295 //===----------------------------------------------------------------------===//
296 // ExplodedGraph Viewer
297 //===----------------------------------------------------------------------===//
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);
310 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
311 mgr.registerChecker<ExplodedGraphViewer>();
314 bool ento::shouldRegisterExplodedGraphViewer(const CheckerManager &mgr) {
315 return true;
318 //===----------------------------------------------------------------------===//
319 // Emits a report for every Stmt that the analyzer visits.
320 //===----------------------------------------------------------------------===//
322 namespace {
324 class ReportStmts : public Checker<check::PreStmt<Stmt>> {
325 BugType BT_stmtLoc{this, "Statement"};
327 public:
328 void checkPreStmt(const Stmt *S, CheckerContext &C) const {
329 ExplodedNode *Node = C.generateNonFatalErrorNode();
330 if (!Node)
331 return;
333 auto Report =
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) {
347 return true;