1 //==- DebugCheckers.cpp - Debugging Checkers ---------------------*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines checkers that display debugging information.
12 //===----------------------------------------------------------------------===//
14 #include "ClangSACheckers.h"
15 #include "clang/Analysis/Analyses/Dominators.h"
16 #include "clang/Analysis/Analyses/LiveVariables.h"
17 #include "clang/Analysis/CallGraph.h"
18 #include "clang/StaticAnalyzer/Core/Checker.h"
19 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
21 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
22 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
23 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
24 #include "llvm/Support/Process.h"
26 using namespace clang;
29 //===----------------------------------------------------------------------===//
30 // DominatorsTreeDumper
31 //===----------------------------------------------------------------------===//
34 class DominatorsTreeDumper : public Checker<check::ASTCodeBody> {
36 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
37 BugReporter &BR) const {
38 if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
40 dom.buildDominatorTree(*AC);
47 void ento::registerDominatorsTreeDumper(CheckerManager &mgr) {
48 mgr.registerChecker<DominatorsTreeDumper>();
51 //===----------------------------------------------------------------------===//
52 // LiveVariablesDumper
53 //===----------------------------------------------------------------------===//
56 class LiveVariablesDumper : public Checker<check::ASTCodeBody> {
58 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
59 BugReporter &BR) const {
60 if (LiveVariables* L = mgr.getAnalysis<LiveVariables>(D)) {
61 L->dumpBlockLiveness(mgr.getSourceManager());
67 void ento::registerLiveVariablesDumper(CheckerManager &mgr) {
68 mgr.registerChecker<LiveVariablesDumper>();
71 //===----------------------------------------------------------------------===//
73 //===----------------------------------------------------------------------===//
76 class CFGViewer : public Checker<check::ASTCodeBody> {
78 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
79 BugReporter &BR) const {
80 if (CFG *cfg = mgr.getCFG(D)) {
81 cfg->viewCFG(mgr.getLangOpts());
87 void ento::registerCFGViewer(CheckerManager &mgr) {
88 mgr.registerChecker<CFGViewer>();
91 //===----------------------------------------------------------------------===//
93 //===----------------------------------------------------------------------===//
96 class CFGDumper : public Checker<check::ASTCodeBody> {
98 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
99 BugReporter &BR) const {
100 PrintingPolicy Policy(mgr.getLangOpts());
101 Policy.TerseOutput = true;
102 Policy.PolishForDeclaration = true;
103 D->print(llvm::errs(), Policy);
105 if (CFG *cfg = mgr.getCFG(D)) {
106 cfg->dump(mgr.getLangOpts(),
107 llvm::sys::Process::StandardErrHasColors());
113 void ento::registerCFGDumper(CheckerManager &mgr) {
114 mgr.registerChecker<CFGDumper>();
117 //===----------------------------------------------------------------------===//
119 //===----------------------------------------------------------------------===//
122 class CallGraphViewer : public Checker< check::ASTDecl<TranslationUnitDecl> > {
124 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
125 BugReporter &BR) const {
127 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
133 void ento::registerCallGraphViewer(CheckerManager &mgr) {
134 mgr.registerChecker<CallGraphViewer>();
137 //===----------------------------------------------------------------------===//
139 //===----------------------------------------------------------------------===//
142 class CallGraphDumper : public Checker< check::ASTDecl<TranslationUnitDecl> > {
144 void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager& mgr,
145 BugReporter &BR) const {
147 CG.addToCallGraph(const_cast<TranslationUnitDecl*>(TU));
153 void ento::registerCallGraphDumper(CheckerManager &mgr) {
154 mgr.registerChecker<CallGraphDumper>();
158 //===----------------------------------------------------------------------===//
160 //===----------------------------------------------------------------------===//
163 class ConfigDumper : public Checker< check::EndOfTranslationUnit > {
164 typedef AnalyzerOptions::ConfigTable Table;
166 static int compareEntry(const Table::MapEntryTy *const *LHS,
167 const Table::MapEntryTy *const *RHS) {
168 return (*LHS)->getKey().compare((*RHS)->getKey());
172 void checkEndOfTranslationUnit(const TranslationUnitDecl *TU,
173 AnalysisManager& mgr,
174 BugReporter &BR) const {
175 const Table &Config = mgr.options.Config;
177 SmallVector<const Table::MapEntryTy *, 32> Keys;
178 for (Table::const_iterator I = Config.begin(), E = Config.end(); I != E;
181 llvm::array_pod_sort(Keys.begin(), Keys.end(), compareEntry);
183 llvm::errs() << "[config]\n";
184 for (unsigned I = 0, E = Keys.size(); I != E; ++I)
185 llvm::errs() << Keys[I]->getKey() << " = " << Keys[I]->second << '\n';
187 llvm::errs() << "[stats]\n" << "num-entries = " << Keys.size() << '\n';
192 void ento::registerConfigDumper(CheckerManager &mgr) {
193 mgr.registerChecker<ConfigDumper>();
196 //===----------------------------------------------------------------------===//
197 // ExplodedGraph Viewer
198 //===----------------------------------------------------------------------===//
201 class ExplodedGraphViewer : public Checker< check::EndAnalysis > {
203 ExplodedGraphViewer() {}
204 void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,ExprEngine &Eng) const {
211 void ento::registerExplodedGraphViewer(CheckerManager &mgr) {
212 mgr.registerChecker<ExplodedGraphViewer>();