blob: 0a59797549e4e3b215a7c8a2c975e44e944c300a [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 Kremenek710ad932008-08-28 03:54:51 +000036#include "llvm/System/Program.h"
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000037#include <vector>
38
Ted Kremenekf4381fd2008-07-02 00:03:09 +000039using namespace clang;
40
Ted Kremenekf8ce6992008-08-27 22:31:43 +000041static ExplodedNodeImpl::Auditor* CreateUbiViz();
Ted Kremenekf4381fd2008-07-02 00:03:09 +000042
43//===----------------------------------------------------------------------===//
44// Basic type definitions.
45//===----------------------------------------------------------------------===//
46
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000047namespace {
Ted Kremenekf4381fd2008-07-02 00:03:09 +000048 class AnalysisManager;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000049 typedef void (*CodeAction)(AnalysisManager& Mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +000050} // end anonymous namespace
51
52//===----------------------------------------------------------------------===//
53// AnalysisConsumer declaration.
54//===----------------------------------------------------------------------===//
55
56namespace {
57
58 class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000059 typedef std::vector<CodeAction> Actions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000060 Actions FunctionActions;
61 Actions ObjCMethodActions;
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000062 Actions ObjCImplementationActions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000063
64 public:
Ted Kremenekf8ce6992008-08-27 22:31:43 +000065 const bool VisGraphviz;
66 const bool VisUbigraph;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000067 const bool TrimGraph;
68 const LangOptions& LOpts;
69 Diagnostic &Diags;
70 ASTContext* Ctx;
71 Preprocessor* PP;
72 PreprocessorFactory* PPF;
73 const std::string HTMLDir;
74 const std::string FName;
75 llvm::OwningPtr<PathDiagnosticClient> PD;
76 bool AnalyzeAll;
77
78 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
79 PreprocessorFactory* ppf,
80 const LangOptions& lopts,
81 const std::string& fname,
82 const std::string& htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +000083 bool visgraphviz, bool visubi, bool trim, bool analyzeAll)
84 : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
85 LOpts(lopts), Diags(diags),
Ted Kremenekf4381fd2008-07-02 00:03:09 +000086 Ctx(0), PP(pp), PPF(ppf),
87 HTMLDir(htmldir),
88 FName(fname),
89 AnalyzeAll(analyzeAll) {}
90
91 void addCodeAction(CodeAction action) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000092 FunctionActions.push_back(action);
93 ObjCMethodActions.push_back(action);
94 }
95
96 void addObjCImplementationAction(CodeAction action) {
97 ObjCImplementationActions.push_back(action);
Ted Kremenekf4381fd2008-07-02 00:03:09 +000098 }
99
100 virtual void Initialize(ASTContext &Context) {
101 Ctx = &Context;
102 }
103
104 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000105 virtual void HandleTranslationUnit(TranslationUnit &TU);
106
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000107 void HandleCode(Decl* D, Stmt* Body, Actions actions);
108 };
109
110
Ted Kremenekc0959972008-07-02 21:24:01 +0000111 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000112 Decl* D;
113 Stmt* Body;
114 AnalysisConsumer& C;
Ted Kremenek34d77342008-07-02 16:49:11 +0000115 bool DisplayedFunction;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000116
117 llvm::OwningPtr<CFG> cfg;
118 llvm::OwningPtr<LiveVariables> liveness;
119 llvm::OwningPtr<ParentMap> PM;
120
121 public:
122 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
Ted Kremenek34d77342008-07-02 16:49:11 +0000123 : D(d), Body(b), C(c), DisplayedFunction(false) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000124
125
126 Decl* getCodeDecl() const { return D; }
127 Stmt* getBody() const { return Body; }
128
Ted Kremenek7032f462008-07-03 05:26:14 +0000129 virtual CFG* getCFG() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000130 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenek7032f462008-07-03 05:26:14 +0000131 return cfg.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000132 }
133
Ted Kremenekc0959972008-07-02 21:24:01 +0000134 virtual ParentMap& getParentMap() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000135 if (!PM)
136 PM.reset(new ParentMap(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000137 return *PM.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000138 }
139
Ted Kremenekc0959972008-07-02 21:24:01 +0000140 virtual ASTContext& getContext() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000141 return *C.Ctx;
142 }
143
Ted Kremenekc0959972008-07-02 21:24:01 +0000144 virtual SourceManager& getSourceManager() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000145 return getContext().getSourceManager();
146 }
147
Ted Kremenekc0959972008-07-02 21:24:01 +0000148 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000149 return C.Diags;
150 }
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000151
152 const LangOptions& getLangOptions() const {
153 return C.LOpts;
154 }
155
Ted Kremenekc0959972008-07-02 21:24:01 +0000156 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000157 if (C.PD.get() == 0 && !C.HTMLDir.empty())
158 C.PD.reset(CreateHTMLDiagnosticClient(C.HTMLDir, C.PP, C.PPF));
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000159
Ted Kremeneke2075582008-07-02 23:16:33 +0000160 return C.PD.get();
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000161 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000162
Ted Kremenek7032f462008-07-03 05:26:14 +0000163 virtual LiveVariables* getLiveVariables() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000164 if (!liveness) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000165 CFG* c = getCFG();
166 if (!c) return 0;
167
168 liveness.reset(new LiveVariables(*c));
169 liveness->runOnCFG(*c);
170 liveness->runOnAllBlocks(*c, 0, true);
Ted Kremenek235e0312008-07-02 18:11:29 +0000171 }
Ted Kremenekc0959972008-07-02 21:24:01 +0000172
Ted Kremenek7032f462008-07-03 05:26:14 +0000173 return liveness.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000174 }
Ted Kremenek34d77342008-07-02 16:49:11 +0000175
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000176 bool shouldVisualizeGraphviz() const {
177 return C.VisGraphviz;
178 }
179
180 bool shouldVisualizeUbigraph() const {
181 return C.VisUbigraph;
182 }
183
Ted Kremenek34d77342008-07-02 16:49:11 +0000184 bool shouldVisualize() const {
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000185 return C.VisGraphviz || C.VisUbigraph;
Ted Kremenek34d77342008-07-02 16:49:11 +0000186 }
187
188 bool shouldTrimGraph() const {
189 return C.TrimGraph;
190 }
191
192 void DisplayFunction() {
193
194 if (DisplayedFunction)
195 return;
196
197 DisplayedFunction = true;
198
199 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(getCodeDecl())) {
200 llvm::cerr << "ANALYZE: "
201 << getContext().getSourceManager().getSourceName(FD->getLocation())
202 << ' '
203 << FD->getIdentifier()->getName()
204 << '\n';
205 }
206 else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCodeDecl())) {
207 llvm::cerr << "ANALYZE (ObjC Method): "
208 << getContext().getSourceManager().getSourceName(MD->getLocation())
209 << " '"
210 << MD->getSelector().getName() << "'\n";
211 }
212 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000213 };
214
215} // end anonymous namespace
216
217namespace llvm {
218 template <> struct FoldingSetTrait<CodeAction> {
219 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
220 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
221 }
222 };
223}
224
225//===----------------------------------------------------------------------===//
226// AnalysisConsumer implementation.
227//===----------------------------------------------------------------------===//
228
229void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
230 switch (D->getKind()) {
231 case Decl::Function: {
232 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000233
234 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
235 break;
236
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000237 Stmt* Body = FD->getBody();
238 if (Body) HandleCode(FD, Body, FunctionActions);
239 break;
240 }
241
242 case Decl::ObjCMethod: {
243 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000244
245 if (FName.size() > 0 && FName != MD->getSelector().getName())
246 return;
247
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000248 Stmt* Body = MD->getBody();
249 if (Body) HandleCode(MD, Body, ObjCMethodActions);
250 break;
251 }
252
253 default:
254 break;
255 }
256}
257
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000258void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
259
260 if (ObjCImplementationActions.empty())
261 return;
262
263 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) {
264
265 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
266 HandleCode(ID, 0, ObjCImplementationActions);
267 }
268}
269
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000270void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
271
272 // Don't run the actions if an error has occured with parsing the file.
273 if (Diags.hasErrorOccurred())
274 return;
275
276 SourceLocation Loc = D->getLocation();
277
278 // Only run actions on declarations defined in actual source.
279 if (!Loc.isFileID())
280 return;
281
282 // Don't run the actions on declarations in header files unless
283 // otherwise specified.
284 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
285 return;
286
287 // Create an AnalysisManager that will manage the state for analyzing
288 // this method/function.
289 AnalysisManager mgr(*this, D, Body);
290
291 // Dispatch on the actions.
Ted Kremenekc0959972008-07-02 21:24:01 +0000292 for (Actions::iterator I = actions.begin(),
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000293 E = actions.end(); I != E; ++I)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000294 (*I)(mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000295}
296
297//===----------------------------------------------------------------------===//
298// Analyses
299//===----------------------------------------------------------------------===//
300
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000301static void ActionWarnDeadStores(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000302 if (LiveVariables* L = mgr.getLiveVariables()) {
303 BugReporter BR(mgr);
304 CheckDeadStores(*L, BR);
305 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000306}
307
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000308static void ActionWarnUninitVals(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000309 if (CFG* c = mgr.getCFG())
310 CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000311}
312
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000313
Ted Kremenek78d46242008-07-22 16:21:24 +0000314static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
315 bool StandardWarnings = true) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000316
Ted Kremenek7032f462008-07-03 05:26:14 +0000317
Ted Kremenekbc46f342008-07-02 16:35:50 +0000318 llvm::OwningPtr<GRTransferFuncs> TF(tf);
Ted Kremenek7032f462008-07-03 05:26:14 +0000319
320 // Construct the analysis engine.
321 LiveVariables* L = mgr.getLiveVariables();
322 if (!L) return;
Ted Kremenekbc46f342008-07-02 16:35:50 +0000323
Ted Kremenek34d77342008-07-02 16:49:11 +0000324 // Display progress.
325 if (!mgr.shouldVisualize())
326 mgr.DisplayFunction();
327
Ted Kremenek7032f462008-07-03 05:26:14 +0000328 GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L);
Ted Kremenekbc46f342008-07-02 16:35:50 +0000329 Eng.setTransferFunctions(tf);
330
Ted Kremenek78d46242008-07-22 16:21:24 +0000331 if (StandardWarnings) {
332 Eng.RegisterInternalChecks();
333 RegisterAppleChecks(Eng);
334 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000335
336 // Set the graph auditor.
337 llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor;
338 if (mgr.shouldVisualizeUbigraph()) {
339 Auditor.reset(CreateUbiViz());
340 ExplodedNodeImpl::SetAuditor(Auditor.get());
341 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000342
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000343 // Execute the worklist algorithm.
344 Eng.ExecuteWorkList();
Ted Kremenekbc46f342008-07-02 16:35:50 +0000345
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000346 // Release the auditor (if any) so that it doesn't monitor the graph
347 // created BugReporter.
348 ExplodedNodeImpl::SetAuditor(0);
349
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000350 // Display warnings.
Ted Kremenekc0959972008-07-02 21:24:01 +0000351 Eng.EmitWarnings(mgr);
Ted Kremenek34d77342008-07-02 16:49:11 +0000352
353 // Visualize the exploded graph.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000354 if (mgr.shouldVisualizeGraphviz())
Ted Kremenek34d77342008-07-02 16:49:11 +0000355 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000356}
357
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000358static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
Ted Kremenek78d46242008-07-22 16:21:24 +0000359 bool StandardWarnings) {
360
Ted Kremenekbc46f342008-07-02 16:35:50 +0000361 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
362 GCEnabled,
Ted Kremenekbc46f342008-07-02 16:35:50 +0000363 mgr.getLangOptions());
364
Ted Kremenek78d46242008-07-22 16:21:24 +0000365 ActionGRExprEngine(mgr, TF, StandardWarnings);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000366}
367
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000368static void ActionCheckerCFRef(AnalysisManager& mgr) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000369
370 switch (mgr.getLangOptions().getGCMode()) {
371 default:
372 assert (false && "Invalid GC mode.");
373 case LangOptions::NonGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000374 ActionCheckerCFRefAux(mgr, false, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000375 break;
376
377 case LangOptions::GCOnly:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000378 ActionCheckerCFRefAux(mgr, true, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000379 break;
380
381 case LangOptions::HybridGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000382 ActionCheckerCFRefAux(mgr, false, true);
383 ActionCheckerCFRefAux(mgr, true, false);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000384 break;
385 }
386}
387
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000388static void ActionCheckerSimple(AnalysisManager& mgr) {
Ted Kremenekbc46f342008-07-02 16:35:50 +0000389 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
390}
391
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000392static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000393 if (LiveVariables* L = mgr.getLiveVariables()) {
394 mgr.DisplayFunction();
395 L->dumpBlockLiveness(mgr.getSourceManager());
396 }
Ted Kremenek235e0312008-07-02 18:11:29 +0000397}
398
Ted Kremenek902141f2008-07-02 18:23:21 +0000399static void ActionCFGDump(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000400 if (CFG* c = mgr.getCFG()) {
401 mgr.DisplayFunction();
402 c->dump();
403 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000404}
405
406static void ActionCFGView(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000407 if (CFG* c = mgr.getCFG()) {
408 mgr.DisplayFunction();
409 c->viewCFG();
410 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000411}
412
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000413static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
Ted Kremenek4f4e7e42008-08-04 17:14:10 +0000414 if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
415 return;
416
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000417 BugReporter BR(mgr);
Ted Kremenek3cd483c2008-07-03 14:35:01 +0000418
419 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
420 mgr.getLangOptions(), BR);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000421}
422
Ted Kremenek395aaf22008-07-23 00:45:26 +0000423static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
424 BugReporter BR(mgr);
425 CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
426}
427
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000428static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
Ted Kremenek0d8019e2008-07-11 22:40:47 +0000429 BugReporter BR(mgr);
430
431 CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
432 BR);
433}
434
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000435//===----------------------------------------------------------------------===//
436// AnalysisConsumer creation.
437//===----------------------------------------------------------------------===//
438
439ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
440 Diagnostic &diags, Preprocessor* pp,
441 PreprocessorFactory* ppf,
442 const LangOptions& lopts,
443 const std::string& fname,
444 const std::string& htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000445 bool VisGraphviz, bool VisUbi,
446 bool trim,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000447 bool analyzeAll) {
448
449 llvm::OwningPtr<AnalysisConsumer>
450 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000451 VisGraphviz, VisUbi, trim, analyzeAll));
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000452
453 for ( ; Beg != End ; ++Beg)
454 switch (*Beg) {
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000455#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000456 case NAME:\
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000457 C->add ## SCOPE ## Action(&Action ## NAME);\
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000458 break;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000459#include "Analyses.def"
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000460 default: break;
461 }
462
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000463 return C.take();
464}
465
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000466//===----------------------------------------------------------------------===//
467// Ubigraph Visualization. FIXME: Move to separate file.
468//===----------------------------------------------------------------------===//
469
470namespace {
471
472class UbigraphViz : public ExplodedNodeImpl::Auditor {
473 llvm::OwningPtr<llvm::raw_ostream> Out;
Ted Kremenek710ad932008-08-28 03:54:51 +0000474 llvm::sys::Path Dir, Filename;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000475 unsigned Cntr;
476
477 typedef llvm::DenseMap<void*,unsigned> VMap;
478 VMap M;
479
480public:
Ted Kremenek710ad932008-08-28 03:54:51 +0000481 UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
Ted Kremenek56b98712008-08-28 05:02:09 +0000482 llvm::sys::Path& filename);
Ted Kremenek710ad932008-08-28 03:54:51 +0000483
484 ~UbigraphViz();
485
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000486 virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
487};
488
489} // end anonymous namespace
490
491static ExplodedNodeImpl::Auditor* CreateUbiViz() {
492 std::string ErrMsg;
493
Ted Kremenek710ad932008-08-28 03:54:51 +0000494 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000495 if (!ErrMsg.empty())
496 return 0;
497
Ted Kremenek710ad932008-08-28 03:54:51 +0000498 llvm::sys::Path Filename = Dir;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000499 Filename.appendComponent("llvm_ubi");
500 Filename.makeUnique(true,&ErrMsg);
501
502 if (!ErrMsg.empty())
503 return 0;
504
505 llvm::cerr << "Writing '" << Filename << "'.\n";
506
507 llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
508 std::string filename = Filename.toString();
509 Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), ErrMsg));
510
511 if (!ErrMsg.empty())
512 return 0;
513
Ted Kremenek710ad932008-08-28 03:54:51 +0000514 return new UbigraphViz(Stream.take(), Dir, Filename);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000515}
516
517void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
518 // Lookup the Src. If it is a new node, it's a root.
519 VMap::iterator SrcI= M.find(Src);
520 unsigned SrcID;
521
522 if (SrcI == M.end()) {
523 M[Src] = SrcID = Cntr++;
524 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
525 }
526 else
527 SrcID = SrcI->second;
528
529 // Lookup the Dst.
530 VMap::iterator DstI= M.find(Dst);
531 unsigned DstID;
532
533 if (DstI == M.end()) {
534 M[Dst] = DstID = Cntr++;
535 *Out << "('vertex', " << DstID << ")\n";
536 }
Ted Kremenek56b98712008-08-28 05:02:09 +0000537 else {
538 // We have hit DstID before. Change its style to reflect a cache hit.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000539 DstID = DstI->second;
Ted Kremenek56b98712008-08-28 05:02:09 +0000540 *Out << "('change_vertex_style', " << DstID << ", 1)\n";
541 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000542
543 // Add the edge.
Ted Kremenekd1289322008-08-27 22:46:55 +0000544 *Out << "('edge', " << SrcID << ", " << DstID
545 << ", ('arrow','true'), ('oriented', 'true'))\n";
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000546}
547
Ted Kremenek56b98712008-08-28 05:02:09 +0000548UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
549 llvm::sys::Path& filename)
550 : Out(out), Dir(dir), Filename(filename), Cntr(0) {
551
552 *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
553 *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
554 " ('size', '1.5'))\n";
555}
556
Ted Kremenek710ad932008-08-28 03:54:51 +0000557UbigraphViz::~UbigraphViz() {
558 Out.reset(0);
559 llvm::cerr << "Running 'ubiviz' program... ";
560 std::string ErrMsg;
561 llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
562 std::vector<const char*> args;
563 args.push_back(Ubiviz.c_str());
564 args.push_back(Filename.c_str());
565 args.push_back(0);
566
567 if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
568 llvm::cerr << "Error viewing graph: " << ErrMsg << "\n";
569 }
570
571 // Delete the directory.
572 Dir.eraseFromDisk(true);
573}