clang  3.9.0
DebugCheckers.cpp
Go to the documentation of this file.
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"
25 #include "llvm/Support/Process.h"
26 
27 using namespace clang;
28 using namespace ento;
29 
30 //===----------------------------------------------------------------------===//
31 // DominatorsTreeDumper
32 //===----------------------------------------------------------------------===//
33 
34 namespace {
35 class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
36 public:
37  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
38  BugReporter &BR) const {
40  DominatorTree dom;
41  dom.buildDominatorTree(*AC);
42  dom.dump();
43  }
44  }
45 };
46 }
47 
48 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
49  mgr.registerChecker<DominatorsTreeDumper>();
50 }
51 
52 //===----------------------------------------------------------------------===//
53 // LiveVariablesDumper
54 //===----------------------------------------------------------------------===//
55 
56 namespace {
57 class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
58 public:
59  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
60  BugReporter &BR) const {
61  if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
62  L->dumpBlockLiveness(mgr.getSourceManager());
63  }
64  }
65 };
66 }
67 
68 void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
69  mgr.registerChecker<LiveVariablesDumper>();
70 }
71 
72 //===----------------------------------------------------------------------===//
73 // CFGViewer
74 //===----------------------------------------------------------------------===//
75 
76 namespace {
77 class CFGViewer : public Checker<check::ASTCodeBody> {
78 public:
79  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
80  BugReporter &BR) const {
81  if (CFG *cfg = mgr.getCFG(D)) {
82  cfg->viewCFG(mgr.getLangOpts());
83  }
84  }
85 };
86 }
87 
88 void ento::registerCFGViewer(CheckerManager &mgr) {
89  mgr.registerChecker<CFGViewer>();
90 }
91 
92 //===----------------------------------------------------------------------===//
93 // CFGDumper
94 //===----------------------------------------------------------------------===//
95 
96 namespace {
97 class CFGDumper : public Checker<check::ASTCodeBody> {
98 public:
99  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
100  BugReporter &BR) const {
101  PrintingPolicy Policy(mgr.getLangOpts());
102  Policy.TerseOutput = true;
103  Policy.PolishForDeclaration = true;
104  D->print(llvm::errs(), Policy);
105 
106  if (CFG *cfg = mgr.getCFG(D)) {
107  cfg->dump(mgr.getLangOpts(),
108  llvm::sys::Process::StandardErrHasColors());
109  }
110  }
111 };
112 }
113 
114 void ento::registerCFGDumper(CheckerManager &mgr) {
115  mgr.registerChecker<CFGDumper>();
116 }
117 
118 //===----------------------------------------------------------------------===//
119 // CallGraphViewer
120 //===----------------------------------------------------------------------===//
121 
122 namespace {
123 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
124 public:
125  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
126  BugReporter &BR) const {
127  CallGraph CG;
128  CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
129  CG.viewGraph();
130  }
131 };
132 }
133 
134 void ento::registerCallGraphViewer(CheckerManager &mgr) {
135  mgr.registerChecker<CallGraphViewer>();
136 }
137 
138 //===----------------------------------------------------------------------===//
139 // CallGraphDumper
140 //===----------------------------------------------------------------------===//
141 
142 namespace {
143 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
144 public:
145  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
146  BugReporter &BR) const {
147  CallGraph CG;
148  CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
149  CG.dump();
150  }
151 };
152 }
153 
154 void ento::registerCallGraphDumper(CheckerManager &mgr) {
155  mgr.registerChecker<CallGraphDumper>();
156 }
157 
158 
159 //===----------------------------------------------------------------------===//
160 // ConfigDumper
161 //===----------------------------------------------------------------------===//
162 
163 namespace {
164 class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
165  typedef AnalyzerOptions::ConfigTable Table;
166 
167  static int compareEntry(const Table::MapEntryTy *const *LHS,
168  const Table::MapEntryTy *const *RHS) {
169  return (*LHS)->getKey().compare((*RHS)->getKey());
170  }
171 
172 public:
173  void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
174  AnalysisManager& mgr,
175  BugReporter &BR) const {
176  const Table &Config = mgr.options.Config;
177 
179  for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
180  ++I)
181  Keys.push_back(&*I);
182  llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
183 
184  llvm::errs() << "[config]\n";
185  for (unsigned I = 0, E = Keys.size(); I != E; ++I)
186  llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
187 
188  llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
189  }
190 };
191 }
192 
193 void ento::registerConfigDumper(CheckerManager &mgr) {
194  mgr.registerChecker<ConfigDumper>();
195 }
196 
197 //===----------------------------------------------------------------------===//
198 // ExplodedGraph Viewer
199 //===----------------------------------------------------------------------===//
200 
201 namespace {
202 class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
203 public:
204  ExplodedGraphViewer() {}
205  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
206  Eng.ViewGraph(0);
207  }
208 };
209 
210 }
211 
212 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
213  mgr.registerChecker<ExplodedGraphViewer>();
214 }
215 
216 //===----------------------------------------------------------------------===//
217 // DumpBugHash
218 //===----------------------------------------------------------------------===//
219 
220 namespace {
221 class BugHashDumper : public Checker<check::PostStmt<Stmt>> {
222 public:
223  mutable std::unique_ptr<BugType> BT;
224 
225  void checkPostStmt(const Stmt *S, CheckerContext &C) const {
226  if (!BT)
227  BT.reset(new BugType(this, "Dump hash components", "debug"));
228 
230  if (!N)
231  return;
232 
233  const LangOptions &Opts = C.getLangOpts();
234  const SourceManager &SM = C.getSourceManager();
235  FullSourceLoc FL(S->getLocStart(), SM);
236  std::string HashContent =
237  GetIssueString(SM, FL, getCheckName().getName(), BT->getCategory(),
238  C.getLocationContext()->getDecl(), Opts);
239 
240  C.emitReport(llvm::make_unique<BugReport>(*BT, HashContent, N));
241  }
242 };
243 }
244 
245 void ento::registerBugHashDumper(CheckerManager &mgr) {
246  mgr.registerChecker<BugHashDumper>();
247 }
The AST-based call graph.
Definition: CallGraph.h:34
void dump()
This method dumps immediate dominators for each block, mainly used for debug purposes.
Definition: Dominators.h:91
Describes how types, statements, expressions, and declarations should be printed. ...
Definition: PrettyPrinter.h:38
unsigned TerseOutput
Provide a 'terse' output.
AnalysisDeclContext contains the context data for the function or method under analysis.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:48
detail::InMemoryDirectory::const_iterator I
Concrete subclass of DominatorTreeBase for Clang This class implements the dominators tree functional...
Definition: Dominators.h:38
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
Definition: CFG.h:721
void buildDominatorTree(AnalysisDeclContext &AC)
This method builds the dominator tree for a given CFG The CFG information is passed via AnalysisDeclC...
Definition: Dominators.h:83
CFG * getCFG(Decl const *D)
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
const SourceManager & SM
Definition: Format.cpp:1184
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:388
CHECKER * registerChecker()
Used to register checkers.
ConfigTable Config
A key-value table of use-specified configuration values.
const Decl * getDecl() const
SourceManager & getSourceManager() override
void dump() const
Definition: CallGraph.cpp:191
detail::InMemoryDirectory::const_iterator E
const LangOptions & getLangOpts() const
std::string GetIssueString(const SourceManager &SM, FullSourceLoc &IssueLoc, llvm::StringRef CheckerName, llvm::StringRef BugType, const Decl *D, const LangOptions &LangOpts)
Get the string representation of issue hash.
void viewGraph() const
Definition: CallGraph.cpp:195
llvm::StringMap< std::string > ConfigTable
SourceManager & getSourceManager()
A SourceLocation and its associated SourceManager.
void addToCallGraph(Decl *D)
Populate the call graph with the functions in the given declaration.
Definition: CallGraph.h:53
TranslationUnitDecl - The top declaration context.
Definition: Decl.h:80
const LangOptions & getLangOpts() const
void ViewGraph(bool trim=false)
Visualize the ExplodedGraph created by executing the simulation.
T * getAnalysis(Decl const *D)
This class handles loading and caching of source files into memory.
const LocationContext * getLocationContext() const