157d736fdSArgyrios Kyrtzidis //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
257d736fdSArgyrios Kyrtzidis //
357d736fdSArgyrios Kyrtzidis //                     The LLVM Compiler Infrastructure
457d736fdSArgyrios Kyrtzidis //
557d736fdSArgyrios Kyrtzidis // This file is distributed under the University of Illinois Open Source
657d736fdSArgyrios Kyrtzidis // License. See LICENSE.TXT for details.
757d736fdSArgyrios Kyrtzidis //
857d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
957d736fdSArgyrios Kyrtzidis //
1073b75e01SJordan Rose //  This file defines checkers that display debugging information.
1157d736fdSArgyrios Kyrtzidis //
1257d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
1357d736fdSArgyrios Kyrtzidis 
1476a21502SKristof Umann #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
153a02247dSChandler Carruth #include "clang/Analysis/Analyses/Dominators.h"
163a02247dSChandler Carruth #include "clang/Analysis/Analyses/LiveVariables.h"
173a02247dSChandler Carruth #include "clang/Analysis/CallGraph.h"
186a5674ffSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/Checker.h"
19efec1630SGabor Horvath #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
2057d736fdSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
21efec1630SGabor Horvath #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
227925e3dbSAnna Zaks #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
237925e3dbSAnna Zaks #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
2472be32afSTed Kremenek #include "llvm/Support/Process.h"
2557d736fdSArgyrios Kyrtzidis 
2657d736fdSArgyrios Kyrtzidis using namespace clang;
2757d736fdSArgyrios Kyrtzidis using namespace ento;
2857d736fdSArgyrios Kyrtzidis 
2957d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
300062e749STed Kremenek // DominatorsTreeDumper
310062e749STed Kremenek //===----------------------------------------------------------------------===//
320062e749STed Kremenek 
330062e749STed Kremenek namespace {
340062e749STed Kremenek class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
350062e749STed Kremenek public:
360062e749STed Kremenek   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
370062e749STed Kremenek                         BugReporter &BR) const {
380062e749STed Kremenek     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
3902a1fc1dSAnna Zaks       DominatorTree dom;
4002a1fc1dSAnna Zaks       dom.buildDominatorTree(*AC);
410062e749STed Kremenek       dom.dump();
420062e749STed Kremenek     }
430062e749STed Kremenek   }
440062e749STed Kremenek };
45ab9db510SAlexander Kornienko }
460062e749STed Kremenek 
470062e749STed Kremenek void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
480062e749STed Kremenek   mgr.registerChecker<DominatorsTreeDumper>();
490062e749STed Kremenek }
500062e749STed Kremenek 
510062e749STed Kremenek //===----------------------------------------------------------------------===//
5257d736fdSArgyrios Kyrtzidis // LiveVariablesDumper
5357d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
5457d736fdSArgyrios Kyrtzidis 
5557d736fdSArgyrios Kyrtzidis namespace {
566a5674ffSArgyrios Kyrtzidis class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
5757d736fdSArgyrios Kyrtzidis public:
5857d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
5957d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
60dccc2b22STed Kremenek     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
6157d736fdSArgyrios Kyrtzidis       L->dumpBlockLiveness(mgr.getSourceManager());
6257d736fdSArgyrios Kyrtzidis     }
6357d736fdSArgyrios Kyrtzidis   }
6457d736fdSArgyrios Kyrtzidis };
65ab9db510SAlexander Kornienko }
6657d736fdSArgyrios Kyrtzidis 
6757d736fdSArgyrios Kyrtzidis void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
6857d736fdSArgyrios Kyrtzidis   mgr.registerChecker<LiveVariablesDumper>();
6957d736fdSArgyrios Kyrtzidis }
7057d736fdSArgyrios Kyrtzidis 
7157d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
72*dda42164SArtem Dergachev // LiveStatementsDumper
73*dda42164SArtem Dergachev //===----------------------------------------------------------------------===//
74*dda42164SArtem Dergachev 
75*dda42164SArtem Dergachev namespace {
76*dda42164SArtem Dergachev class LiveStatementsDumper : public Checker<check::ASTCodeBody> {
77*dda42164SArtem Dergachev public:
78*dda42164SArtem Dergachev   void checkASTCodeBody(const Decl *D, AnalysisManager& Mgr,
79*dda42164SArtem Dergachev                         BugReporter &BR) const {
80*dda42164SArtem Dergachev     if (LiveVariables *L = Mgr.getAnalysis<RelaxedLiveVariables>(D))
81*dda42164SArtem Dergachev       L->dumpStmtLiveness(Mgr.getSourceManager());
82*dda42164SArtem Dergachev   }
83*dda42164SArtem Dergachev };
84*dda42164SArtem Dergachev }
85*dda42164SArtem Dergachev 
86*dda42164SArtem Dergachev void ento::registerLiveStatementsDumper(CheckerManager &mgr) {
87*dda42164SArtem Dergachev   mgr.registerChecker<LiveStatementsDumper>();
88*dda42164SArtem Dergachev }
89*dda42164SArtem Dergachev 
90*dda42164SArtem Dergachev //===----------------------------------------------------------------------===//
9157d736fdSArgyrios Kyrtzidis // CFGViewer
9257d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
9357d736fdSArgyrios Kyrtzidis 
9457d736fdSArgyrios Kyrtzidis namespace {
956a5674ffSArgyrios Kyrtzidis class CFGViewer : public Checker<check::ASTCodeBody> {
9657d736fdSArgyrios Kyrtzidis public:
9757d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
9857d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
9957d736fdSArgyrios Kyrtzidis     if (CFG *cfg = mgr.getCFG(D)) {
100bbafb8a7SDavid Blaikie       cfg->viewCFG(mgr.getLangOpts());
10157d736fdSArgyrios Kyrtzidis     }
10257d736fdSArgyrios Kyrtzidis   }
10357d736fdSArgyrios Kyrtzidis };
104ab9db510SAlexander Kornienko }
10557d736fdSArgyrios Kyrtzidis 
10657d736fdSArgyrios Kyrtzidis void ento::registerCFGViewer(CheckerManager &mgr) {
10757d736fdSArgyrios Kyrtzidis   mgr.registerChecker<CFGViewer>();
10857d736fdSArgyrios Kyrtzidis }
10957d736fdSArgyrios Kyrtzidis 
11057d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
11157d736fdSArgyrios Kyrtzidis // CFGDumper
11257d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
11357d736fdSArgyrios Kyrtzidis 
11457d736fdSArgyrios Kyrtzidis namespace {
1156a5674ffSArgyrios Kyrtzidis class CFGDumper : public Checker<check::ASTCodeBody> {
11657d736fdSArgyrios Kyrtzidis public:
11757d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
11857d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
119e02e96a6SJordan Rose     PrintingPolicy Policy(mgr.getLangOpts());
120e02e96a6SJordan Rose     Policy.TerseOutput = true;
121e02e96a6SJordan Rose     Policy.PolishForDeclaration = true;
122e02e96a6SJordan Rose     D->print(llvm::errs(), Policy);
123e02e96a6SJordan Rose 
12457d736fdSArgyrios Kyrtzidis     if (CFG *cfg = mgr.getCFG(D)) {
125bbafb8a7SDavid Blaikie       cfg->dump(mgr.getLangOpts(),
12672be32afSTed Kremenek                 llvm::sys::Process::StandardErrHasColors());
12757d736fdSArgyrios Kyrtzidis     }
12857d736fdSArgyrios Kyrtzidis   }
12957d736fdSArgyrios Kyrtzidis };
130ab9db510SAlexander Kornienko }
13157d736fdSArgyrios Kyrtzidis 
13257d736fdSArgyrios Kyrtzidis void ento::registerCFGDumper(CheckerManager &mgr) {
13357d736fdSArgyrios Kyrtzidis   mgr.registerChecker<CFGDumper>();
13457d736fdSArgyrios Kyrtzidis }
135c000e7edSAnna Zaks 
136c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
137c000e7edSAnna Zaks // CallGraphViewer
138c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
139c000e7edSAnna Zaks 
140c000e7edSAnna Zaks namespace {
141c000e7edSAnna Zaks class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
142c000e7edSAnna Zaks public:
143c000e7edSAnna Zaks   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
144c000e7edSAnna Zaks                     BugReporter &BR) const {
145c000e7edSAnna Zaks     CallGraph CG;
146c000e7edSAnna Zaks     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
147c000e7edSAnna Zaks     CG.viewGraph();
148c000e7edSAnna Zaks   }
149c000e7edSAnna Zaks };
150ab9db510SAlexander Kornienko }
151c000e7edSAnna Zaks 
152c000e7edSAnna Zaks void ento::registerCallGraphViewer(CheckerManager &mgr) {
153c000e7edSAnna Zaks   mgr.registerChecker<CallGraphViewer>();
154c000e7edSAnna Zaks }
155c000e7edSAnna Zaks 
156c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
157c000e7edSAnna Zaks // CallGraphDumper
158c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
159c000e7edSAnna Zaks 
160c000e7edSAnna Zaks namespace {
161c000e7edSAnna Zaks class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
162c000e7edSAnna Zaks public:
163c000e7edSAnna Zaks   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
164c000e7edSAnna Zaks                     BugReporter &BR) const {
165c000e7edSAnna Zaks     CallGraph CG;
166c000e7edSAnna Zaks     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
167c000e7edSAnna Zaks     CG.dump();
168c000e7edSAnna Zaks   }
169c000e7edSAnna Zaks };
170ab9db510SAlexander Kornienko }
171c000e7edSAnna Zaks 
172c000e7edSAnna Zaks void ento::registerCallGraphDumper(CheckerManager &mgr) {
173c000e7edSAnna Zaks   mgr.registerChecker<CallGraphDumper>();
174c000e7edSAnna Zaks }
17586917fdbSTed Kremenek 
17686917fdbSTed Kremenek 
17786917fdbSTed Kremenek //===----------------------------------------------------------------------===//
17886917fdbSTed Kremenek // ConfigDumper
17986917fdbSTed Kremenek //===----------------------------------------------------------------------===//
18086917fdbSTed Kremenek 
18186917fdbSTed Kremenek namespace {
18286917fdbSTed Kremenek class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
183a92b80f8SBenjamin Kramer   typedef AnalyzerOptions::ConfigTable Table;
184a92b80f8SBenjamin Kramer 
1854cadf292SBenjamin Kramer   static int compareEntry(const Table::MapEntryTy *const *LHS,
1864cadf292SBenjamin Kramer                           const Table::MapEntryTy *const *RHS) {
1874cadf292SBenjamin Kramer     return (*LHS)->getKey().compare((*RHS)->getKey());
1884cadf292SBenjamin Kramer   }
1894cadf292SBenjamin Kramer 
19086917fdbSTed Kremenek public:
19186917fdbSTed Kremenek   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
19286917fdbSTed Kremenek                                  AnalysisManager& mgr,
19386917fdbSTed Kremenek                                  BugReporter &BR) const {
194a92b80f8SBenjamin Kramer     const Table &Config = mgr.options.Config;
19586917fdbSTed Kremenek 
196a92b80f8SBenjamin Kramer     SmallVector<const Table::MapEntryTy *, 32> Keys;
197a92b80f8SBenjamin Kramer     for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
198a92b80f8SBenjamin Kramer          ++I)
199a92b80f8SBenjamin Kramer       Keys.push_back(&*I);
2004cadf292SBenjamin Kramer     llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
20186917fdbSTed Kremenek 
20286917fdbSTed Kremenek     llvm::errs() << "[config]\n";
203a92b80f8SBenjamin Kramer     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
204549f9cd4SKristof Umann       llvm::errs() << Keys[I]->getKey() << " = "
205549f9cd4SKristof Umann                    << (Keys[I]->second.empty() ? "\"\"" : Keys[I]->second)
206549f9cd4SKristof Umann                    << '\n';
207a92b80f8SBenjamin Kramer 
20886917fdbSTed Kremenek     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
20986917fdbSTed Kremenek   }
21086917fdbSTed Kremenek };
211ab9db510SAlexander Kornienko }
21286917fdbSTed Kremenek 
21386917fdbSTed Kremenek void ento::registerConfigDumper(CheckerManager &mgr) {
21486917fdbSTed Kremenek   mgr.registerChecker<ConfigDumper>();
21586917fdbSTed Kremenek }
2167925e3dbSAnna Zaks 
2177925e3dbSAnna Zaks //===----------------------------------------------------------------------===//
2187925e3dbSAnna Zaks // ExplodedGraph Viewer
2197925e3dbSAnna Zaks //===----------------------------------------------------------------------===//
2207925e3dbSAnna Zaks 
2217925e3dbSAnna Zaks namespace {
2227925e3dbSAnna Zaks class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
2237925e3dbSAnna Zaks public:
2247925e3dbSAnna Zaks   ExplodedGraphViewer() {}
2257925e3dbSAnna Zaks   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
2267925e3dbSAnna Zaks     Eng.ViewGraph(0);
2277925e3dbSAnna Zaks   }
2287925e3dbSAnna Zaks };
2297925e3dbSAnna Zaks 
2307925e3dbSAnna Zaks }
2317925e3dbSAnna Zaks 
2327925e3dbSAnna Zaks void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
2337925e3dbSAnna Zaks   mgr.registerChecker<ExplodedGraphViewer>();
2347925e3dbSAnna Zaks }
235efec1630SGabor Horvath 
236