| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 1 | //===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===// | 
|  | 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 | // "Meta" ASTConsumer for running different source analyses. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | #include "ASTConsumers.h" | 
| Ted Kremenek | ad99dbf | 2008-11-03 22:31:48 +0000 | [diff] [blame] | 15 | #include "clang/Driver/PathDiagnosticClients.h" | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 16 | #include "clang/Driver/ManagerRegistry.h" | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 17 | #include "clang/AST/ASTConsumer.h" | 
|  | 18 | #include "clang/AST/Decl.h" | 
|  | 19 | #include "clang/AST/DeclObjC.h" | 
|  | 20 | #include "llvm/Support/Compiler.h" | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 21 | #include "llvm/ADT/OwningPtr.h" | 
|  | 22 | #include "clang/AST/CFG.h" | 
|  | 23 | #include "clang/Analysis/Analyses/LiveVariables.h" | 
|  | 24 | #include "clang/Analysis/PathDiagnostic.h" | 
|  | 25 | #include "clang/Basic/SourceManager.h" | 
|  | 26 | #include "clang/Basic/FileManager.h" | 
|  | 27 | #include "clang/AST/ParentMap.h" | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 28 | #include "clang/AST/TranslationUnit.h" | 
| Ted Kremenek | c095997 | 2008-07-02 21:24:01 +0000 | [diff] [blame] | 29 | #include "clang/Analysis/PathSensitive/BugReporter.h" | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 30 | #include "clang/Analysis/Analyses/LiveVariables.h" | 
|  | 31 | #include "clang/Analysis/LocalCheckers.h" | 
|  | 32 | #include "clang/Analysis/PathSensitive/GRTransferFuncs.h" | 
|  | 33 | #include "clang/Analysis/PathSensitive/GRExprEngine.h" | 
| Zhongxing Xu | ff944a8 | 2008-12-22 01:52:37 +0000 | [diff] [blame] | 34 | #include "llvm/Support/CommandLine.h" | 
| Ted Kremenek | 34d7734 | 2008-07-02 16:49:11 +0000 | [diff] [blame] | 35 | #include "llvm/Support/Streams.h" | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 36 | #include "llvm/Support/raw_ostream.h" | 
|  | 37 | #include "llvm/System/Path.h" | 
| Ted Kremenek | 710ad93 | 2008-08-28 03:54:51 +0000 | [diff] [blame] | 38 | #include "llvm/System/Program.h" | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 39 | #include <vector> | 
|  | 40 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 41 | using namespace clang; | 
|  | 42 |  | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 43 | static ExplodedNodeImpl::Auditor* CreateUbiViz(); | 
| Zhongxing Xu | ff944a8 | 2008-12-22 01:52:37 +0000 | [diff] [blame] | 44 |  | 
|  | 45 | // Analyzer options. | 
|  | 46 | static llvm::cl::opt<bool> | 
|  | 47 | PurgeDead("analyzer-purge-dead", | 
|  | 48 | llvm::cl::init(true), | 
|  | 49 | llvm::cl::desc("Remove dead symbols, bindings, and constraints before" | 
|  | 50 | " processing a statement.")); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 51 |  | 
|  | 52 | //===----------------------------------------------------------------------===// | 
|  | 53 | // Basic type definitions. | 
|  | 54 | //===----------------------------------------------------------------------===// | 
|  | 55 |  | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 56 | namespace { | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 57 | class AnalysisManager; | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 58 | typedef void (*CodeAction)(AnalysisManager& Mgr); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 59 | } // end anonymous namespace | 
|  | 60 |  | 
|  | 61 | //===----------------------------------------------------------------------===// | 
|  | 62 | // AnalysisConsumer declaration. | 
|  | 63 | //===----------------------------------------------------------------------===// | 
|  | 64 |  | 
|  | 65 | namespace { | 
|  | 66 |  | 
|  | 67 | class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer { | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 68 | typedef std::vector<CodeAction> Actions; | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 69 | Actions FunctionActions; | 
|  | 70 | Actions ObjCMethodActions; | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 71 | Actions ObjCImplementationActions; | 
| Ted Kremenek | daac634 | 2008-11-07 02:09:25 +0000 | [diff] [blame] | 72 | Actions TranslationUnitActions; | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 73 |  | 
|  | 74 | public: | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 75 | const bool VisGraphviz; | 
|  | 76 | const bool VisUbigraph; | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 77 | const bool TrimGraph; | 
| Ted Kremenek | 95c7b00 | 2008-10-24 01:04:59 +0000 | [diff] [blame] | 78 | const LangOptions& LOpts; | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 79 | Diagnostic &Diags; | 
|  | 80 | ASTContext* Ctx; | 
|  | 81 | Preprocessor* PP; | 
|  | 82 | PreprocessorFactory* PPF; | 
|  | 83 | const std::string HTMLDir; | 
|  | 84 | const std::string FName; | 
|  | 85 | llvm::OwningPtr<PathDiagnosticClient> PD; | 
|  | 86 | bool AnalyzeAll; | 
| Ted Kremenek | 95c7b00 | 2008-10-24 01:04:59 +0000 | [diff] [blame] | 87 | AnalysisStores SM; | 
| Ted Kremenek | 4fc82c8 | 2008-11-03 23:18:07 +0000 | [diff] [blame] | 88 | AnalysisDiagClients DC; | 
| Ted Kremenek | 491918e | 2009-01-23 20:52:26 +0000 | [diff] [blame] | 89 | const bool DisplayProgress; | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 90 |  | 
|  | 91 | AnalysisConsumer(Diagnostic &diags, Preprocessor* pp, | 
|  | 92 | PreprocessorFactory* ppf, | 
|  | 93 | const LangOptions& lopts, | 
|  | 94 | const std::string& fname, | 
|  | 95 | const std::string& htmldir, | 
| Ted Kremenek | 4fc82c8 | 2008-11-03 23:18:07 +0000 | [diff] [blame] | 96 | AnalysisStores sm, AnalysisDiagClients dc, | 
| Ted Kremenek | 491918e | 2009-01-23 20:52:26 +0000 | [diff] [blame] | 97 | bool visgraphviz, bool visubi, bool trim, bool analyzeAll, | 
|  | 98 | bool displayProgress) | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 99 | : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim), | 
|  | 100 | LOpts(lopts), Diags(diags), | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 101 | Ctx(0), PP(pp), PPF(ppf), | 
|  | 102 | HTMLDir(htmldir), | 
|  | 103 | FName(fname), | 
| Ted Kremenek | 491918e | 2009-01-23 20:52:26 +0000 | [diff] [blame] | 104 | AnalyzeAll(analyzeAll), SM(sm), DC(dc), | 
|  | 105 | DisplayProgress(displayProgress) {} | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 106 |  | 
|  | 107 | void addCodeAction(CodeAction action) { | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 108 | FunctionActions.push_back(action); | 
|  | 109 | ObjCMethodActions.push_back(action); | 
|  | 110 | } | 
|  | 111 |  | 
|  | 112 | void addObjCImplementationAction(CodeAction action) { | 
|  | 113 | ObjCImplementationActions.push_back(action); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 114 | } | 
|  | 115 |  | 
| Ted Kremenek | daac634 | 2008-11-07 02:09:25 +0000 | [diff] [blame] | 116 | void addTranslationUnitAction(CodeAction action) { | 
|  | 117 | TranslationUnitActions.push_back(action); | 
|  | 118 | } | 
|  | 119 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 120 | virtual void Initialize(ASTContext &Context) { | 
|  | 121 | Ctx = &Context; | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | virtual void HandleTopLevelDecl(Decl *D); | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 125 | virtual void HandleTranslationUnit(TranslationUnit &TU); | 
|  | 126 |  | 
| Ted Kremenek | 81922f0 | 2009-02-02 20:52:40 +0000 | [diff] [blame^] | 127 | void HandleCode(Decl* D, Stmt* Body, Actions& actions); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 128 | }; | 
|  | 129 |  | 
|  | 130 |  | 
| Ted Kremenek | c095997 | 2008-07-02 21:24:01 +0000 | [diff] [blame] | 131 | class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData { | 
| Ted Kremenek | f304ddc | 2008-11-05 19:05:06 +0000 | [diff] [blame] | 132 | Decl* D; Stmt* Body; | 
|  | 133 | TranslationUnit* TU; | 
|  | 134 |  | 
|  | 135 | enum AnalysisScope { ScopeTU, ScopeDecl } AScope; | 
|  | 136 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 137 | AnalysisConsumer& C; | 
| Ted Kremenek | 34d7734 | 2008-07-02 16:49:11 +0000 | [diff] [blame] | 138 | bool DisplayedFunction; | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 139 |  | 
|  | 140 | llvm::OwningPtr<CFG> cfg; | 
|  | 141 | llvm::OwningPtr<LiveVariables> liveness; | 
|  | 142 | llvm::OwningPtr<ParentMap> PM; | 
|  | 143 |  | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 144 | // Configurable components creators. | 
|  | 145 | StoreManagerCreator CreateStoreMgr; | 
|  | 146 | ConstraintManagerCreator CreateConstraintMgr; | 
|  | 147 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 148 | public: | 
| Ted Kremenek | 491918e | 2009-01-23 20:52:26 +0000 | [diff] [blame] | 149 | AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b, bool displayProgress) | 
|  | 150 | : D(d), Body(b), TU(0), AScope(ScopeDecl), C(c), | 
|  | 151 | DisplayedFunction(!displayProgress) { | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 152 | setManagerCreators(); | 
|  | 153 | } | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 154 |  | 
| Ted Kremenek | 491918e | 2009-01-23 20:52:26 +0000 | [diff] [blame] | 155 | AnalysisManager(AnalysisConsumer& c, TranslationUnit* tu, | 
|  | 156 | bool displayProgress) | 
|  | 157 | : D(0), Body(0), TU(tu), AScope(ScopeTU), C(c), | 
|  | 158 | DisplayedFunction(!displayProgress) { | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 159 | setManagerCreators(); | 
|  | 160 | } | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 161 |  | 
| Ted Kremenek | f304ddc | 2008-11-05 19:05:06 +0000 | [diff] [blame] | 162 | Decl* getCodeDecl() const { | 
|  | 163 | assert (AScope == ScopeDecl); | 
|  | 164 | return D; | 
|  | 165 | } | 
|  | 166 |  | 
|  | 167 | Stmt* getBody() const { | 
|  | 168 | assert (AScope == ScopeDecl); | 
|  | 169 | return Body; | 
|  | 170 | } | 
|  | 171 |  | 
|  | 172 | TranslationUnit* getTranslationUnit() const { | 
|  | 173 | assert (AScope == ScopeTU); | 
|  | 174 | return TU; | 
|  | 175 | } | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 176 |  | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 177 | StoreManagerCreator getStoreManagerCreator() { | 
|  | 178 | return CreateStoreMgr; | 
| Ted Kremenek | 95c7b00 | 2008-10-24 01:04:59 +0000 | [diff] [blame] | 179 | }; | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 180 |  | 
|  | 181 | ConstraintManagerCreator getConstraintManagerCreator() { | 
|  | 182 | return CreateConstraintMgr; | 
|  | 183 | } | 
| Ted Kremenek | 95c7b00 | 2008-10-24 01:04:59 +0000 | [diff] [blame] | 184 |  | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 185 | virtual CFG* getCFG() { | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 186 | if (!cfg) cfg.reset(CFG::buildCFG(getBody())); | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 187 | return cfg.get(); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 188 | } | 
|  | 189 |  | 
| Ted Kremenek | c095997 | 2008-07-02 21:24:01 +0000 | [diff] [blame] | 190 | virtual ParentMap& getParentMap() { | 
| Ted Kremenek | e207558 | 2008-07-02 23:16:33 +0000 | [diff] [blame] | 191 | if (!PM) | 
|  | 192 | PM.reset(new ParentMap(getBody())); | 
| Ted Kremenek | c095997 | 2008-07-02 21:24:01 +0000 | [diff] [blame] | 193 | return *PM.get(); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 194 | } | 
|  | 195 |  | 
| Ted Kremenek | c095997 | 2008-07-02 21:24:01 +0000 | [diff] [blame] | 196 | virtual ASTContext& getContext() { | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 197 | return *C.Ctx; | 
|  | 198 | } | 
|  | 199 |  | 
| Ted Kremenek | c095997 | 2008-07-02 21:24:01 +0000 | [diff] [blame] | 200 | virtual SourceManager& getSourceManager() { | 
| Ted Kremenek | 235e031 | 2008-07-02 18:11:29 +0000 | [diff] [blame] | 201 | return getContext().getSourceManager(); | 
|  | 202 | } | 
|  | 203 |  | 
| Ted Kremenek | c095997 | 2008-07-02 21:24:01 +0000 | [diff] [blame] | 204 | virtual Diagnostic& getDiagnostic() { | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 205 | return C.Diags; | 
|  | 206 | } | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 207 |  | 
|  | 208 | const LangOptions& getLangOptions() const { | 
|  | 209 | return C.LOpts; | 
|  | 210 | } | 
|  | 211 |  | 
| Ted Kremenek | c095997 | 2008-07-02 21:24:01 +0000 | [diff] [blame] | 212 | virtual PathDiagnosticClient* getPathDiagnosticClient() { | 
| Ted Kremenek | 4fc82c8 | 2008-11-03 23:18:07 +0000 | [diff] [blame] | 213 | if (C.PD.get() == 0 && !C.HTMLDir.empty()) { | 
|  | 214 | switch (C.DC) { | 
|  | 215 | default: | 
| Ted Kremenek | c472d79 | 2009-01-23 20:06:20 +0000 | [diff] [blame] | 216 | #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\ | 
| Ted Kremenek | 4fc82c8 | 2008-11-03 23:18:07 +0000 | [diff] [blame] | 217 | case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break; | 
|  | 218 | #include "Analyses.def" | 
|  | 219 | } | 
|  | 220 | } | 
| Ted Kremenek | e207558 | 2008-07-02 23:16:33 +0000 | [diff] [blame] | 221 | return C.PD.get(); | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 222 | } | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 223 |  | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 224 | virtual LiveVariables* getLiveVariables() { | 
| Ted Kremenek | 235e031 | 2008-07-02 18:11:29 +0000 | [diff] [blame] | 225 | if (!liveness) { | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 226 | CFG* c = getCFG(); | 
|  | 227 | if (!c) return 0; | 
|  | 228 |  | 
| Ted Kremenek | ca9bab0 | 2008-12-09 00:17:51 +0000 | [diff] [blame] | 229 | liveness.reset(new LiveVariables(getContext(), *c)); | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 230 | liveness->runOnCFG(*c); | 
|  | 231 | liveness->runOnAllBlocks(*c, 0, true); | 
| Ted Kremenek | 235e031 | 2008-07-02 18:11:29 +0000 | [diff] [blame] | 232 | } | 
| Ted Kremenek | c095997 | 2008-07-02 21:24:01 +0000 | [diff] [blame] | 233 |  | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 234 | return liveness.get(); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 235 | } | 
| Ted Kremenek | 34d7734 | 2008-07-02 16:49:11 +0000 | [diff] [blame] | 236 |  | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 237 | bool shouldVisualizeGraphviz() const { | 
|  | 238 | return C.VisGraphviz; | 
|  | 239 | } | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 240 |  | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 241 | bool shouldVisualizeUbigraph() const { | 
|  | 242 | return C.VisUbigraph; | 
|  | 243 | } | 
|  | 244 |  | 
| Ted Kremenek | 34d7734 | 2008-07-02 16:49:11 +0000 | [diff] [blame] | 245 | bool shouldVisualize() const { | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 246 | return C.VisGraphviz || C.VisUbigraph; | 
| Ted Kremenek | 34d7734 | 2008-07-02 16:49:11 +0000 | [diff] [blame] | 247 | } | 
|  | 248 |  | 
|  | 249 | bool shouldTrimGraph() const { | 
|  | 250 | return C.TrimGraph; | 
|  | 251 | } | 
|  | 252 |  | 
|  | 253 | void DisplayFunction() { | 
|  | 254 |  | 
|  | 255 | if (DisplayedFunction) | 
|  | 256 | return; | 
|  | 257 |  | 
|  | 258 | DisplayedFunction = true; | 
|  | 259 |  | 
| Chris Lattner | b9c3f96 | 2009-01-27 07:57:44 +0000 | [diff] [blame] | 260 | // FIXME: Is getCodeDecl() always a named decl? | 
|  | 261 | if (isa<FunctionDecl>(getCodeDecl()) || | 
|  | 262 | isa<ObjCMethodDecl>(getCodeDecl())) { | 
|  | 263 | NamedDecl *ND = cast<NamedDecl>(getCodeDecl()); | 
|  | 264 | SourceManager &SM = getContext().getSourceManager(); | 
| Ted Kremenek | a88fcef | 2008-11-20 16:14:48 +0000 | [diff] [blame] | 265 | llvm::cerr << "ANALYZE: " | 
| Chris Lattner | b9c3f96 | 2009-01-27 07:57:44 +0000 | [diff] [blame] | 266 | << SM.getPresumedLoc(ND->getLocation()).getFilename() | 
|  | 267 | << ' ' << ND->getNameAsString() << '\n'; | 
| Ted Kremenek | 34d7734 | 2008-07-02 16:49:11 +0000 | [diff] [blame] | 268 | } | 
|  | 269 | } | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 270 |  | 
|  | 271 | private: | 
|  | 272 | /// Set configurable analyzer components creators. First check if there are | 
|  | 273 | /// components registered at runtime. Otherwise fall back to builtin | 
|  | 274 | /// components. | 
|  | 275 | void setManagerCreators() { | 
|  | 276 | if (ManagerRegistry::StoreMgrCreator != 0) { | 
|  | 277 | CreateStoreMgr = ManagerRegistry::StoreMgrCreator; | 
|  | 278 | } | 
|  | 279 | else { | 
|  | 280 | switch (C.SM) { | 
|  | 281 | default: | 
|  | 282 | assert(0 && "Unknown store manager."); | 
|  | 283 | #define ANALYSIS_STORE(NAME, CMDFLAG, DESC)     \ | 
|  | 284 | case NAME##Model: CreateStoreMgr = Create##NAME##Manager; break; | 
|  | 285 | #include "Analyses.def" | 
|  | 286 | } | 
|  | 287 | } | 
|  | 288 |  | 
|  | 289 | if (ManagerRegistry::ConstraintMgrCreator != 0) | 
|  | 290 | CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator; | 
|  | 291 | else | 
|  | 292 | CreateConstraintMgr = CreateBasicConstraintManager; | 
| Ted Kremenek | c472d79 | 2009-01-23 20:06:20 +0000 | [diff] [blame] | 293 |  | 
|  | 294 | // Some DiagnosticClients should be created all the time instead of | 
|  | 295 | // lazily.  Create those now. | 
|  | 296 | switch (C.DC) { | 
|  | 297 | default: break; | 
|  | 298 | #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\ | 
|  | 299 | case PD_##NAME: if (AUTOCREATE) getPathDiagnosticClient(); break; | 
|  | 300 | #include "Analyses.def" | 
|  | 301 | } | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 302 | } | 
|  | 303 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 304 | }; | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 305 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 306 | } // end anonymous namespace | 
|  | 307 |  | 
|  | 308 | namespace llvm { | 
|  | 309 | template <> struct FoldingSetTrait<CodeAction> { | 
|  | 310 | static inline void Profile(CodeAction X, FoldingSetNodeID& ID) { | 
|  | 311 | ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X))); | 
|  | 312 | } | 
|  | 313 | }; | 
|  | 314 | } | 
|  | 315 |  | 
|  | 316 | //===----------------------------------------------------------------------===// | 
|  | 317 | // AnalysisConsumer implementation. | 
|  | 318 | //===----------------------------------------------------------------------===// | 
|  | 319 |  | 
|  | 320 | void AnalysisConsumer::HandleTopLevelDecl(Decl *D) { | 
|  | 321 | switch (D->getKind()) { | 
|  | 322 | case Decl::Function: { | 
|  | 323 | FunctionDecl* FD = cast<FunctionDecl>(D); | 
| Ted Kremenek | 235e031 | 2008-07-02 18:11:29 +0000 | [diff] [blame] | 324 |  | 
|  | 325 | if (FName.size() > 0 && FName != FD->getIdentifier()->getName()) | 
|  | 326 | break; | 
|  | 327 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 328 | Stmt* Body = FD->getBody(); | 
|  | 329 | if (Body) HandleCode(FD, Body, FunctionActions); | 
|  | 330 | break; | 
|  | 331 | } | 
|  | 332 |  | 
|  | 333 | case Decl::ObjCMethod: { | 
|  | 334 | ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D); | 
| Ted Kremenek | 235e031 | 2008-07-02 18:11:29 +0000 | [diff] [blame] | 335 |  | 
| Chris Lattner | 077bf5e | 2008-11-24 03:33:13 +0000 | [diff] [blame] | 336 | if (FName.size() > 0 && FName != MD->getSelector().getAsString()) | 
| Ted Kremenek | 235e031 | 2008-07-02 18:11:29 +0000 | [diff] [blame] | 337 | return; | 
|  | 338 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 339 | Stmt* Body = MD->getBody(); | 
|  | 340 | if (Body) HandleCode(MD, Body, ObjCMethodActions); | 
|  | 341 | break; | 
|  | 342 | } | 
|  | 343 |  | 
|  | 344 | default: | 
|  | 345 | break; | 
|  | 346 | } | 
|  | 347 | } | 
|  | 348 |  | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 349 | void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) { | 
|  | 350 |  | 
| Ted Kremenek | daac634 | 2008-11-07 02:09:25 +0000 | [diff] [blame] | 351 | if(!TranslationUnitActions.empty()) { | 
| Ted Kremenek | 491918e | 2009-01-23 20:52:26 +0000 | [diff] [blame] | 352 | AnalysisManager mgr(*this, &TU, DisplayProgress); | 
| Ted Kremenek | daac634 | 2008-11-07 02:09:25 +0000 | [diff] [blame] | 353 | for (Actions::iterator I = TranslationUnitActions.begin(), | 
|  | 354 | E = TranslationUnitActions.end(); I != E; ++I) | 
|  | 355 | (*I)(mgr); | 
|  | 356 | } | 
|  | 357 |  | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 358 | if (ObjCImplementationActions.empty()) | 
|  | 359 | return; | 
|  | 360 |  | 
|  | 361 | for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) { | 
|  | 362 |  | 
|  | 363 | if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I)) | 
|  | 364 | HandleCode(ID, 0, ObjCImplementationActions); | 
|  | 365 | } | 
|  | 366 | } | 
|  | 367 |  | 
| Ted Kremenek | 81922f0 | 2009-02-02 20:52:40 +0000 | [diff] [blame^] | 368 | void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions& actions) { | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 369 |  | 
|  | 370 | // Don't run the actions if an error has occured with parsing the file. | 
|  | 371 | if (Diags.hasErrorOccurred()) | 
|  | 372 | return; | 
| Ted Kremenek | 81922f0 | 2009-02-02 20:52:40 +0000 | [diff] [blame^] | 373 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 374 | // Don't run the actions on declarations in header files unless | 
|  | 375 | // otherwise specified. | 
| Ted Kremenek | 81922f0 | 2009-02-02 20:52:40 +0000 | [diff] [blame^] | 376 | if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(D->getLocation())) | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 377 | return; | 
|  | 378 |  | 
|  | 379 | // Create an AnalysisManager that will manage the state for analyzing | 
|  | 380 | // this method/function. | 
| Ted Kremenek | 491918e | 2009-01-23 20:52:26 +0000 | [diff] [blame] | 381 | AnalysisManager mgr(*this, D, Body, DisplayProgress); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 382 |  | 
|  | 383 | // Dispatch on the actions. | 
| Zhongxing Xu | 3702af5 | 2008-10-30 05:03:28 +0000 | [diff] [blame] | 384 | for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I) | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 385 | (*I)(mgr); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 386 | } | 
|  | 387 |  | 
|  | 388 | //===----------------------------------------------------------------------===// | 
|  | 389 | // Analyses | 
|  | 390 | //===----------------------------------------------------------------------===// | 
|  | 391 |  | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 392 | static void ActionWarnDeadStores(AnalysisManager& mgr) { | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 393 | if (LiveVariables* L = mgr.getLiveVariables()) { | 
|  | 394 | BugReporter BR(mgr); | 
|  | 395 | CheckDeadStores(*L, BR); | 
|  | 396 | } | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 397 | } | 
|  | 398 |  | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 399 | static void ActionWarnUninitVals(AnalysisManager& mgr) { | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 400 | if (CFG* c = mgr.getCFG()) | 
|  | 401 | CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic()); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 402 | } | 
|  | 403 |  | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 404 |  | 
| Ted Kremenek | 78d4624 | 2008-07-22 16:21:24 +0000 | [diff] [blame] | 405 | static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf, | 
|  | 406 | bool StandardWarnings = true) { | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 407 |  | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 408 |  | 
| Ted Kremenek | bc46f34 | 2008-07-02 16:35:50 +0000 | [diff] [blame] | 409 | llvm::OwningPtr<GRTransferFuncs> TF(tf); | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 410 |  | 
| Ted Kremenek | 8ffc8a5 | 2008-11-24 20:53:32 +0000 | [diff] [blame] | 411 | // Display progress. | 
|  | 412 | mgr.DisplayFunction(); | 
|  | 413 |  | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 414 | // Construct the analysis engine. | 
|  | 415 | LiveVariables* L = mgr.getLiveVariables(); | 
|  | 416 | if (!L) return; | 
| Ted Kremenek | 8ffc8a5 | 2008-11-24 20:53:32 +0000 | [diff] [blame] | 417 |  | 
| Ted Kremenek | 95c7b00 | 2008-10-24 01:04:59 +0000 | [diff] [blame] | 418 | GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L, | 
| Zhongxing Xu | ff944a8 | 2008-12-22 01:52:37 +0000 | [diff] [blame] | 419 | PurgeDead, | 
| Zhongxing Xu | 22438a8 | 2008-11-27 01:55:08 +0000 | [diff] [blame] | 420 | mgr.getStoreManagerCreator(), | 
|  | 421 | mgr.getConstraintManagerCreator()); | 
| Ted Kremenek | 95c7b00 | 2008-10-24 01:04:59 +0000 | [diff] [blame] | 422 |  | 
| Ted Kremenek | bc46f34 | 2008-07-02 16:35:50 +0000 | [diff] [blame] | 423 | Eng.setTransferFunctions(tf); | 
|  | 424 |  | 
| Ted Kremenek | 78d4624 | 2008-07-22 16:21:24 +0000 | [diff] [blame] | 425 | if (StandardWarnings) { | 
|  | 426 | Eng.RegisterInternalChecks(); | 
|  | 427 | RegisterAppleChecks(Eng); | 
|  | 428 | } | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 429 |  | 
|  | 430 | // Set the graph auditor. | 
|  | 431 | llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor; | 
|  | 432 | if (mgr.shouldVisualizeUbigraph()) { | 
|  | 433 | Auditor.reset(CreateUbiViz()); | 
|  | 434 | ExplodedNodeImpl::SetAuditor(Auditor.get()); | 
|  | 435 | } | 
| Ted Kremenek | 78d4624 | 2008-07-22 16:21:24 +0000 | [diff] [blame] | 436 |  | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 437 | // Execute the worklist algorithm. | 
|  | 438 | Eng.ExecuteWorkList(); | 
| Ted Kremenek | bc46f34 | 2008-07-02 16:35:50 +0000 | [diff] [blame] | 439 |  | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 440 | // Release the auditor (if any) so that it doesn't monitor the graph | 
|  | 441 | // created BugReporter. | 
|  | 442 | ExplodedNodeImpl::SetAuditor(0); | 
|  | 443 |  | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 444 | // Display warnings. | 
| Ted Kremenek | c095997 | 2008-07-02 21:24:01 +0000 | [diff] [blame] | 445 | Eng.EmitWarnings(mgr); | 
| Ted Kremenek | 34d7734 | 2008-07-02 16:49:11 +0000 | [diff] [blame] | 446 |  | 
|  | 447 | // Visualize the exploded graph. | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 448 | if (mgr.shouldVisualizeGraphviz()) | 
| Ted Kremenek | 34d7734 | 2008-07-02 16:49:11 +0000 | [diff] [blame] | 449 | Eng.ViewGraph(mgr.shouldTrimGraph()); | 
| Ted Kremenek | bc46f34 | 2008-07-02 16:35:50 +0000 | [diff] [blame] | 450 | } | 
|  | 451 |  | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 452 | static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled, | 
| Ted Kremenek | 78d4624 | 2008-07-22 16:21:24 +0000 | [diff] [blame] | 453 | bool StandardWarnings) { | 
|  | 454 |  | 
| Ted Kremenek | bc46f34 | 2008-07-02 16:35:50 +0000 | [diff] [blame] | 455 | GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(), | 
|  | 456 | GCEnabled, | 
| Ted Kremenek | bc46f34 | 2008-07-02 16:35:50 +0000 | [diff] [blame] | 457 | mgr.getLangOptions()); | 
|  | 458 |  | 
| Ted Kremenek | 78d4624 | 2008-07-22 16:21:24 +0000 | [diff] [blame] | 459 | ActionGRExprEngine(mgr, TF, StandardWarnings); | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 460 | } | 
|  | 461 |  | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 462 | static void ActionCheckerCFRef(AnalysisManager& mgr) { | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 463 |  | 
|  | 464 | switch (mgr.getLangOptions().getGCMode()) { | 
|  | 465 | default: | 
|  | 466 | assert (false && "Invalid GC mode."); | 
|  | 467 | case LangOptions::NonGC: | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 468 | ActionCheckerCFRefAux(mgr, false, true); | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 469 | break; | 
|  | 470 |  | 
|  | 471 | case LangOptions::GCOnly: | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 472 | ActionCheckerCFRefAux(mgr, true, true); | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 473 | break; | 
|  | 474 |  | 
|  | 475 | case LangOptions::HybridGC: | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 476 | ActionCheckerCFRefAux(mgr, false, true); | 
|  | 477 | ActionCheckerCFRefAux(mgr, true, false); | 
| Ted Kremenek | b35a74a | 2008-07-02 00:44:58 +0000 | [diff] [blame] | 478 | break; | 
|  | 479 | } | 
|  | 480 | } | 
|  | 481 |  | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 482 | static void ActionCheckerSimple(AnalysisManager& mgr) { | 
| Ted Kremenek | bc46f34 | 2008-07-02 16:35:50 +0000 | [diff] [blame] | 483 | ActionGRExprEngine(mgr, MakeGRSimpleValsTF()); | 
|  | 484 | } | 
|  | 485 |  | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 486 | static void ActionDisplayLiveVariables(AnalysisManager& mgr) { | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 487 | if (LiveVariables* L = mgr.getLiveVariables()) { | 
|  | 488 | mgr.DisplayFunction(); | 
|  | 489 | L->dumpBlockLiveness(mgr.getSourceManager()); | 
|  | 490 | } | 
| Ted Kremenek | 235e031 | 2008-07-02 18:11:29 +0000 | [diff] [blame] | 491 | } | 
|  | 492 |  | 
| Ted Kremenek | 902141f | 2008-07-02 18:23:21 +0000 | [diff] [blame] | 493 | static void ActionCFGDump(AnalysisManager& mgr) { | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 494 | if (CFG* c = mgr.getCFG()) { | 
|  | 495 | mgr.DisplayFunction(); | 
|  | 496 | c->dump(); | 
|  | 497 | } | 
| Ted Kremenek | 902141f | 2008-07-02 18:23:21 +0000 | [diff] [blame] | 498 | } | 
|  | 499 |  | 
|  | 500 | static void ActionCFGView(AnalysisManager& mgr) { | 
| Ted Kremenek | 7032f46 | 2008-07-03 05:26:14 +0000 | [diff] [blame] | 501 | if (CFG* c = mgr.getCFG()) { | 
|  | 502 | mgr.DisplayFunction(); | 
|  | 503 | c->viewCFG(); | 
|  | 504 | } | 
| Ted Kremenek | 902141f | 2008-07-02 18:23:21 +0000 | [diff] [blame] | 505 | } | 
|  | 506 |  | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 507 | static void ActionWarnObjCDealloc(AnalysisManager& mgr) { | 
| Ted Kremenek | 4f4e7e4 | 2008-08-04 17:14:10 +0000 | [diff] [blame] | 508 | if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly) | 
|  | 509 | return; | 
|  | 510 |  | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 511 | BugReporter BR(mgr); | 
| Ted Kremenek | 3cd483c | 2008-07-03 14:35:01 +0000 | [diff] [blame] | 512 |  | 
|  | 513 | CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), | 
|  | 514 | mgr.getLangOptions(), BR); | 
| Ted Kremenek | db09a4d | 2008-07-03 04:29:21 +0000 | [diff] [blame] | 515 | } | 
|  | 516 |  | 
| Ted Kremenek | 395aaf2 | 2008-07-23 00:45:26 +0000 | [diff] [blame] | 517 | static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) { | 
|  | 518 | BugReporter BR(mgr); | 
|  | 519 | CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR); | 
|  | 520 | } | 
|  | 521 |  | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 522 | static void ActionWarnObjCMethSigs(AnalysisManager& mgr) { | 
| Ted Kremenek | 0d8019e | 2008-07-11 22:40:47 +0000 | [diff] [blame] | 523 | BugReporter BR(mgr); | 
|  | 524 |  | 
|  | 525 | CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), | 
|  | 526 | BR); | 
|  | 527 | } | 
|  | 528 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 529 | //===----------------------------------------------------------------------===// | 
|  | 530 | // AnalysisConsumer creation. | 
|  | 531 | //===----------------------------------------------------------------------===// | 
|  | 532 |  | 
|  | 533 | ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End, | 
| Ted Kremenek | 95c7b00 | 2008-10-24 01:04:59 +0000 | [diff] [blame] | 534 | AnalysisStores SM, | 
| Ted Kremenek | 4fc82c8 | 2008-11-03 23:18:07 +0000 | [diff] [blame] | 535 | AnalysisDiagClients DC, | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 536 | Diagnostic &diags, Preprocessor* pp, | 
|  | 537 | PreprocessorFactory* ppf, | 
|  | 538 | const LangOptions& lopts, | 
|  | 539 | const std::string& fname, | 
|  | 540 | const std::string& htmldir, | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 541 | bool VisGraphviz, bool VisUbi, | 
|  | 542 | bool trim, | 
| Ted Kremenek | 491918e | 2009-01-23 20:52:26 +0000 | [diff] [blame] | 543 | bool analyzeAll, | 
|  | 544 | bool displayProgress) { | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 545 |  | 
|  | 546 | llvm::OwningPtr<AnalysisConsumer> | 
| Ted Kremenek | 4fc82c8 | 2008-11-03 23:18:07 +0000 | [diff] [blame] | 547 | C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir, SM, DC, | 
| Ted Kremenek | 491918e | 2009-01-23 20:52:26 +0000 | [diff] [blame] | 548 | VisGraphviz, VisUbi, trim, analyzeAll, | 
|  | 549 | displayProgress)); | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 550 |  | 
|  | 551 | for ( ; Beg != End ; ++Beg) | 
|  | 552 | switch (*Beg) { | 
| Ted Kremenek | f7f3c20 | 2008-07-15 00:46:02 +0000 | [diff] [blame] | 553 | #define ANALYSIS(NAME, CMD, DESC, SCOPE)\ | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 554 | case NAME:\ | 
| Ted Kremenek | f7f3c20 | 2008-07-15 00:46:02 +0000 | [diff] [blame] | 555 | C->add ## SCOPE ## Action(&Action ## NAME);\ | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 556 | break; | 
| Ted Kremenek | fb9a48c | 2008-07-14 23:41:13 +0000 | [diff] [blame] | 557 | #include "Analyses.def" | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 558 | default: break; | 
|  | 559 | } | 
|  | 560 |  | 
| Ted Kremenek | f4381fd | 2008-07-02 00:03:09 +0000 | [diff] [blame] | 561 | return C.take(); | 
|  | 562 | } | 
|  | 563 |  | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 564 | //===----------------------------------------------------------------------===// | 
|  | 565 | // Ubigraph Visualization.  FIXME: Move to separate file. | 
|  | 566 | //===----------------------------------------------------------------------===// | 
|  | 567 |  | 
|  | 568 | namespace { | 
|  | 569 |  | 
|  | 570 | class UbigraphViz : public ExplodedNodeImpl::Auditor { | 
|  | 571 | llvm::OwningPtr<llvm::raw_ostream> Out; | 
| Ted Kremenek | 710ad93 | 2008-08-28 03:54:51 +0000 | [diff] [blame] | 572 | llvm::sys::Path Dir, Filename; | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 573 | unsigned Cntr; | 
|  | 574 |  | 
|  | 575 | typedef llvm::DenseMap<void*,unsigned> VMap; | 
|  | 576 | VMap M; | 
|  | 577 |  | 
|  | 578 | public: | 
| Ted Kremenek | 710ad93 | 2008-08-28 03:54:51 +0000 | [diff] [blame] | 579 | UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir, | 
| Ted Kremenek | 56b9871 | 2008-08-28 05:02:09 +0000 | [diff] [blame] | 580 | llvm::sys::Path& filename); | 
| Ted Kremenek | 710ad93 | 2008-08-28 03:54:51 +0000 | [diff] [blame] | 581 |  | 
|  | 582 | ~UbigraphViz(); | 
|  | 583 |  | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 584 | virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst); | 
|  | 585 | }; | 
|  | 586 |  | 
|  | 587 | } // end anonymous namespace | 
|  | 588 |  | 
|  | 589 | static ExplodedNodeImpl::Auditor* CreateUbiViz() { | 
|  | 590 | std::string ErrMsg; | 
|  | 591 |  | 
| Ted Kremenek | 710ad93 | 2008-08-28 03:54:51 +0000 | [diff] [blame] | 592 | llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg); | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 593 | if (!ErrMsg.empty()) | 
|  | 594 | return 0; | 
|  | 595 |  | 
| Ted Kremenek | 710ad93 | 2008-08-28 03:54:51 +0000 | [diff] [blame] | 596 | llvm::sys::Path Filename = Dir; | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 597 | Filename.appendComponent("llvm_ubi"); | 
|  | 598 | Filename.makeUnique(true,&ErrMsg); | 
|  | 599 |  | 
|  | 600 | if (!ErrMsg.empty()) | 
|  | 601 | return 0; | 
|  | 602 |  | 
|  | 603 | llvm::cerr << "Writing '" << Filename << "'.\n"; | 
|  | 604 |  | 
|  | 605 | llvm::OwningPtr<llvm::raw_fd_ostream> Stream; | 
|  | 606 | std::string filename = Filename.toString(); | 
| Daniel Dunbar | 26fb272 | 2008-11-13 05:09:21 +0000 | [diff] [blame] | 607 | Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), false, ErrMsg)); | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 608 |  | 
|  | 609 | if (!ErrMsg.empty()) | 
|  | 610 | return 0; | 
|  | 611 |  | 
| Ted Kremenek | 710ad93 | 2008-08-28 03:54:51 +0000 | [diff] [blame] | 612 | return new UbigraphViz(Stream.take(), Dir, Filename); | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 613 | } | 
|  | 614 |  | 
|  | 615 | void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) { | 
| Ted Kremenek | 45479c8 | 2008-08-28 18:34:41 +0000 | [diff] [blame] | 616 |  | 
|  | 617 | assert (Src != Dst && "Self-edges are not allowed."); | 
|  | 618 |  | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 619 | // Lookup the Src.  If it is a new node, it's a root. | 
|  | 620 | VMap::iterator SrcI= M.find(Src); | 
|  | 621 | unsigned SrcID; | 
|  | 622 |  | 
|  | 623 | if (SrcI == M.end()) { | 
|  | 624 | M[Src] = SrcID = Cntr++; | 
|  | 625 | *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n"; | 
|  | 626 | } | 
|  | 627 | else | 
|  | 628 | SrcID = SrcI->second; | 
|  | 629 |  | 
|  | 630 | // Lookup the Dst. | 
|  | 631 | VMap::iterator DstI= M.find(Dst); | 
|  | 632 | unsigned DstID; | 
|  | 633 |  | 
|  | 634 | if (DstI == M.end()) { | 
|  | 635 | M[Dst] = DstID = Cntr++; | 
|  | 636 | *Out << "('vertex', " << DstID << ")\n"; | 
|  | 637 | } | 
| Ted Kremenek | 56b9871 | 2008-08-28 05:02:09 +0000 | [diff] [blame] | 638 | else { | 
|  | 639 | // We have hit DstID before.  Change its style to reflect a cache hit. | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 640 | DstID = DstI->second; | 
| Ted Kremenek | 56b9871 | 2008-08-28 05:02:09 +0000 | [diff] [blame] | 641 | *Out << "('change_vertex_style', " << DstID << ", 1)\n"; | 
|  | 642 | } | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 643 |  | 
|  | 644 | // Add the edge. | 
| Ted Kremenek | d128932 | 2008-08-27 22:46:55 +0000 | [diff] [blame] | 645 | *Out << "('edge', " << SrcID << ", " << DstID | 
|  | 646 | << ", ('arrow','true'), ('oriented', 'true'))\n"; | 
| Ted Kremenek | f8ce699 | 2008-08-27 22:31:43 +0000 | [diff] [blame] | 647 | } | 
|  | 648 |  | 
| Ted Kremenek | 56b9871 | 2008-08-28 05:02:09 +0000 | [diff] [blame] | 649 | UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir, | 
|  | 650 | llvm::sys::Path& filename) | 
|  | 651 | : Out(out), Dir(dir), Filename(filename), Cntr(0) { | 
|  | 652 |  | 
|  | 653 | *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n"; | 
|  | 654 | *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66')," | 
|  | 655 | " ('size', '1.5'))\n"; | 
|  | 656 | } | 
|  | 657 |  | 
| Ted Kremenek | 710ad93 | 2008-08-28 03:54:51 +0000 | [diff] [blame] | 658 | UbigraphViz::~UbigraphViz() { | 
|  | 659 | Out.reset(0); | 
|  | 660 | llvm::cerr << "Running 'ubiviz' program... "; | 
|  | 661 | std::string ErrMsg; | 
|  | 662 | llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz"); | 
|  | 663 | std::vector<const char*> args; | 
|  | 664 | args.push_back(Ubiviz.c_str()); | 
|  | 665 | args.push_back(Filename.c_str()); | 
|  | 666 | args.push_back(0); | 
|  | 667 |  | 
|  | 668 | if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) { | 
|  | 669 | llvm::cerr << "Error viewing graph: " << ErrMsg << "\n"; | 
|  | 670 | } | 
|  | 671 |  | 
|  | 672 | // Delete the directory. | 
|  | 673 | Dir.eraseFromDisk(true); | 
| Daniel Dunbar | 932680e | 2008-08-29 03:45:59 +0000 | [diff] [blame] | 674 | } |