xref: /llvm-project/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp (revision 15ae783e1487666b5c84f2defdf566cb0435ad95)
1 //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines checkers that display debugging information.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "ClangSACheckers.h"
15 #include "clang/Analysis/Analyses/Dominators.h"
16 #include "clang/Analysis/Analyses/LiveVariables.h"
17 #include "clang/Analysis/CallGraph.h"
18 #include "clang/StaticAnalyzer/Core/Checker.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
21 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
22 #include "llvm/Support/Process.h"
23 
24 using namespace clang;
25 using namespace ento;
26 
27 //===----------------------------------------------------------------------===//
28 // DominatorsTreeDumper
29 //===----------------------------------------------------------------------===//
30 
31 namespace {
32 class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
33 public:
34   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
35                         BugReporter &BR) const {
36     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
37       DominatorTree dom;
38       dom.buildDominatorTree(*AC);
39       dom.dump();
40     }
41   }
42 };
43 }
44 
45 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
46   mgr.registerChecker<DominatorsTreeDumper>();
47 }
48 
49 //===----------------------------------------------------------------------===//
50 // LiveVariablesDumper
51 //===----------------------------------------------------------------------===//
52 
53 namespace {
54 class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
55 public:
56   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
57                         BugReporter &BR) const {
58     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
59       L->dumpBlockLiveness(mgr.getSourceManager());
60     }
61   }
62 };
63 }
64 
65 void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
66   mgr.registerChecker<LiveVariablesDumper>();
67 }
68 
69 //===----------------------------------------------------------------------===//
70 // CFGViewer
71 //===----------------------------------------------------------------------===//
72 
73 namespace {
74 class CFGViewer : public Checker<check::ASTCodeBody> {
75 public:
76   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
77                         BugReporter &BR) const {
78     if (CFG *cfg = mgr.getCFG(D)) {
79       cfg->viewCFG(mgr.getLangOpts());
80     }
81   }
82 };
83 }
84 
85 void ento::registerCFGViewer(CheckerManager &mgr) {
86   mgr.registerChecker<CFGViewer>();
87 }
88 
89 //===----------------------------------------------------------------------===//
90 // CFGDumper
91 //===----------------------------------------------------------------------===//
92 
93 namespace {
94 class CFGDumper : public Checker<check::ASTCodeBody> {
95 public:
96   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
97                         BugReporter &BR) const {
98     PrintingPolicy Policy(mgr.getLangOpts());
99     Policy.TerseOutput = true;
100     Policy.PolishForDeclaration = true;
101     D->print(llvm::errs(), Policy);
102 
103     if (CFG *cfg = mgr.getCFG(D)) {
104       cfg->dump(mgr.getLangOpts(),
105                 llvm::sys::Process::StandardErrHasColors());
106     }
107   }
108 };
109 }
110 
111 void ento::registerCFGDumper(CheckerManager &mgr) {
112   mgr.registerChecker<CFGDumper>();
113 }
114 
115 //===----------------------------------------------------------------------===//
116 // CallGraphViewer
117 //===----------------------------------------------------------------------===//
118 
119 namespace {
120 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
121 public:
122   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
123                     BugReporter &BR) const {
124     CallGraph CG;
125     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
126     CG.viewGraph();
127   }
128 };
129 }
130 
131 void ento::registerCallGraphViewer(CheckerManager &mgr) {
132   mgr.registerChecker<CallGraphViewer>();
133 }
134 
135 //===----------------------------------------------------------------------===//
136 // CallGraphDumper
137 //===----------------------------------------------------------------------===//
138 
139 namespace {
140 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
141 public:
142   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
143                     BugReporter &BR) const {
144     CallGraph CG;
145     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
146     CG.dump();
147   }
148 };
149 }
150 
151 void ento::registerCallGraphDumper(CheckerManager &mgr) {
152   mgr.registerChecker<CallGraphDumper>();
153 }
154 
155 
156 //===----------------------------------------------------------------------===//
157 // ConfigDumper
158 //===----------------------------------------------------------------------===//
159 
160 namespace {
161 class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
162   typedef AnalyzerOptions::ConfigTable Table;
163 
164 public:
165   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
166                                  AnalysisManager& mgr,
167                                  BugReporter &BR) const {
168     const Table &Config = mgr.options.Config;
169 
170     SmallVector<const Table::MapEntryTy *, 32> Keys;
171     for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
172          ++I)
173       Keys.push_back(&*I);
174     llvm::array_pod_sort(Keys.begin(), Keys.end(),
175                          [](const Table::MapEntryTy *const *LHS,
176                             const Table::MapEntryTy *const *RHS) {
177       return (*LHS)->getKey().compare((*RHS)->getKey());
178     });
179 
180     llvm::errs() << "[config]\n";
181     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
182       llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
183 
184     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
185   }
186 };
187 }
188 
189 void ento::registerConfigDumper(CheckerManager &mgr) {
190   mgr.registerChecker<ConfigDumper>();
191 }
192 
193 //===----------------------------------------------------------------------===//
194 // ExplodedGraph Viewer
195 //===----------------------------------------------------------------------===//
196 
197 namespace {
198 class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
199 public:
200   ExplodedGraphViewer() {}
201   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
202     Eng.ViewGraph(0);
203   }
204 };
205 
206 }
207 
208 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
209   mgr.registerChecker<ExplodedGraphViewer>();
210 }
211