blob: 81f14554fa86e1cccbc33d08cc886e31291465d0 [file] [log] [blame]
Ted Kremenekf4381fd2008-07-02 00:03:09 +00001//===--- 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"
Zhongxing Xu81488392008-08-24 02:33:36 +000015#include "clang/Driver/HTMLDiagnostics.h"
Ted Kremenekf4381fd2008-07-02 00:03:09 +000016#include "clang/AST/ASTConsumer.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/DeclObjC.h"
19#include "llvm/Support/Compiler.h"
Ted Kremenekf4381fd2008-07-02 00:03:09 +000020#include "llvm/ADT/OwningPtr.h"
21#include "clang/AST/CFG.h"
22#include "clang/Analysis/Analyses/LiveVariables.h"
23#include "clang/Analysis/PathDiagnostic.h"
24#include "clang/Basic/SourceManager.h"
25#include "clang/Basic/FileManager.h"
26#include "clang/AST/ParentMap.h"
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000027#include "clang/AST/TranslationUnit.h"
Ted Kremenekc0959972008-07-02 21:24:01 +000028#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenekf4381fd2008-07-02 00:03:09 +000029#include "clang/Analysis/Analyses/LiveVariables.h"
30#include "clang/Analysis/LocalCheckers.h"
31#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
32#include "clang/Analysis/PathSensitive/GRExprEngine.h"
Ted Kremenek34d77342008-07-02 16:49:11 +000033#include "llvm/Support/Streams.h"
Ted Kremenekf8ce6992008-08-27 22:31:43 +000034#include "llvm/Support/raw_ostream.h"
35#include "llvm/System/Path.h"
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000036#include <vector>
37
Ted Kremenekf4381fd2008-07-02 00:03:09 +000038using namespace clang;
39
Ted Kremenekf8ce6992008-08-27 22:31:43 +000040static ExplodedNodeImpl::Auditor* CreateUbiViz();
Ted Kremenekf4381fd2008-07-02 00:03:09 +000041
42//===----------------------------------------------------------------------===//
43// Basic type definitions.
44//===----------------------------------------------------------------------===//
45
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000046namespace {
Ted Kremenekf4381fd2008-07-02 00:03:09 +000047 class AnalysisManager;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000048 typedef void (*CodeAction)(AnalysisManager& Mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +000049} // end anonymous namespace
50
51//===----------------------------------------------------------------------===//
52// AnalysisConsumer declaration.
53//===----------------------------------------------------------------------===//
54
55namespace {
56
57 class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000058 typedef std::vector<CodeAction> Actions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000059 Actions FunctionActions;
60 Actions ObjCMethodActions;
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000061 Actions ObjCImplementationActions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000062
63 public:
Ted Kremenekf8ce6992008-08-27 22:31:43 +000064 const bool VisGraphviz;
65 const bool VisUbigraph;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000066 const bool TrimGraph;
67 const LangOptions& LOpts;
68 Diagnostic &Diags;
69 ASTContext* Ctx;
70 Preprocessor* PP;
71 PreprocessorFactory* PPF;
72 const std::string HTMLDir;
73 const std::string FName;
74 llvm::OwningPtr<PathDiagnosticClient> PD;
75 bool AnalyzeAll;
76
77 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
78 PreprocessorFactory* ppf,
79 const LangOptions& lopts,
80 const std::string& fname,
81 const std::string& htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +000082 bool visgraphviz, bool visubi, bool trim, bool analyzeAll)
83 : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
84 LOpts(lopts), Diags(diags),
Ted Kremenekf4381fd2008-07-02 00:03:09 +000085 Ctx(0), PP(pp), PPF(ppf),
86 HTMLDir(htmldir),
87 FName(fname),
88 AnalyzeAll(analyzeAll) {}
89
90 void addCodeAction(CodeAction action) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000091 FunctionActions.push_back(action);
92 ObjCMethodActions.push_back(action);
93 }
94
95 void addObjCImplementationAction(CodeAction action) {
96 ObjCImplementationActions.push_back(action);
Ted Kremenekf4381fd2008-07-02 00:03:09 +000097 }
98
99 virtual void Initialize(ASTContext &Context) {
100 Ctx = &Context;
101 }
102
103 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000104 virtual void HandleTranslationUnit(TranslationUnit &TU);
105
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000106 void HandleCode(Decl* D, Stmt* Body, Actions actions);
107 };
108
109
Ted Kremenekc0959972008-07-02 21:24:01 +0000110 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000111 Decl* D;
112 Stmt* Body;
113 AnalysisConsumer& C;
Ted Kremenek34d77342008-07-02 16:49:11 +0000114 bool DisplayedFunction;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000115
116 llvm::OwningPtr<CFG> cfg;
117 llvm::OwningPtr<LiveVariables> liveness;
118 llvm::OwningPtr<ParentMap> PM;
119
120 public:
121 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
Ted Kremenek34d77342008-07-02 16:49:11 +0000122 : D(d), Body(b), C(c), DisplayedFunction(false) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000123
124
125 Decl* getCodeDecl() const { return D; }
126 Stmt* getBody() const { return Body; }
127
Ted Kremenek7032f462008-07-03 05:26:14 +0000128 virtual CFG* getCFG() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000129 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenek7032f462008-07-03 05:26:14 +0000130 return cfg.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000131 }
132
Ted Kremenekc0959972008-07-02 21:24:01 +0000133 virtual ParentMap& getParentMap() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000134 if (!PM)
135 PM.reset(new ParentMap(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000136 return *PM.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000137 }
138
Ted Kremenekc0959972008-07-02 21:24:01 +0000139 virtual ASTContext& getContext() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000140 return *C.Ctx;
141 }
142
Ted Kremenekc0959972008-07-02 21:24:01 +0000143 virtual SourceManager& getSourceManager() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000144 return getContext().getSourceManager();
145 }
146
Ted Kremenekc0959972008-07-02 21:24:01 +0000147 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000148 return C.Diags;
149 }
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000150
151 const LangOptions& getLangOptions() const {
152 return C.LOpts;
153 }
154
Ted Kremenekc0959972008-07-02 21:24:01 +0000155 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000156 if (C.PD.get() == 0 && !C.HTMLDir.empty())
157 C.PD.reset(CreateHTMLDiagnosticClient(C.HTMLDir, C.PP, C.PPF));
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000158
Ted Kremeneke2075582008-07-02 23:16:33 +0000159 return C.PD.get();
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000160 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000161
Ted Kremenek7032f462008-07-03 05:26:14 +0000162 virtual LiveVariables* getLiveVariables() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000163 if (!liveness) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000164 CFG* c = getCFG();
165 if (!c) return 0;
166
167 liveness.reset(new LiveVariables(*c));
168 liveness->runOnCFG(*c);
169 liveness->runOnAllBlocks(*c, 0, true);
Ted Kremenek235e0312008-07-02 18:11:29 +0000170 }
Ted Kremenekc0959972008-07-02 21:24:01 +0000171
Ted Kremenek7032f462008-07-03 05:26:14 +0000172 return liveness.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000173 }
Ted Kremenek34d77342008-07-02 16:49:11 +0000174
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000175 bool shouldVisualizeGraphviz() const {
176 return C.VisGraphviz;
177 }
178
179 bool shouldVisualizeUbigraph() const {
180 return C.VisUbigraph;
181 }
182
Ted Kremenek34d77342008-07-02 16:49:11 +0000183 bool shouldVisualize() const {
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000184 return C.VisGraphviz || C.VisUbigraph;
Ted Kremenek34d77342008-07-02 16:49:11 +0000185 }
186
187 bool shouldTrimGraph() const {
188 return C.TrimGraph;
189 }
190
191 void DisplayFunction() {
192
193 if (DisplayedFunction)
194 return;
195
196 DisplayedFunction = true;
197
198 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(getCodeDecl())) {
199 llvm::cerr << "ANALYZE: "
200 << getContext().getSourceManager().getSourceName(FD->getLocation())
201 << ' '
202 << FD->getIdentifier()->getName()
203 << '\n';
204 }
205 else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCodeDecl())) {
206 llvm::cerr << "ANALYZE (ObjC Method): "
207 << getContext().getSourceManager().getSourceName(MD->getLocation())
208 << " '"
209 << MD->getSelector().getName() << "'\n";
210 }
211 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000212 };
213
214} // end anonymous namespace
215
216namespace llvm {
217 template <> struct FoldingSetTrait<CodeAction> {
218 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
219 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
220 }
221 };
222}
223
224//===----------------------------------------------------------------------===//
225// AnalysisConsumer implementation.
226//===----------------------------------------------------------------------===//
227
228void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
229 switch (D->getKind()) {
230 case Decl::Function: {
231 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000232
233 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
234 break;
235
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000236 Stmt* Body = FD->getBody();
237 if (Body) HandleCode(FD, Body, FunctionActions);
238 break;
239 }
240
241 case Decl::ObjCMethod: {
242 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000243
244 if (FName.size() > 0 && FName != MD->getSelector().getName())
245 return;
246
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000247 Stmt* Body = MD->getBody();
248 if (Body) HandleCode(MD, Body, ObjCMethodActions);
249 break;
250 }
251
252 default:
253 break;
254 }
255}
256
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000257void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
258
259 if (ObjCImplementationActions.empty())
260 return;
261
262 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) {
263
264 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
265 HandleCode(ID, 0, ObjCImplementationActions);
266 }
267}
268
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000269void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
270
271 // Don't run the actions if an error has occured with parsing the file.
272 if (Diags.hasErrorOccurred())
273 return;
274
275 SourceLocation Loc = D->getLocation();
276
277 // Only run actions on declarations defined in actual source.
278 if (!Loc.isFileID())
279 return;
280
281 // Don't run the actions on declarations in header files unless
282 // otherwise specified.
283 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
284 return;
285
286 // Create an AnalysisManager that will manage the state for analyzing
287 // this method/function.
288 AnalysisManager mgr(*this, D, Body);
289
290 // Dispatch on the actions.
Ted Kremenekc0959972008-07-02 21:24:01 +0000291 for (Actions::iterator I = actions.begin(),
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000292 E = actions.end(); I != E; ++I)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000293 (*I)(mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000294}
295
296//===----------------------------------------------------------------------===//
297// Analyses
298//===----------------------------------------------------------------------===//
299
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000300static void ActionWarnDeadStores(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000301 if (LiveVariables* L = mgr.getLiveVariables()) {
302 BugReporter BR(mgr);
303 CheckDeadStores(*L, BR);
304 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000305}
306
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000307static void ActionWarnUninitVals(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000308 if (CFG* c = mgr.getCFG())
309 CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000310}
311
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000312
Ted Kremenek78d46242008-07-22 16:21:24 +0000313static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
314 bool StandardWarnings = true) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000315
Ted Kremenek7032f462008-07-03 05:26:14 +0000316
Ted Kremenekbc46f342008-07-02 16:35:50 +0000317 llvm::OwningPtr<GRTransferFuncs> TF(tf);
Ted Kremenek7032f462008-07-03 05:26:14 +0000318
319 // Construct the analysis engine.
320 LiveVariables* L = mgr.getLiveVariables();
321 if (!L) return;
Ted Kremenekbc46f342008-07-02 16:35:50 +0000322
Ted Kremenek34d77342008-07-02 16:49:11 +0000323 // Display progress.
324 if (!mgr.shouldVisualize())
325 mgr.DisplayFunction();
326
Ted Kremenek7032f462008-07-03 05:26:14 +0000327 GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L);
Ted Kremenekbc46f342008-07-02 16:35:50 +0000328 Eng.setTransferFunctions(tf);
329
Ted Kremenek78d46242008-07-22 16:21:24 +0000330 if (StandardWarnings) {
331 Eng.RegisterInternalChecks();
332 RegisterAppleChecks(Eng);
333 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000334
335 // Set the graph auditor.
336 llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor;
337 if (mgr.shouldVisualizeUbigraph()) {
338 Auditor.reset(CreateUbiViz());
339 ExplodedNodeImpl::SetAuditor(Auditor.get());
340 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000341
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000342 // Execute the worklist algorithm.
343 Eng.ExecuteWorkList();
Ted Kremenekbc46f342008-07-02 16:35:50 +0000344
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000345 // Release the auditor (if any) so that it doesn't monitor the graph
346 // created BugReporter.
347 ExplodedNodeImpl::SetAuditor(0);
348
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000349 // Display warnings.
Ted Kremenekc0959972008-07-02 21:24:01 +0000350 Eng.EmitWarnings(mgr);
Ted Kremenek34d77342008-07-02 16:49:11 +0000351
352 // Visualize the exploded graph.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000353 if (mgr.shouldVisualizeGraphviz())
Ted Kremenek34d77342008-07-02 16:49:11 +0000354 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000355}
356
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000357static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
Ted Kremenek78d46242008-07-22 16:21:24 +0000358 bool StandardWarnings) {
359
Ted Kremenekbc46f342008-07-02 16:35:50 +0000360 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
361 GCEnabled,
Ted Kremenekbc46f342008-07-02 16:35:50 +0000362 mgr.getLangOptions());
363
Ted Kremenek78d46242008-07-22 16:21:24 +0000364 ActionGRExprEngine(mgr, TF, StandardWarnings);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000365}
366
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000367static void ActionCheckerCFRef(AnalysisManager& mgr) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000368
369 switch (mgr.getLangOptions().getGCMode()) {
370 default:
371 assert (false && "Invalid GC mode.");
372 case LangOptions::NonGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000373 ActionCheckerCFRefAux(mgr, false, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000374 break;
375
376 case LangOptions::GCOnly:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000377 ActionCheckerCFRefAux(mgr, true, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000378 break;
379
380 case LangOptions::HybridGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000381 ActionCheckerCFRefAux(mgr, false, true);
382 ActionCheckerCFRefAux(mgr, true, false);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000383 break;
384 }
385}
386
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000387static void ActionCheckerSimple(AnalysisManager& mgr) {
Ted Kremenekbc46f342008-07-02 16:35:50 +0000388 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
389}
390
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000391static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000392 if (LiveVariables* L = mgr.getLiveVariables()) {
393 mgr.DisplayFunction();
394 L->dumpBlockLiveness(mgr.getSourceManager());
395 }
Ted Kremenek235e0312008-07-02 18:11:29 +0000396}
397
Ted Kremenek902141f2008-07-02 18:23:21 +0000398static void ActionCFGDump(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000399 if (CFG* c = mgr.getCFG()) {
400 mgr.DisplayFunction();
401 c->dump();
402 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000403}
404
405static void ActionCFGView(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000406 if (CFG* c = mgr.getCFG()) {
407 mgr.DisplayFunction();
408 c->viewCFG();
409 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000410}
411
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000412static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
Ted Kremenek4f4e7e42008-08-04 17:14:10 +0000413 if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
414 return;
415
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000416 BugReporter BR(mgr);
Ted Kremenek3cd483c2008-07-03 14:35:01 +0000417
418 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
419 mgr.getLangOptions(), BR);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000420}
421
Ted Kremenek395aaf22008-07-23 00:45:26 +0000422static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
423 BugReporter BR(mgr);
424 CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
425}
426
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000427static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
Ted Kremenek0d8019e2008-07-11 22:40:47 +0000428 BugReporter BR(mgr);
429
430 CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
431 BR);
432}
433
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000434//===----------------------------------------------------------------------===//
435// AnalysisConsumer creation.
436//===----------------------------------------------------------------------===//
437
438ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
439 Diagnostic &diags, Preprocessor* pp,
440 PreprocessorFactory* ppf,
441 const LangOptions& lopts,
442 const std::string& fname,
443 const std::string& htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000444 bool VisGraphviz, bool VisUbi,
445 bool trim,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000446 bool analyzeAll) {
447
448 llvm::OwningPtr<AnalysisConsumer>
449 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000450 VisGraphviz, VisUbi, trim, analyzeAll));
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000451
452 for ( ; Beg != End ; ++Beg)
453 switch (*Beg) {
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000454#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000455 case NAME:\
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000456 C->add ## SCOPE ## Action(&Action ## NAME);\
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000457 break;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000458#include "Analyses.def"
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000459 default: break;
460 }
461
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000462 return C.take();
463}
464
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000465//===----------------------------------------------------------------------===//
466// Ubigraph Visualization. FIXME: Move to separate file.
467//===----------------------------------------------------------------------===//
468
469namespace {
470
471class UbigraphViz : public ExplodedNodeImpl::Auditor {
472 llvm::OwningPtr<llvm::raw_ostream> Out;
473 unsigned Cntr;
474
475 typedef llvm::DenseMap<void*,unsigned> VMap;
476 VMap M;
477
478public:
479 UbigraphViz(llvm::raw_ostream* out) : Out(out), Cntr(0) {}
480 virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
481};
482
483} // end anonymous namespace
484
485static ExplodedNodeImpl::Auditor* CreateUbiViz() {
486 std::string ErrMsg;
487
488 llvm::sys::Path Filename = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
489 if (!ErrMsg.empty())
490 return 0;
491
492 Filename.appendComponent("llvm_ubi");
493 Filename.makeUnique(true,&ErrMsg);
494
495 if (!ErrMsg.empty())
496 return 0;
497
498 llvm::cerr << "Writing '" << Filename << "'.\n";
499
500 llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
501 std::string filename = Filename.toString();
502 Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), ErrMsg));
503
504 if (!ErrMsg.empty())
505 return 0;
506
507 return new UbigraphViz(Stream.take());
508}
509
510void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
511 // Lookup the Src. If it is a new node, it's a root.
512 VMap::iterator SrcI= M.find(Src);
513 unsigned SrcID;
514
515 if (SrcI == M.end()) {
516 M[Src] = SrcID = Cntr++;
517 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
518 }
519 else
520 SrcID = SrcI->second;
521
522 // Lookup the Dst.
523 VMap::iterator DstI= M.find(Dst);
524 unsigned DstID;
525
526 if (DstI == M.end()) {
527 M[Dst] = DstID = Cntr++;
528 *Out << "('vertex', " << DstID << ")\n";
529 }
530 else
531 DstID = DstI->second;
532
533 // Add the edge.
Ted Kremenekd1289322008-08-27 22:46:55 +0000534 *Out << "('edge', " << SrcID << ", " << DstID
535 << ", ('arrow','true'), ('oriented', 'true'))\n";
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000536}
537