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 
1457d736fdSArgyrios Kyrtzidis #include "ClangSACheckers.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"
1957d736fdSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
207925e3dbSAnna Zaks #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
217925e3dbSAnna Zaks #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
2272be32afSTed Kremenek #include "llvm/Support/Process.h"
2357d736fdSArgyrios Kyrtzidis 
2457d736fdSArgyrios Kyrtzidis using namespace clang;
2557d736fdSArgyrios Kyrtzidis using namespace ento;
2657d736fdSArgyrios Kyrtzidis 
2757d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
280062e749STed Kremenek // DominatorsTreeDumper
290062e749STed Kremenek //===----------------------------------------------------------------------===//
300062e749STed Kremenek 
310062e749STed Kremenek namespace {
320062e749STed Kremenek class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
330062e749STed Kremenek public:
340062e749STed Kremenek   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
350062e749STed Kremenek                         BugReporter &BR) const {
360062e749STed Kremenek     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
3702a1fc1dSAnna Zaks       DominatorTree dom;
3802a1fc1dSAnna Zaks       dom.buildDominatorTree(*AC);
390062e749STed Kremenek       dom.dump();
400062e749STed Kremenek     }
410062e749STed Kremenek   }
420062e749STed Kremenek };
430062e749STed Kremenek }
440062e749STed Kremenek 
450062e749STed Kremenek void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
460062e749STed Kremenek   mgr.registerChecker<DominatorsTreeDumper>();
470062e749STed Kremenek }
480062e749STed Kremenek 
490062e749STed Kremenek //===----------------------------------------------------------------------===//
5057d736fdSArgyrios Kyrtzidis // LiveVariablesDumper
5157d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
5257d736fdSArgyrios Kyrtzidis 
5357d736fdSArgyrios Kyrtzidis namespace {
546a5674ffSArgyrios Kyrtzidis class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
5557d736fdSArgyrios Kyrtzidis public:
5657d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
5757d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
58dccc2b22STed Kremenek     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
5957d736fdSArgyrios Kyrtzidis       L->dumpBlockLiveness(mgr.getSourceManager());
6057d736fdSArgyrios Kyrtzidis     }
6157d736fdSArgyrios Kyrtzidis   }
6257d736fdSArgyrios Kyrtzidis };
6357d736fdSArgyrios Kyrtzidis }
6457d736fdSArgyrios Kyrtzidis 
6557d736fdSArgyrios Kyrtzidis void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
6657d736fdSArgyrios Kyrtzidis   mgr.registerChecker<LiveVariablesDumper>();
6757d736fdSArgyrios Kyrtzidis }
6857d736fdSArgyrios Kyrtzidis 
6957d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
7057d736fdSArgyrios Kyrtzidis // CFGViewer
7157d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
7257d736fdSArgyrios Kyrtzidis 
7357d736fdSArgyrios Kyrtzidis namespace {
746a5674ffSArgyrios Kyrtzidis class CFGViewer : public Checker<check::ASTCodeBody> {
7557d736fdSArgyrios Kyrtzidis public:
7657d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
7757d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
7857d736fdSArgyrios Kyrtzidis     if (CFG *cfg = mgr.getCFG(D)) {
79bbafb8a7SDavid Blaikie       cfg->viewCFG(mgr.getLangOpts());
8057d736fdSArgyrios Kyrtzidis     }
8157d736fdSArgyrios Kyrtzidis   }
8257d736fdSArgyrios Kyrtzidis };
8357d736fdSArgyrios Kyrtzidis }
8457d736fdSArgyrios Kyrtzidis 
8557d736fdSArgyrios Kyrtzidis void ento::registerCFGViewer(CheckerManager &mgr) {
8657d736fdSArgyrios Kyrtzidis   mgr.registerChecker<CFGViewer>();
8757d736fdSArgyrios Kyrtzidis }
8857d736fdSArgyrios Kyrtzidis 
8957d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
9057d736fdSArgyrios Kyrtzidis // CFGDumper
9157d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
9257d736fdSArgyrios Kyrtzidis 
9357d736fdSArgyrios Kyrtzidis namespace {
946a5674ffSArgyrios Kyrtzidis class CFGDumper : public Checker<check::ASTCodeBody> {
9557d736fdSArgyrios Kyrtzidis public:
9657d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
9757d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
98e02e96a6SJordan Rose     PrintingPolicy Policy(mgr.getLangOpts());
99e02e96a6SJordan Rose     Policy.TerseOutput = true;
100e02e96a6SJordan Rose     Policy.PolishForDeclaration = true;
101e02e96a6SJordan Rose     D->print(llvm::errs(), Policy);
102e02e96a6SJordan Rose 
10357d736fdSArgyrios Kyrtzidis     if (CFG *cfg = mgr.getCFG(D)) {
104bbafb8a7SDavid Blaikie       cfg->dump(mgr.getLangOpts(),
10572be32afSTed Kremenek                 llvm::sys::Process::StandardErrHasColors());
10657d736fdSArgyrios Kyrtzidis     }
10757d736fdSArgyrios Kyrtzidis   }
10857d736fdSArgyrios Kyrtzidis };
10957d736fdSArgyrios Kyrtzidis }
11057d736fdSArgyrios Kyrtzidis 
11157d736fdSArgyrios Kyrtzidis void ento::registerCFGDumper(CheckerManager &mgr) {
11257d736fdSArgyrios Kyrtzidis   mgr.registerChecker<CFGDumper>();
11357d736fdSArgyrios Kyrtzidis }
114c000e7edSAnna Zaks 
115c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
116c000e7edSAnna Zaks // CallGraphViewer
117c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
118c000e7edSAnna Zaks 
119c000e7edSAnna Zaks namespace {
120c000e7edSAnna Zaks class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
121c000e7edSAnna Zaks public:
122c000e7edSAnna Zaks   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
123c000e7edSAnna Zaks                     BugReporter &BR) const {
124c000e7edSAnna Zaks     CallGraph CG;
125c000e7edSAnna Zaks     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
126c000e7edSAnna Zaks     CG.viewGraph();
127c000e7edSAnna Zaks   }
128c000e7edSAnna Zaks };
129c000e7edSAnna Zaks }
130c000e7edSAnna Zaks 
131c000e7edSAnna Zaks void ento::registerCallGraphViewer(CheckerManager &mgr) {
132c000e7edSAnna Zaks   mgr.registerChecker<CallGraphViewer>();
133c000e7edSAnna Zaks }
134c000e7edSAnna Zaks 
135c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
136c000e7edSAnna Zaks // CallGraphDumper
137c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
138c000e7edSAnna Zaks 
139c000e7edSAnna Zaks namespace {
140c000e7edSAnna Zaks class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
141c000e7edSAnna Zaks public:
142c000e7edSAnna Zaks   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
143c000e7edSAnna Zaks                     BugReporter &BR) const {
144c000e7edSAnna Zaks     CallGraph CG;
145c000e7edSAnna Zaks     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
146c000e7edSAnna Zaks     CG.dump();
147c000e7edSAnna Zaks   }
148c000e7edSAnna Zaks };
149c000e7edSAnna Zaks }
150c000e7edSAnna Zaks 
151c000e7edSAnna Zaks void ento::registerCallGraphDumper(CheckerManager &mgr) {
152c000e7edSAnna Zaks   mgr.registerChecker<CallGraphDumper>();
153c000e7edSAnna Zaks }
15486917fdbSTed Kremenek 
15586917fdbSTed Kremenek 
15686917fdbSTed Kremenek //===----------------------------------------------------------------------===//
15786917fdbSTed Kremenek // ConfigDumper
15886917fdbSTed Kremenek //===----------------------------------------------------------------------===//
15986917fdbSTed Kremenek 
16086917fdbSTed Kremenek namespace {
16186917fdbSTed Kremenek class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
162a92b80f8SBenjamin Kramer   typedef AnalyzerOptions::ConfigTable Table;
163a92b80f8SBenjamin Kramer 
164*4cadf292SBenjamin Kramer   static int compareEntry(const Table::MapEntryTy *const *LHS,
165*4cadf292SBenjamin Kramer                           const Table::MapEntryTy *const *RHS) {
166*4cadf292SBenjamin Kramer     return (*LHS)->getKey().compare((*RHS)->getKey());
167*4cadf292SBenjamin Kramer   }
168*4cadf292SBenjamin Kramer 
16986917fdbSTed Kremenek public:
17086917fdbSTed Kremenek   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
17186917fdbSTed Kremenek                                  AnalysisManager& mgr,
17286917fdbSTed Kremenek                                  BugReporter &BR) const {
173a92b80f8SBenjamin Kramer     const Table &Config = mgr.options.Config;
17486917fdbSTed Kremenek 
175a92b80f8SBenjamin Kramer     SmallVector<const Table::MapEntryTy *, 32> Keys;
176a92b80f8SBenjamin Kramer     for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
177a92b80f8SBenjamin Kramer          ++I)
178a92b80f8SBenjamin Kramer       Keys.push_back(&*I);
179*4cadf292SBenjamin Kramer     llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
18086917fdbSTed Kremenek 
18186917fdbSTed Kremenek     llvm::errs() << "[config]\n";
182a92b80f8SBenjamin Kramer     for (unsigned I = 0, E = Keys.size(); I != E; ++I)
183a92b80f8SBenjamin Kramer       llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
184a92b80f8SBenjamin Kramer 
18586917fdbSTed Kremenek     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
18686917fdbSTed Kremenek   }
18786917fdbSTed Kremenek };
18886917fdbSTed Kremenek }
18986917fdbSTed Kremenek 
19086917fdbSTed Kremenek void ento::registerConfigDumper(CheckerManager &mgr) {
19186917fdbSTed Kremenek   mgr.registerChecker<ConfigDumper>();
19286917fdbSTed Kremenek }
1937925e3dbSAnna Zaks 
1947925e3dbSAnna Zaks //===----------------------------------------------------------------------===//
1957925e3dbSAnna Zaks // ExplodedGraph Viewer
1967925e3dbSAnna Zaks //===----------------------------------------------------------------------===//
1977925e3dbSAnna Zaks 
1987925e3dbSAnna Zaks namespace {
1997925e3dbSAnna Zaks class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
2007925e3dbSAnna Zaks public:
2017925e3dbSAnna Zaks   ExplodedGraphViewer() {}
2027925e3dbSAnna Zaks   void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
2037925e3dbSAnna Zaks     Eng.ViewGraph(0);
2047925e3dbSAnna Zaks   }
2057925e3dbSAnna Zaks };
2067925e3dbSAnna Zaks 
2077925e3dbSAnna Zaks }
2087925e3dbSAnna Zaks 
2097925e3dbSAnna Zaks void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
2107925e3dbSAnna Zaks   mgr.registerChecker<ExplodedGraphViewer>();
2117925e3dbSAnna Zaks }
212