blob: 39b76e28853afe754b615d8e5b808df6fcfb434e [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.
Ted Kremenek45479c82008-08-28 18:34:41 +0000325 mgr.DisplayFunction();
Ted Kremenek34d77342008-07-02 16:49:11 +0000326
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;
Ted Kremenek710ad932008-08-28 03:54:51 +0000473 llvm::sys::Path Dir, Filename;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000474 unsigned Cntr;
475
476 typedef llvm::DenseMap<void*,unsigned> VMap;
477 VMap M;
478
479public:
Ted Kremenek710ad932008-08-28 03:54:51 +0000480 UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
Ted Kremenek56b98712008-08-28 05:02:09 +0000481 llvm::sys::Path& filename);
Ted Kremenek710ad932008-08-28 03:54:51 +0000482
483 ~UbigraphViz();
484
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000485 virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
486};
487
488} // end anonymous namespace
489
490static ExplodedNodeImpl::Auditor* CreateUbiViz() {
491 std::string ErrMsg;
492
Ted Kremenek710ad932008-08-28 03:54:51 +0000493 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000494 if (!ErrMsg.empty())
495 return 0;
496
Ted Kremenek710ad932008-08-28 03:54:51 +0000497 llvm::sys::Path Filename = Dir;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000498 Filename.appendComponent("llvm_ubi");
499 Filename.makeUnique(true,&ErrMsg);
500
501 if (!ErrMsg.empty())
502 return 0;
503
504 llvm::cerr << "Writing '" << Filename << "'.\n";
505
506 llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
507 std::string filename = Filename.toString();
508 Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), ErrMsg));
509
510 if (!ErrMsg.empty())
511 return 0;
512
Ted Kremenek710ad932008-08-28 03:54:51 +0000513 return new UbigraphViz(Stream.take(), Dir, Filename);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000514}
515
516void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
Ted Kremenek45479c82008-08-28 18:34:41 +0000517
518 assert (Src != Dst && "Self-edges are not allowed.");
519
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000520 // Lookup the Src. If it is a new node, it's a root.
521 VMap::iterator SrcI= M.find(Src);
522 unsigned SrcID;
523
524 if (SrcI == M.end()) {
525 M[Src] = SrcID = Cntr++;
526 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
527 }
528 else
529 SrcID = SrcI->second;
530
531 // Lookup the Dst.
532 VMap::iterator DstI= M.find(Dst);
533 unsigned DstID;
534
535 if (DstI == M.end()) {
536 M[Dst] = DstID = Cntr++;
537 *Out << "('vertex', " << DstID << ")\n";
538 }
Ted Kremenek56b98712008-08-28 05:02:09 +0000539 else {
540 // We have hit DstID before. Change its style to reflect a cache hit.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000541 DstID = DstI->second;
Ted Kremenek56b98712008-08-28 05:02:09 +0000542 *Out << "('change_vertex_style', " << DstID << ", 1)\n";
543 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000544
545 // Add the edge.
Ted Kremenekd1289322008-08-27 22:46:55 +0000546 *Out << "('edge', " << SrcID << ", " << DstID
547 << ", ('arrow','true'), ('oriented', 'true'))\n";
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000548}
549
Ted Kremenek56b98712008-08-28 05:02:09 +0000550UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
551 llvm::sys::Path& filename)
552 : Out(out), Dir(dir), Filename(filename), Cntr(0) {
553
554 *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
555 *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
556 " ('size', '1.5'))\n";
557}
558
Ted Kremenek710ad932008-08-28 03:54:51 +0000559UbigraphViz::~UbigraphViz() {
560 Out.reset(0);
561 llvm::cerr << "Running 'ubiviz' program... ";
562 std::string ErrMsg;
563 llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
564 std::vector<const char*> args;
565 args.push_back(Ubiviz.c_str());
566 args.push_back(Filename.c_str());
567 args.push_back(0);
568
569 if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
570 llvm::cerr << "Error viewing graph: " << ErrMsg << "\n";
571 }
572
573 // Delete the directory.
574 Dir.eraseFromDisk(true);
Daniel Dunbar932680e2008-08-29 03:45:59 +0000575}