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 //
1057d736fdSArgyrios Kyrtzidis //  This file defines a checkers that display debugging information.
1157d736fdSArgyrios Kyrtzidis //
1257d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
1357d736fdSArgyrios Kyrtzidis 
1457d736fdSArgyrios Kyrtzidis #include "ClangSACheckers.h"
156a5674ffSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/Checker.h"
1657d736fdSArgyrios Kyrtzidis #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
1757d736fdSArgyrios Kyrtzidis #include "clang/Analysis/Analyses/LiveVariables.h"
180062e749STed Kremenek #include "clang/Analysis/Analyses/Dominators.h"
19c000e7edSAnna Zaks #include "clang/Analysis/CallGraph.h"
2072be32afSTed Kremenek #include "llvm/Support/Process.h"
2157d736fdSArgyrios Kyrtzidis 
2257d736fdSArgyrios Kyrtzidis using namespace clang;
2357d736fdSArgyrios Kyrtzidis using namespace ento;
2457d736fdSArgyrios Kyrtzidis 
2557d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
260062e749STed Kremenek // DominatorsTreeDumper
270062e749STed Kremenek //===----------------------------------------------------------------------===//
280062e749STed Kremenek 
290062e749STed Kremenek namespace {
300062e749STed Kremenek class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
310062e749STed Kremenek public:
320062e749STed Kremenek   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
330062e749STed Kremenek                         BugReporter &BR) const {
340062e749STed Kremenek     if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
3502a1fc1dSAnna Zaks       DominatorTree dom;
3602a1fc1dSAnna Zaks       dom.buildDominatorTree(*AC);
370062e749STed Kremenek       dom.dump();
380062e749STed Kremenek     }
390062e749STed Kremenek   }
400062e749STed Kremenek };
410062e749STed Kremenek }
420062e749STed Kremenek 
430062e749STed Kremenek void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
440062e749STed Kremenek   mgr.registerChecker<DominatorsTreeDumper>();
450062e749STed Kremenek }
460062e749STed Kremenek 
470062e749STed Kremenek //===----------------------------------------------------------------------===//
4857d736fdSArgyrios Kyrtzidis // LiveVariablesDumper
4957d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
5057d736fdSArgyrios Kyrtzidis 
5157d736fdSArgyrios Kyrtzidis namespace {
526a5674ffSArgyrios Kyrtzidis class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
5357d736fdSArgyrios Kyrtzidis public:
5457d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
5557d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
56dccc2b22STed Kremenek     if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
5757d736fdSArgyrios Kyrtzidis       L->dumpBlockLiveness(mgr.getSourceManager());
5857d736fdSArgyrios Kyrtzidis     }
5957d736fdSArgyrios Kyrtzidis   }
6057d736fdSArgyrios Kyrtzidis };
6157d736fdSArgyrios Kyrtzidis }
6257d736fdSArgyrios Kyrtzidis 
6357d736fdSArgyrios Kyrtzidis void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
6457d736fdSArgyrios Kyrtzidis   mgr.registerChecker<LiveVariablesDumper>();
6557d736fdSArgyrios Kyrtzidis }
6657d736fdSArgyrios Kyrtzidis 
6757d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
6857d736fdSArgyrios Kyrtzidis // CFGViewer
6957d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
7057d736fdSArgyrios Kyrtzidis 
7157d736fdSArgyrios Kyrtzidis namespace {
726a5674ffSArgyrios Kyrtzidis class CFGViewer : public Checker<check::ASTCodeBody> {
7357d736fdSArgyrios Kyrtzidis public:
7457d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
7557d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
7657d736fdSArgyrios Kyrtzidis     if (CFG *cfg = mgr.getCFG(D)) {
77bbafb8a7SDavid Blaikie       cfg->viewCFG(mgr.getLangOpts());
7857d736fdSArgyrios Kyrtzidis     }
7957d736fdSArgyrios Kyrtzidis   }
8057d736fdSArgyrios Kyrtzidis };
8157d736fdSArgyrios Kyrtzidis }
8257d736fdSArgyrios Kyrtzidis 
8357d736fdSArgyrios Kyrtzidis void ento::registerCFGViewer(CheckerManager &mgr) {
8457d736fdSArgyrios Kyrtzidis   mgr.registerChecker<CFGViewer>();
8557d736fdSArgyrios Kyrtzidis }
8657d736fdSArgyrios Kyrtzidis 
8757d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
8857d736fdSArgyrios Kyrtzidis // CFGDumper
8957d736fdSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
9057d736fdSArgyrios Kyrtzidis 
9157d736fdSArgyrios Kyrtzidis namespace {
926a5674ffSArgyrios Kyrtzidis class CFGDumper : public Checker<check::ASTCodeBody> {
9357d736fdSArgyrios Kyrtzidis public:
9457d736fdSArgyrios Kyrtzidis   void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
9557d736fdSArgyrios Kyrtzidis                         BugReporter &BR) const {
9657d736fdSArgyrios Kyrtzidis     if (CFG *cfg = mgr.getCFG(D)) {
97bbafb8a7SDavid Blaikie       cfg->dump(mgr.getLangOpts(),
9872be32afSTed Kremenek                 llvm::sys::Process::StandardErrHasColors());
9957d736fdSArgyrios Kyrtzidis     }
10057d736fdSArgyrios Kyrtzidis   }
10157d736fdSArgyrios Kyrtzidis };
10257d736fdSArgyrios Kyrtzidis }
10357d736fdSArgyrios Kyrtzidis 
10457d736fdSArgyrios Kyrtzidis void ento::registerCFGDumper(CheckerManager &mgr) {
10557d736fdSArgyrios Kyrtzidis   mgr.registerChecker<CFGDumper>();
10657d736fdSArgyrios Kyrtzidis }
107c000e7edSAnna Zaks 
108c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
109c000e7edSAnna Zaks // CallGraphViewer
110c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
111c000e7edSAnna Zaks 
112c000e7edSAnna Zaks namespace {
113c000e7edSAnna Zaks class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
114c000e7edSAnna Zaks public:
115c000e7edSAnna Zaks   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
116c000e7edSAnna Zaks                     BugReporter &BR) const {
117c000e7edSAnna Zaks     CallGraph CG;
118c000e7edSAnna Zaks     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
119c000e7edSAnna Zaks     CG.viewGraph();
120c000e7edSAnna Zaks   }
121c000e7edSAnna Zaks };
122c000e7edSAnna Zaks }
123c000e7edSAnna Zaks 
124c000e7edSAnna Zaks void ento::registerCallGraphViewer(CheckerManager &mgr) {
125c000e7edSAnna Zaks   mgr.registerChecker<CallGraphViewer>();
126c000e7edSAnna Zaks }
127c000e7edSAnna Zaks 
128c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
129c000e7edSAnna Zaks // CallGraphDumper
130c000e7edSAnna Zaks //===----------------------------------------------------------------------===//
131c000e7edSAnna Zaks 
132c000e7edSAnna Zaks namespace {
133c000e7edSAnna Zaks class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
134c000e7edSAnna Zaks public:
135c000e7edSAnna Zaks   void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
136c000e7edSAnna Zaks                     BugReporter &BR) const {
137c000e7edSAnna Zaks     CallGraph CG;
138c000e7edSAnna Zaks     CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
139c000e7edSAnna Zaks     CG.dump();
140c000e7edSAnna Zaks   }
141c000e7edSAnna Zaks };
142c000e7edSAnna Zaks }
143c000e7edSAnna Zaks 
144c000e7edSAnna Zaks void ento::registerCallGraphDumper(CheckerManager &mgr) {
145c000e7edSAnna Zaks   mgr.registerChecker<CallGraphDumper>();
146c000e7edSAnna Zaks }
147*86917fdbSTed Kremenek 
148*86917fdbSTed Kremenek 
149*86917fdbSTed Kremenek //===----------------------------------------------------------------------===//
150*86917fdbSTed Kremenek // ConfigDumper
151*86917fdbSTed Kremenek //===----------------------------------------------------------------------===//
152*86917fdbSTed Kremenek 
153*86917fdbSTed Kremenek namespace {
154*86917fdbSTed Kremenek class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
155*86917fdbSTed Kremenek public:
156*86917fdbSTed Kremenek   void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
157*86917fdbSTed Kremenek                                  AnalysisManager& mgr,
158*86917fdbSTed Kremenek                                  BugReporter &BR) const {
159*86917fdbSTed Kremenek 
160*86917fdbSTed Kremenek     const AnalyzerOptions::ConfigTable &Config = mgr.options.Config;
161*86917fdbSTed Kremenek     AnalyzerOptions::ConfigTable::const_iterator I =
162*86917fdbSTed Kremenek       Config.begin(), E = Config.end();
163*86917fdbSTed Kremenek 
164*86917fdbSTed Kremenek     std::vector<StringRef> Keys;
165*86917fdbSTed Kremenek     for (; I != E ; ++I) { Keys.push_back(I->getKey()); }
166*86917fdbSTed Kremenek     sort(Keys.begin(), Keys.end());
167*86917fdbSTed Kremenek 
168*86917fdbSTed Kremenek     llvm::errs() << "[config]\n";
169*86917fdbSTed Kremenek     for (unsigned i = 0, n = Keys.size(); i < n ; ++i) {
170*86917fdbSTed Kremenek       StringRef Key = Keys[i];
171*86917fdbSTed Kremenek       I = Config.find(Key);
172*86917fdbSTed Kremenek       llvm::errs() << Key << " = " << I->second << '\n';
173*86917fdbSTed Kremenek     }
174*86917fdbSTed Kremenek     llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
175*86917fdbSTed Kremenek   }
176*86917fdbSTed Kremenek };
177*86917fdbSTed Kremenek }
178*86917fdbSTed Kremenek 
179*86917fdbSTed Kremenek void ento::registerConfigDumper(CheckerManager &mgr) {
180*86917fdbSTed Kremenek   mgr.registerChecker<ConfigDumper>();
181*86917fdbSTed Kremenek }
182