DebugCheckers.cpp revision 43e8ef0b90dffcf9bda4fc2d3e6b21feb1e15bfb
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 a checkers that display debugging information.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ClangSACheckers.h"
15#include "clang/StaticAnalyzer/Core/Checker.h"
16#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
17#include "clang/Analysis/Analyses/LiveVariables.h"
18#include "clang/Analysis/Analyses/Dominators.h"
19#include "clang/Analysis/CallGraph.h"
20#include "llvm/Support/Process.h"
21
22using namespace clang;
23using namespace ento;
24
25//===----------------------------------------------------------------------===//
26// DominatorsTreeDumper
27//===----------------------------------------------------------------------===//
28
29namespace {
30class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
31public:
32  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
33                        BugReporter &BR) const {
34    if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
35      DominatorTree dom;
36      dom.buildDominatorTree(*AC);
37      dom.dump();
38    }
39  }
40};
41}
42
43void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
44  mgr.registerChecker<DominatorsTreeDumper>();
45}
46
47//===----------------------------------------------------------------------===//
48// LiveVariablesDumper
49//===----------------------------------------------------------------------===//
50
51namespace {
52class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
53public:
54  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
55                        BugReporter &BR) const {
56    if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
57      L->dumpBlockLiveness(mgr.getSourceManager());
58    }
59  }
60};
61}
62
63void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
64  mgr.registerChecker<LiveVariablesDumper>();
65}
66
67//===----------------------------------------------------------------------===//
68// CFGViewer
69//===----------------------------------------------------------------------===//
70
71namespace {
72class CFGViewer : public Checker<check::ASTCodeBody> {
73public:
74  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
75                        BugReporter &BR) const {
76    if (CFG *cfg = mgr.getCFG(D)) {
77      cfg->viewCFG(mgr.getLangOpts());
78    }
79  }
80};
81}
82
83void ento::registerCFGViewer(CheckerManager &mgr) {
84  mgr.registerChecker<CFGViewer>();
85}
86
87//===----------------------------------------------------------------------===//
88// CFGDumper
89//===----------------------------------------------------------------------===//
90
91namespace {
92class CFGDumper : public Checker<check::ASTCodeBody> {
93public:
94  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
95                        BugReporter &BR) const {
96    if (CFG *cfg = mgr.getCFG(D)) {
97      cfg->dump(mgr.getLangOpts(),
98                llvm::sys::Process::StandardErrHasColors());
99    }
100  }
101};
102}
103
104void ento::registerCFGDumper(CheckerManager &mgr) {
105  mgr.registerChecker<CFGDumper>();
106}
107
108//===----------------------------------------------------------------------===//
109// CallGraphViewer
110//===----------------------------------------------------------------------===//
111
112namespace {
113class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
114public:
115  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
116                    BugReporter &BR) const {
117    CallGraph CG;
118    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
119    CG.viewGraph();
120  }
121};
122}
123
124void ento::registerCallGraphViewer(CheckerManager &mgr) {
125  mgr.registerChecker<CallGraphViewer>();
126}
127
128//===----------------------------------------------------------------------===//
129// CallGraphDumper
130//===----------------------------------------------------------------------===//
131
132namespace {
133class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
134public:
135  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
136                    BugReporter &BR) const {
137    CallGraph CG;
138    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
139    CG.dump();
140  }
141};
142}
143
144void ento::registerCallGraphDumper(CheckerManager &mgr) {
145  mgr.registerChecker<CallGraphDumper>();
146}
147
148
149//===----------------------------------------------------------------------===//
150// ConfigDumper
151//===----------------------------------------------------------------------===//
152
153namespace {
154class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
155public:
156  void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
157                                 AnalysisManager& mgr,
158                                 BugReporter &BR) const {
159
160    const AnalyzerOptions::ConfigTable &Config = mgr.options.Config;
161    AnalyzerOptions::ConfigTable::const_iterator I =
162      Config.begin(), E = Config.end();
163
164    std::vector<StringRef> Keys;
165    for (; I != E ; ++I) { Keys.push_back(I->getKey()); }
166    sort(Keys.begin(), Keys.end());
167
168    llvm::errs() << "[config]\n";
169    for (unsigned i = 0, n = Keys.size(); i < n ; ++i) {
170      StringRef Key = Keys[i];
171      I = Config.find(Key);
172      llvm::errs() << Key << " = " << I->second << '\n';
173    }
174    llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
175  }
176};
177}
178
179void ento::registerConfigDumper(CheckerManager &mgr) {
180  mgr.registerChecker<ConfigDumper>();
181}
182