1218887Sdim//==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10251662Sdim//  This file defines checkers that display debugging information.
11218887Sdim//
12218887Sdim//===----------------------------------------------------------------------===//
13218887Sdim
14218887Sdim#include "ClangSACheckers.h"
15249423Sdim#include "clang/Analysis/Analyses/Dominators.h"
16249423Sdim#include "clang/Analysis/Analyses/LiveVariables.h"
17249423Sdim#include "clang/Analysis/CallGraph.h"
18221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h"
19218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
20263508Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
21263508Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
22234353Sdim#include "llvm/Support/Process.h"
23218887Sdim
24218887Sdimusing namespace clang;
25218887Sdimusing namespace ento;
26218887Sdim
27218887Sdim//===----------------------------------------------------------------------===//
28234353Sdim// DominatorsTreeDumper
29234353Sdim//===----------------------------------------------------------------------===//
30234353Sdim
31234353Sdimnamespace {
32234353Sdimclass DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
33234353Sdimpublic:
34234353Sdim  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
35234353Sdim                        BugReporter &BR) const {
36234353Sdim    if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
37234353Sdim      DominatorTree dom;
38234353Sdim      dom.buildDominatorTree(*AC);
39234353Sdim      dom.dump();
40234353Sdim    }
41234353Sdim  }
42234353Sdim};
43234353Sdim}
44234353Sdim
45234353Sdimvoid ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
46234353Sdim  mgr.registerChecker<DominatorsTreeDumper>();
47234353Sdim}
48234353Sdim
49234353Sdim//===----------------------------------------------------------------------===//
50218887Sdim// LiveVariablesDumper
51218887Sdim//===----------------------------------------------------------------------===//
52218887Sdim
53218887Sdimnamespace {
54221345Sdimclass LiveVariablesDumper : public Checker<check::ASTCodeBody> {
55218887Sdimpublic:
56218887Sdim  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
57218887Sdim                        BugReporter &BR) const {
58226633Sdim    if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
59218887Sdim      L->dumpBlockLiveness(mgr.getSourceManager());
60218887Sdim    }
61218887Sdim  }
62218887Sdim};
63218887Sdim}
64218887Sdim
65218887Sdimvoid ento::registerLiveVariablesDumper(CheckerManager &mgr) {
66218887Sdim  mgr.registerChecker<LiveVariablesDumper>();
67218887Sdim}
68218887Sdim
69218887Sdim//===----------------------------------------------------------------------===//
70218887Sdim// CFGViewer
71218887Sdim//===----------------------------------------------------------------------===//
72218887Sdim
73218887Sdimnamespace {
74221345Sdimclass CFGViewer : public Checker<check::ASTCodeBody> {
75218887Sdimpublic:
76218887Sdim  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
77218887Sdim                        BugReporter &BR) const {
78218887Sdim    if (CFG *cfg = mgr.getCFG(D)) {
79234353Sdim      cfg->viewCFG(mgr.getLangOpts());
80218887Sdim    }
81218887Sdim  }
82218887Sdim};
83218887Sdim}
84218887Sdim
85218887Sdimvoid ento::registerCFGViewer(CheckerManager &mgr) {
86218887Sdim  mgr.registerChecker<CFGViewer>();
87218887Sdim}
88218887Sdim
89218887Sdim//===----------------------------------------------------------------------===//
90218887Sdim// CFGDumper
91218887Sdim//===----------------------------------------------------------------------===//
92218887Sdim
93218887Sdimnamespace {
94221345Sdimclass CFGDumper : public Checker<check::ASTCodeBody> {
95218887Sdimpublic:
96218887Sdim  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
97218887Sdim                        BugReporter &BR) const {
98218887Sdim    if (CFG *cfg = mgr.getCFG(D)) {
99234353Sdim      cfg->dump(mgr.getLangOpts(),
100234353Sdim                llvm::sys::Process::StandardErrHasColors());
101218887Sdim    }
102218887Sdim  }
103218887Sdim};
104218887Sdim}
105218887Sdim
106218887Sdimvoid ento::registerCFGDumper(CheckerManager &mgr) {
107218887Sdim  mgr.registerChecker<CFGDumper>();
108218887Sdim}
109234353Sdim
110234353Sdim//===----------------------------------------------------------------------===//
111234353Sdim// CallGraphViewer
112234353Sdim//===----------------------------------------------------------------------===//
113234353Sdim
114234353Sdimnamespace {
115234353Sdimclass CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
116234353Sdimpublic:
117234353Sdim  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
118234353Sdim                    BugReporter &BR) const {
119234353Sdim    CallGraph CG;
120234353Sdim    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
121234353Sdim    CG.viewGraph();
122234353Sdim  }
123234353Sdim};
124234353Sdim}
125234353Sdim
126234353Sdimvoid ento::registerCallGraphViewer(CheckerManager &mgr) {
127234353Sdim  mgr.registerChecker<CallGraphViewer>();
128234353Sdim}
129234353Sdim
130234353Sdim//===----------------------------------------------------------------------===//
131234353Sdim// CallGraphDumper
132234353Sdim//===----------------------------------------------------------------------===//
133234353Sdim
134234353Sdimnamespace {
135234353Sdimclass CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
136234353Sdimpublic:
137234353Sdim  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
138234353Sdim                    BugReporter &BR) const {
139234353Sdim    CallGraph CG;
140234353Sdim    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
141234353Sdim    CG.dump();
142234353Sdim  }
143234353Sdim};
144234353Sdim}
145234353Sdim
146234353Sdimvoid ento::registerCallGraphDumper(CheckerManager &mgr) {
147234353Sdim  mgr.registerChecker<CallGraphDumper>();
148234353Sdim}
149243830Sdim
150243830Sdim
151243830Sdim//===----------------------------------------------------------------------===//
152243830Sdim// ConfigDumper
153243830Sdim//===----------------------------------------------------------------------===//
154243830Sdim
155243830Sdimnamespace {
156243830Sdimclass ConfigDumper : public Checker< check::EndOfTranslationUnit > {
157263508Sdim  typedef AnalyzerOptions::ConfigTable Table;
158263508Sdim
159263508Sdim  static int compareEntry(const Table::MapEntryTy *const *LHS,
160263508Sdim                          const Table::MapEntryTy *const *RHS) {
161263508Sdim    return (*LHS)->getKey().compare((*RHS)->getKey());
162263508Sdim  }
163263508Sdim
164243830Sdimpublic:
165243830Sdim  void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
166243830Sdim                                 AnalysisManager& mgr,
167243830Sdim                                 BugReporter &BR) const {
168263508Sdim    const Table &Config = mgr.options.Config;
169243830Sdim
170263508Sdim    SmallVector<const Table::MapEntryTy *, 32> Keys;
171263508Sdim    for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
172263508Sdim         ++I)
173263508Sdim      Keys.push_back(&*I);
174263508Sdim    llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
175243830Sdim
176243830Sdim    llvm::errs() << "[config]\n";
177263508Sdim    for (unsigned I = 0, E = Keys.size(); I != E; ++I)
178263508Sdim      llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
179263508Sdim
180243830Sdim    llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
181243830Sdim  }
182243830Sdim};
183243830Sdim}
184243830Sdim
185243830Sdimvoid ento::registerConfigDumper(CheckerManager &mgr) {
186243830Sdim  mgr.registerChecker<ConfigDumper>();
187243830Sdim}
188263508Sdim
189263508Sdim//===----------------------------------------------------------------------===//
190263508Sdim// ExplodedGraph Viewer
191263508Sdim//===----------------------------------------------------------------------===//
192263508Sdim
193263508Sdimnamespace {
194263508Sdimclass ExplodedGraphViewer : public Checker< check::EndAnalysis > {
195263508Sdimpublic:
196263508Sdim  ExplodedGraphViewer() {}
197263508Sdim  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
198263508Sdim    Eng.ViewGraph(0);
199263508Sdim  }
200263508Sdim};
201263508Sdim
202263508Sdim}
203263508Sdim
204263508Sdimvoid ento::registerExplodedGraphViewer(CheckerManager &mgr) {
205263508Sdim  mgr.registerChecker<ExplodedGraphViewer>();
206263508Sdim}
207