xref: /llvm-project/clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp (revision 73b75e01bfa15ab4d308d05861e39a4f93cb15e9)
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 "llvm/Support/Process.h"
21 
22 using namespace clang;
23 using namespace ento;
24 
25 //===----------------------------------------------------------------------===//
26 // DominatorsTreeDumper
27 //===----------------------------------------------------------------------===//
28 
29 namespace {
30 class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
31 public:
32   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
33                         BugReporter &BR) const {
34     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
35       DominatorTree dom;
36       dom.buildDominatorTree(*AC);
37       dom.dump();
38     }
39   }
40 };
41 }
42 
43 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
44   mgr.registerChecker<DominatorsTreeDumper>();
45 }
46 
47 //===----------------------------------------------------------------------===//
48 // LiveVariablesDumper
49 //===----------------------------------------------------------------------===//
50 
51 namespace {
52 class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
53 public:
54   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
55                         BugReporter &BR) const {
56     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
57       L->dumpBlockLiveness(mgr.getSourceManager());
58     }
59   }
60 };
61 }
62 
63 void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
64   mgr.registerChecker<LiveVariablesDumper>();
65 }
66 
67 //===----------------------------------------------------------------------===//
68 // CFGViewer
69 //===----------------------------------------------------------------------===//
70 
71 namespace {
72 class CFGViewer : public Checker<check::ASTCodeBody> {
73 public:
74   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
75                         BugReporter &BR) const {
76     if (CFG *cfg = mgr.getCFG(D)) {
77       cfg->viewCFG(mgr.getLangOpts());
78     }
79   }
80 };
81 }
82 
83 void ento::registerCFGViewer(CheckerManager &mgr) {
84   mgr.registerChecker<CFGViewer>();
85 }
86 
87 //===----------------------------------------------------------------------===//
88 // CFGDumper
89 //===----------------------------------------------------------------------===//
90 
91 namespace {
92 class CFGDumper : public Checker<check::ASTCodeBody> {
93 public:
94   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
95                         BugReporter &BR) const {
96     if (CFG *cfg = mgr.getCFG(D)) {
97       cfg->dump(mgr.getLangOpts(),
98                 llvm::sys::Process::StandardErrHasColors());
99     }
100   }
101 };
102 }
103 
104 void ento::registerCFGDumper(CheckerManager &mgr) {
105   mgr.registerChecker<CFGDumper>();
106 }
107 
108 //===----------------------------------------------------------------------===//
109 // CallGraphViewer
110 //===----------------------------------------------------------------------===//
111 
112 namespace {
113 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
114 public:
115   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
116                     BugReporter &BR) const {
117     CallGraph CG;
118     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
119     CG.viewGraph();
120   }
121 };
122 }
123 
124 void ento::registerCallGraphViewer(CheckerManager &mgr) {
125   mgr.registerChecker<CallGraphViewer>();
126 }
127 
128 //===----------------------------------------------------------------------===//
129 // CallGraphDumper
130 //===----------------------------------------------------------------------===//
131 
132 namespace {
133 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
134 public:
135   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
136                     BugReporter &BR) const {
137     CallGraph CG;
138     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
139     CG.dump();
140   }
141 };
142 }
143 
144 void ento::registerCallGraphDumper(CheckerManager &mgr) {
145   mgr.registerChecker<CallGraphDumper>();
146 }
147 
148 
149 //===----------------------------------------------------------------------===//
150 // ConfigDumper
151 //===----------------------------------------------------------------------===//
152 
153 namespace {
154 class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
155 public:
156   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
157                                  AnalysisManager& mgr,
158                                  BugReporter &BR) const {
159 
160     const AnalyzerOptions::ConfigTable &Config = mgr.options.Config;
161     AnalyzerOptions::ConfigTable::const_iterator I =
162       Config.begin(), E = Config.end();
163 
164     std::vector<StringRef> Keys;
165     for (; I != E ; ++I) { Keys.push_back(I->getKey()); }
166     sort(Keys.begin(), Keys.end());
167 
168     llvm::errs() << "[config]\n";
169     for (unsigned i = 0, n = Keys.size(); i < n ; ++i) {
170       StringRef Key = Keys[i];
171       I = Config.find(Key);
172       llvm::errs() << Key << " = " << I->second << '\n';
173     }
174     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
175   }
176 };
177 }
178 
179 void ento::registerConfigDumper(CheckerManager &mgr) {
180   mgr.registerChecker<ConfigDumper>();
181 }
182