1*67e74705SXin Li //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file defines checkers that display debugging information.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li
14*67e74705SXin Li #include "ClangSACheckers.h"
15*67e74705SXin Li #include "clang/Analysis/Analyses/Dominators.h"
16*67e74705SXin Li #include "clang/Analysis/Analyses/LiveVariables.h"
17*67e74705SXin Li #include "clang/Analysis/CallGraph.h"
18*67e74705SXin Li #include "clang/StaticAnalyzer/Core/Checker.h"
19*67e74705SXin Li #include "clang/StaticAnalyzer/Core/IssueHash.h"
20*67e74705SXin Li #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
21*67e74705SXin Li #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
22*67e74705SXin Li #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
23*67e74705SXin Li #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
24*67e74705SXin Li #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
25*67e74705SXin Li #include "llvm/Support/Process.h"
26*67e74705SXin Li
27*67e74705SXin Li using namespace clang;
28*67e74705SXin Li using namespace ento;
29*67e74705SXin Li
30*67e74705SXin Li //===----------------------------------------------------------------------===//
31*67e74705SXin Li // DominatorsTreeDumper
32*67e74705SXin Li //===----------------------------------------------------------------------===//
33*67e74705SXin Li
34*67e74705SXin Li namespace {
35*67e74705SXin Li class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
36*67e74705SXin Li public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const37*67e74705SXin Li void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
38*67e74705SXin Li BugReporter &BR) const {
39*67e74705SXin Li if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
40*67e74705SXin Li DominatorTree dom;
41*67e74705SXin Li dom.buildDominatorTree(*AC);
42*67e74705SXin Li dom.dump();
43*67e74705SXin Li }
44*67e74705SXin Li }
45*67e74705SXin Li };
46*67e74705SXin Li }
47*67e74705SXin Li
registerDominatorsTreeDumper(CheckerManager & mgr)48*67e74705SXin Li void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
49*67e74705SXin Li mgr.registerChecker<DominatorsTreeDumper>();
50*67e74705SXin Li }
51*67e74705SXin Li
52*67e74705SXin Li //===----------------------------------------------------------------------===//
53*67e74705SXin Li // LiveVariablesDumper
54*67e74705SXin Li //===----------------------------------------------------------------------===//
55*67e74705SXin Li
56*67e74705SXin Li namespace {
57*67e74705SXin Li class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
58*67e74705SXin Li public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const59*67e74705SXin Li void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
60*67e74705SXin Li BugReporter &BR) const {
61*67e74705SXin Li if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
62*67e74705SXin Li L->dumpBlockLiveness(mgr.getSourceManager());
63*67e74705SXin Li }
64*67e74705SXin Li }
65*67e74705SXin Li };
66*67e74705SXin Li }
67*67e74705SXin Li
registerLiveVariablesDumper(CheckerManager & mgr)68*67e74705SXin Li void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
69*67e74705SXin Li mgr.registerChecker<LiveVariablesDumper>();
70*67e74705SXin Li }
71*67e74705SXin Li
72*67e74705SXin Li //===----------------------------------------------------------------------===//
73*67e74705SXin Li // CFGViewer
74*67e74705SXin Li //===----------------------------------------------------------------------===//
75*67e74705SXin Li
76*67e74705SXin Li namespace {
77*67e74705SXin Li class CFGViewer : public Checker<check::ASTCodeBody> {
78*67e74705SXin Li public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const79*67e74705SXin Li void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
80*67e74705SXin Li BugReporter &BR) const {
81*67e74705SXin Li if (CFG *cfg = mgr.getCFG(D)) {
82*67e74705SXin Li cfg->viewCFG(mgr.getLangOpts());
83*67e74705SXin Li }
84*67e74705SXin Li }
85*67e74705SXin Li };
86*67e74705SXin Li }
87*67e74705SXin Li
registerCFGViewer(CheckerManager & mgr)88*67e74705SXin Li void ento::registerCFGViewer(CheckerManager &mgr) {
89*67e74705SXin Li mgr.registerChecker<CFGViewer>();
90*67e74705SXin Li }
91*67e74705SXin Li
92*67e74705SXin Li //===----------------------------------------------------------------------===//
93*67e74705SXin Li // CFGDumper
94*67e74705SXin Li //===----------------------------------------------------------------------===//
95*67e74705SXin Li
96*67e74705SXin Li namespace {
97*67e74705SXin Li class CFGDumper : public Checker<check::ASTCodeBody> {
98*67e74705SXin Li public:
checkASTCodeBody(const Decl * D,AnalysisManager & mgr,BugReporter & BR) const99*67e74705SXin Li void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
100*67e74705SXin Li BugReporter &BR) const {
101*67e74705SXin Li PrintingPolicy Policy(mgr.getLangOpts());
102*67e74705SXin Li Policy.TerseOutput = true;
103*67e74705SXin Li Policy.PolishForDeclaration = true;
104*67e74705SXin Li D->print(llvm::errs(), Policy);
105*67e74705SXin Li
106*67e74705SXin Li if (CFG *cfg = mgr.getCFG(D)) {
107*67e74705SXin Li cfg->dump(mgr.getLangOpts(),
108*67e74705SXin Li llvm::sys::Process::StandardErrHasColors());
109*67e74705SXin Li }
110*67e74705SXin Li }
111*67e74705SXin Li };
112*67e74705SXin Li }
113*67e74705SXin Li
registerCFGDumper(CheckerManager & mgr)114*67e74705SXin Li void ento::registerCFGDumper(CheckerManager &mgr) {
115*67e74705SXin Li mgr.registerChecker<CFGDumper>();
116*67e74705SXin Li }
117*67e74705SXin Li
118*67e74705SXin Li //===----------------------------------------------------------------------===//
119*67e74705SXin Li // CallGraphViewer
120*67e74705SXin Li //===----------------------------------------------------------------------===//
121*67e74705SXin Li
122*67e74705SXin Li namespace {
123*67e74705SXin Li class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
124*67e74705SXin Li public:
checkASTDecl(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const125*67e74705SXin Li void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
126*67e74705SXin Li BugReporter &BR) const {
127*67e74705SXin Li CallGraph CG;
128*67e74705SXin Li CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
129*67e74705SXin Li CG.viewGraph();
130*67e74705SXin Li }
131*67e74705SXin Li };
132*67e74705SXin Li }
133*67e74705SXin Li
registerCallGraphViewer(CheckerManager & mgr)134*67e74705SXin Li void ento::registerCallGraphViewer(CheckerManager &mgr) {
135*67e74705SXin Li mgr.registerChecker<CallGraphViewer>();
136*67e74705SXin Li }
137*67e74705SXin Li
138*67e74705SXin Li //===----------------------------------------------------------------------===//
139*67e74705SXin Li // CallGraphDumper
140*67e74705SXin Li //===----------------------------------------------------------------------===//
141*67e74705SXin Li
142*67e74705SXin Li namespace {
143*67e74705SXin Li class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
144*67e74705SXin Li public:
checkASTDecl(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const145*67e74705SXin Li void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
146*67e74705SXin Li BugReporter &BR) const {
147*67e74705SXin Li CallGraph CG;
148*67e74705SXin Li CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
149*67e74705SXin Li CG.dump();
150*67e74705SXin Li }
151*67e74705SXin Li };
152*67e74705SXin Li }
153*67e74705SXin Li
registerCallGraphDumper(CheckerManager & mgr)154*67e74705SXin Li void ento::registerCallGraphDumper(CheckerManager &mgr) {
155*67e74705SXin Li mgr.registerChecker<CallGraphDumper>();
156*67e74705SXin Li }
157*67e74705SXin Li
158*67e74705SXin Li
159*67e74705SXin Li //===----------------------------------------------------------------------===//
160*67e74705SXin Li // ConfigDumper
161*67e74705SXin Li //===----------------------------------------------------------------------===//
162*67e74705SXin Li
163*67e74705SXin Li namespace {
164*67e74705SXin Li class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
165*67e74705SXin Li typedef AnalyzerOptions::ConfigTable Table;
166*67e74705SXin Li
compareEntry(const Table::MapEntryTy * const * LHS,const Table::MapEntryTy * const * RHS)167*67e74705SXin Li static int compareEntry(const Table::MapEntryTy *const *LHS,
168*67e74705SXin Li const Table::MapEntryTy *const *RHS) {
169*67e74705SXin Li return (*LHS)->getKey().compare((*RHS)->getKey());
170*67e74705SXin Li }
171*67e74705SXin Li
172*67e74705SXin Li public:
checkEndOfTranslationUnit(const TranslationUnitDecl * TU,AnalysisManager & mgr,BugReporter & BR) const173*67e74705SXin Li void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
174*67e74705SXin Li AnalysisManager& mgr,
175*67e74705SXin Li BugReporter &BR) const {
176*67e74705SXin Li const Table &Config = mgr.options.Config;
177*67e74705SXin Li
178*67e74705SXin Li SmallVector<const Table::MapEntryTy *, 32> Keys;
179*67e74705SXin Li for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
180*67e74705SXin Li ++I)
181*67e74705SXin Li Keys.push_back(&*I);
182*67e74705SXin Li llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
183*67e74705SXin Li
184*67e74705SXin Li llvm::errs() << "[config]\n";
185*67e74705SXin Li for (unsigned I = 0, E = Keys.size(); I != E; ++I)
186*67e74705SXin Li llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
187*67e74705SXin Li
188*67e74705SXin Li llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
189*67e74705SXin Li }
190*67e74705SXin Li };
191*67e74705SXin Li }
192*67e74705SXin Li
registerConfigDumper(CheckerManager & mgr)193*67e74705SXin Li void ento::registerConfigDumper(CheckerManager &mgr) {
194*67e74705SXin Li mgr.registerChecker<ConfigDumper>();
195*67e74705SXin Li }
196*67e74705SXin Li
197*67e74705SXin Li //===----------------------------------------------------------------------===//
198*67e74705SXin Li // ExplodedGraph Viewer
199*67e74705SXin Li //===----------------------------------------------------------------------===//
200*67e74705SXin Li
201*67e74705SXin Li namespace {
202*67e74705SXin Li class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
203*67e74705SXin Li public:
ExplodedGraphViewer()204*67e74705SXin Li ExplodedGraphViewer() {}
checkEndAnalysis(ExplodedGraph & G,BugReporter & B,ExprEngine & Eng) const205*67e74705SXin Li void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
206*67e74705SXin Li Eng.ViewGraph(0);
207*67e74705SXin Li }
208*67e74705SXin Li };
209*67e74705SXin Li
210*67e74705SXin Li }
211*67e74705SXin Li
registerExplodedGraphViewer(CheckerManager & mgr)212*67e74705SXin Li void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
213*67e74705SXin Li mgr.registerChecker<ExplodedGraphViewer>();
214*67e74705SXin Li }
215*67e74705SXin Li
216*67e74705SXin Li //===----------------------------------------------------------------------===//
217*67e74705SXin Li // DumpBugHash
218*67e74705SXin Li //===----------------------------------------------------------------------===//
219*67e74705SXin Li
220*67e74705SXin Li namespace {
221*67e74705SXin Li class BugHashDumper : public Checker<check::PostStmt<Stmt>> {
222*67e74705SXin Li public:
223*67e74705SXin Li mutable std::unique_ptr<BugType> BT;
224*67e74705SXin Li
checkPostStmt(const Stmt * S,CheckerContext & C) const225*67e74705SXin Li void checkPostStmt(const Stmt *S, CheckerContext &C) const {
226*67e74705SXin Li if (!BT)
227*67e74705SXin Li BT.reset(new BugType(this, "Dump hash components", "debug"));
228*67e74705SXin Li
229*67e74705SXin Li ExplodedNode *N = C.generateNonFatalErrorNode();
230*67e74705SXin Li if (!N)
231*67e74705SXin Li return;
232*67e74705SXin Li
233*67e74705SXin Li const LangOptions &Opts = C.getLangOpts();
234*67e74705SXin Li const SourceManager &SM = C.getSourceManager();
235*67e74705SXin Li FullSourceLoc FL(S->getLocStart(), SM);
236*67e74705SXin Li std::string HashContent =
237*67e74705SXin Li GetIssueString(SM, FL, getCheckName().getName(), BT->getCategory(),
238*67e74705SXin Li C.getLocationContext()->getDecl(), Opts);
239*67e74705SXin Li
240*67e74705SXin Li C.emitReport(llvm::make_unique<BugReport>(*BT, HashContent, N));
241*67e74705SXin Li }
242*67e74705SXin Li };
243*67e74705SXin Li }
244*67e74705SXin Li
registerBugHashDumper(CheckerManager & mgr)245*67e74705SXin Li void ento::registerBugHashDumper(CheckerManager &mgr) {
246*67e74705SXin Li mgr.registerChecker<BugHashDumper>();
247*67e74705SXin Li }
248