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//
10252723Sdim//  This file defines checkers that display debugging information.
11218887Sdim//
12218887Sdim//===----------------------------------------------------------------------===//
13218887Sdim
14218887Sdim#include "ClangSACheckers.h"
15252723Sdim#include "clang/Analysis/Analyses/Dominators.h"
16252723Sdim#include "clang/Analysis/Analyses/LiveVariables.h"
17252723Sdim#include "clang/Analysis/CallGraph.h"
18221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h"
19218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
20263509Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
21263509Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
22235633Sdim#include "llvm/Support/Process.h"
23218887Sdim
24218887Sdimusing namespace clang;
25218887Sdimusing namespace ento;
26218887Sdim
27218887Sdim//===----------------------------------------------------------------------===//
28235633Sdim// DominatorsTreeDumper
29235633Sdim//===----------------------------------------------------------------------===//
30235633Sdim
31235633Sdimnamespace {
32235633Sdimclass DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
33235633Sdimpublic:
34235633Sdim  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
35235633Sdim                        BugReporter &BR) const {
36235633Sdim    if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
37235633Sdim      DominatorTree dom;
38235633Sdim      dom.buildDominatorTree(*AC);
39235633Sdim      dom.dump();
40235633Sdim    }
41235633Sdim  }
42235633Sdim};
43235633Sdim}
44235633Sdim
45235633Sdimvoid ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
46235633Sdim  mgr.registerChecker<DominatorsTreeDumper>();
47235633Sdim}
48235633Sdim
49235633Sdim//===----------------------------------------------------------------------===//
50218887Sdim// LiveVariablesDumper
51218887Sdim//===----------------------------------------------------------------------===//
52218887Sdim
53218887Sdimnamespace {
54221345Sdimclass LiveVariablesDumper : public Checker<check::ASTCodeBody> {
55218887Sdimpublic:
56218887Sdim  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
57218887Sdim                        BugReporter &BR) const {
58226890Sdim    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)) {
79235633Sdim      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)) {
99235633Sdim      cfg->dump(mgr.getLangOpts(),
100235633Sdim                llvm::sys::Process::StandardErrHasColors());
101218887Sdim    }
102218887Sdim  }
103218887Sdim};
104218887Sdim}
105218887Sdim
106218887Sdimvoid ento::registerCFGDumper(CheckerManager &mgr) {
107218887Sdim  mgr.registerChecker<CFGDumper>();
108218887Sdim}
109235633Sdim
110235633Sdim//===----------------------------------------------------------------------===//
111235633Sdim// CallGraphViewer
112235633Sdim//===----------------------------------------------------------------------===//
113235633Sdim
114235633Sdimnamespace {
115235633Sdimclass CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
116235633Sdimpublic:
117235633Sdim  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
118235633Sdim                    BugReporter &BR) const {
119235633Sdim    CallGraph CG;
120235633Sdim    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
121235633Sdim    CG.viewGraph();
122235633Sdim  }
123235633Sdim};
124235633Sdim}
125235633Sdim
126235633Sdimvoid ento::registerCallGraphViewer(CheckerManager &mgr) {
127235633Sdim  mgr.registerChecker<CallGraphViewer>();
128235633Sdim}
129235633Sdim
130235633Sdim//===----------------------------------------------------------------------===//
131235633Sdim// CallGraphDumper
132235633Sdim//===----------------------------------------------------------------------===//
133235633Sdim
134235633Sdimnamespace {
135235633Sdimclass CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
136235633Sdimpublic:
137235633Sdim  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
138235633Sdim                    BugReporter &BR) const {
139235633Sdim    CallGraph CG;
140235633Sdim    CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
141235633Sdim    CG.dump();
142235633Sdim  }
143235633Sdim};
144235633Sdim}
145235633Sdim
146235633Sdimvoid ento::registerCallGraphDumper(CheckerManager &mgr) {
147235633Sdim  mgr.registerChecker<CallGraphDumper>();
148235633Sdim}
149245431Sdim
150245431Sdim
151245431Sdim//===----------------------------------------------------------------------===//
152245431Sdim// ConfigDumper
153245431Sdim//===----------------------------------------------------------------------===//
154245431Sdim
155245431Sdimnamespace {
156245431Sdimclass ConfigDumper : public Checker< check::EndOfTranslationUnit > {
157263509Sdim  typedef AnalyzerOptions::ConfigTable Table;
158263509Sdim
159263509Sdim  static int compareEntry(const Table::MapEntryTy *const *LHS,
160263509Sdim                          const Table::MapEntryTy *const *RHS) {
161263509Sdim    return (*LHS)->getKey().compare((*RHS)->getKey());
162263509Sdim  }
163263509Sdim
164245431Sdimpublic:
165245431Sdim  void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
166245431Sdim                                 AnalysisManager& mgr,
167245431Sdim                                 BugReporter &BR) const {
168263509Sdim    const Table &Config = mgr.options.Config;
169245431Sdim
170263509Sdim    SmallVector<const Table::MapEntryTy *, 32> Keys;
171263509Sdim    for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
172263509Sdim         ++I)
173263509Sdim      Keys.push_back(&*I);
174263509Sdim    llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
175245431Sdim
176245431Sdim    llvm::errs() << "[config]\n";
177263509Sdim    for (unsigned I = 0, E = Keys.size(); I != E; ++I)
178263509Sdim      llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
179263509Sdim
180245431Sdim    llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
181245431Sdim  }
182245431Sdim};
183245431Sdim}
184245431Sdim
185245431Sdimvoid ento::registerConfigDumper(CheckerManager &mgr) {
186245431Sdim  mgr.registerChecker<ConfigDumper>();
187245431Sdim}
188263509Sdim
189263509Sdim//===----------------------------------------------------------------------===//
190263509Sdim// ExplodedGraph Viewer
191263509Sdim//===----------------------------------------------------------------------===//
192263509Sdim
193263509Sdimnamespace {
194263509Sdimclass ExplodedGraphViewer : public Checker< check::EndAnalysis > {
195263509Sdimpublic:
196263509Sdim  ExplodedGraphViewer() {}
197263509Sdim  void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
198263509Sdim    Eng.ViewGraph(0);
199263509Sdim  }
200263509Sdim};
201263509Sdim
202263509Sdim}
203263509Sdim
204263509Sdimvoid ento::registerExplodedGraphViewer(CheckerManager &mgr) {
205263509Sdim  mgr.registerChecker<ExplodedGraphViewer>();
206263509Sdim}
207