blob: f01a755988e890d7375dc1a6d689908fa6d1ae79 [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"
Ted Kremenekad99dbf2008-11-03 22:31:48 +000015#include "clang/Driver/PathDiagnosticClients.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;
Ted Kremenek95c7b002008-10-24 01:04:59 +000068 const LangOptions& LOpts;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000069 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;
Ted Kremenek95c7b002008-10-24 01:04:59 +000077 AnalysisStores SM;
Ted Kremenek4fc82c82008-11-03 23:18:07 +000078 AnalysisDiagClients DC;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000079
80 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
81 PreprocessorFactory* ppf,
82 const LangOptions& lopts,
83 const std::string& fname,
84 const std::string& htmldir,
Ted Kremenek4fc82c82008-11-03 23:18:07 +000085 AnalysisStores sm, AnalysisDiagClients dc,
Ted Kremenekf8ce6992008-08-27 22:31:43 +000086 bool visgraphviz, bool visubi, bool trim, bool analyzeAll)
87 : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
88 LOpts(lopts), Diags(diags),
Ted Kremenekf4381fd2008-07-02 00:03:09 +000089 Ctx(0), PP(pp), PPF(ppf),
90 HTMLDir(htmldir),
91 FName(fname),
Ted Kremenek4fc82c82008-11-03 23:18:07 +000092 AnalyzeAll(analyzeAll), SM(sm), DC(dc) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +000093
94 void addCodeAction(CodeAction action) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000095 FunctionActions.push_back(action);
96 ObjCMethodActions.push_back(action);
97 }
98
99 void addObjCImplementationAction(CodeAction action) {
100 ObjCImplementationActions.push_back(action);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000101 }
102
103 virtual void Initialize(ASTContext &Context) {
104 Ctx = &Context;
105 }
106
107 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000108 virtual void HandleTranslationUnit(TranslationUnit &TU);
109
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000110 void HandleCode(Decl* D, Stmt* Body, Actions actions);
111 };
112
113
Ted Kremenekc0959972008-07-02 21:24:01 +0000114 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000115 Decl* D; Stmt* Body;
116 TranslationUnit* TU;
117
118 enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
119
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000120 AnalysisConsumer& C;
Ted Kremenek34d77342008-07-02 16:49:11 +0000121 bool DisplayedFunction;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000122
123 llvm::OwningPtr<CFG> cfg;
124 llvm::OwningPtr<LiveVariables> liveness;
125 llvm::OwningPtr<ParentMap> PM;
126
127 public:
128 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000129 : D(d), Body(b), TU(0), AScope(ScopeDecl), C(c), DisplayedFunction(false) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000130
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000131 AnalysisManager(AnalysisConsumer& c, TranslationUnit* tu)
132 : D(0), Body(0), TU(tu), AScope(ScopeTU), C(c), DisplayedFunction(false) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000133
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000134 Decl* getCodeDecl() const {
135 assert (AScope == ScopeDecl);
136 return D;
137 }
138
139 Stmt* getBody() const {
140 assert (AScope == ScopeDecl);
141 return Body;
142 }
143
144 TranslationUnit* getTranslationUnit() const {
145 assert (AScope == ScopeTU);
146 return TU;
147 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000148
Ted Kremenek95c7b002008-10-24 01:04:59 +0000149 GRStateManager::StoreManagerCreator getStoreManagerCreator() {
150 switch (C.SM) {
151 default:
152#define ANALYSIS_STORE(NAME, CMDFLAG, DESC)\
153case NAME##Model: return Create##NAME##Manager;
154#include "Analyses.def"
155 }
156 };
157
Ted Kremenek7032f462008-07-03 05:26:14 +0000158 virtual CFG* getCFG() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000159 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenek7032f462008-07-03 05:26:14 +0000160 return cfg.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000161 }
162
Ted Kremenekc0959972008-07-02 21:24:01 +0000163 virtual ParentMap& getParentMap() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000164 if (!PM)
165 PM.reset(new ParentMap(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000166 return *PM.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000167 }
168
Ted Kremenekc0959972008-07-02 21:24:01 +0000169 virtual ASTContext& getContext() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000170 return *C.Ctx;
171 }
172
Ted Kremenekc0959972008-07-02 21:24:01 +0000173 virtual SourceManager& getSourceManager() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000174 return getContext().getSourceManager();
175 }
176
Ted Kremenekc0959972008-07-02 21:24:01 +0000177 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000178 return C.Diags;
179 }
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000180
181 const LangOptions& getLangOptions() const {
182 return C.LOpts;
183 }
184
Ted Kremenekc0959972008-07-02 21:24:01 +0000185 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000186 if (C.PD.get() == 0 && !C.HTMLDir.empty()) {
187 switch (C.DC) {
188 default:
189#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)\
190case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break;
191#include "Analyses.def"
192 }
193 }
Ted Kremeneke2075582008-07-02 23:16:33 +0000194 return C.PD.get();
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000195 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000196
Ted Kremenek7032f462008-07-03 05:26:14 +0000197 virtual LiveVariables* getLiveVariables() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000198 if (!liveness) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000199 CFG* c = getCFG();
200 if (!c) return 0;
201
202 liveness.reset(new LiveVariables(*c));
203 liveness->runOnCFG(*c);
204 liveness->runOnAllBlocks(*c, 0, true);
Ted Kremenek235e0312008-07-02 18:11:29 +0000205 }
Ted Kremenekc0959972008-07-02 21:24:01 +0000206
Ted Kremenek7032f462008-07-03 05:26:14 +0000207 return liveness.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000208 }
Ted Kremenek34d77342008-07-02 16:49:11 +0000209
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000210 bool shouldVisualizeGraphviz() const {
211 return C.VisGraphviz;
212 }
213
214 bool shouldVisualizeUbigraph() const {
215 return C.VisUbigraph;
216 }
217
Ted Kremenek34d77342008-07-02 16:49:11 +0000218 bool shouldVisualize() const {
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000219 return C.VisGraphviz || C.VisUbigraph;
Ted Kremenek34d77342008-07-02 16:49:11 +0000220 }
221
222 bool shouldTrimGraph() const {
223 return C.TrimGraph;
224 }
225
226 void DisplayFunction() {
227
228 if (DisplayedFunction)
229 return;
230
231 DisplayedFunction = true;
232
233 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(getCodeDecl())) {
Ted Kremenek628a42e2008-09-04 00:02:50 +0000234 llvm::cout << "ANALYZE: "
Ted Kremenek34d77342008-07-02 16:49:11 +0000235 << getContext().getSourceManager().getSourceName(FD->getLocation())
236 << ' '
237 << FD->getIdentifier()->getName()
238 << '\n';
239 }
240 else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCodeDecl())) {
Ted Kremenek628a42e2008-09-04 00:02:50 +0000241 llvm::cout << "ANALYZE (ObjC Method): "
Ted Kremenek34d77342008-07-02 16:49:11 +0000242 << getContext().getSourceManager().getSourceName(MD->getLocation())
243 << " '"
244 << MD->getSelector().getName() << "'\n";
245 }
246 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000247 };
248
249} // end anonymous namespace
250
251namespace llvm {
252 template <> struct FoldingSetTrait<CodeAction> {
253 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
254 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
255 }
256 };
257}
258
259//===----------------------------------------------------------------------===//
260// AnalysisConsumer implementation.
261//===----------------------------------------------------------------------===//
262
263void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
264 switch (D->getKind()) {
265 case Decl::Function: {
266 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000267
268 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
269 break;
270
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000271 Stmt* Body = FD->getBody();
272 if (Body) HandleCode(FD, Body, FunctionActions);
273 break;
274 }
275
276 case Decl::ObjCMethod: {
277 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000278
279 if (FName.size() > 0 && FName != MD->getSelector().getName())
280 return;
281
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000282 Stmt* Body = MD->getBody();
283 if (Body) HandleCode(MD, Body, ObjCMethodActions);
284 break;
285 }
286
287 default:
288 break;
289 }
290}
291
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000292void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
293
294 if (ObjCImplementationActions.empty())
295 return;
296
297 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) {
298
299 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
300 HandleCode(ID, 0, ObjCImplementationActions);
301 }
302}
303
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000304void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
305
306 // Don't run the actions if an error has occured with parsing the file.
307 if (Diags.hasErrorOccurred())
308 return;
309
310 SourceLocation Loc = D->getLocation();
311
312 // Only run actions on declarations defined in actual source.
313 if (!Loc.isFileID())
314 return;
315
316 // Don't run the actions on declarations in header files unless
317 // otherwise specified.
318 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
319 return;
320
321 // Create an AnalysisManager that will manage the state for analyzing
322 // this method/function.
323 AnalysisManager mgr(*this, D, Body);
324
325 // Dispatch on the actions.
Zhongxing Xu3702af52008-10-30 05:03:28 +0000326 for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000327 (*I)(mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000328}
329
330//===----------------------------------------------------------------------===//
331// Analyses
332//===----------------------------------------------------------------------===//
333
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000334static void ActionWarnDeadStores(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000335 if (LiveVariables* L = mgr.getLiveVariables()) {
336 BugReporter BR(mgr);
337 CheckDeadStores(*L, BR);
338 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000339}
340
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000341static void ActionWarnUninitVals(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000342 if (CFG* c = mgr.getCFG())
343 CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000344}
345
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000346
Ted Kremenek78d46242008-07-22 16:21:24 +0000347static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
348 bool StandardWarnings = true) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000349
Ted Kremenek7032f462008-07-03 05:26:14 +0000350
Ted Kremenekbc46f342008-07-02 16:35:50 +0000351 llvm::OwningPtr<GRTransferFuncs> TF(tf);
Ted Kremenek7032f462008-07-03 05:26:14 +0000352
353 // Construct the analysis engine.
354 LiveVariables* L = mgr.getLiveVariables();
355 if (!L) return;
Ted Kremenekbc46f342008-07-02 16:35:50 +0000356
Ted Kremenek34d77342008-07-02 16:49:11 +0000357 // Display progress.
Ted Kremenek45479c82008-08-28 18:34:41 +0000358 mgr.DisplayFunction();
Ted Kremenek34d77342008-07-02 16:49:11 +0000359
Ted Kremenek95c7b002008-10-24 01:04:59 +0000360 GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L,
361 mgr.getStoreManagerCreator());
362
Ted Kremenekbc46f342008-07-02 16:35:50 +0000363 Eng.setTransferFunctions(tf);
364
Ted Kremenek78d46242008-07-22 16:21:24 +0000365 if (StandardWarnings) {
366 Eng.RegisterInternalChecks();
367 RegisterAppleChecks(Eng);
368 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000369
370 // Set the graph auditor.
371 llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor;
372 if (mgr.shouldVisualizeUbigraph()) {
373 Auditor.reset(CreateUbiViz());
374 ExplodedNodeImpl::SetAuditor(Auditor.get());
375 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000376
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000377 // Execute the worklist algorithm.
378 Eng.ExecuteWorkList();
Ted Kremenekbc46f342008-07-02 16:35:50 +0000379
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000380 // Release the auditor (if any) so that it doesn't monitor the graph
381 // created BugReporter.
382 ExplodedNodeImpl::SetAuditor(0);
383
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000384 // Display warnings.
Ted Kremenekc0959972008-07-02 21:24:01 +0000385 Eng.EmitWarnings(mgr);
Ted Kremenek34d77342008-07-02 16:49:11 +0000386
387 // Visualize the exploded graph.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000388 if (mgr.shouldVisualizeGraphviz())
Ted Kremenek34d77342008-07-02 16:49:11 +0000389 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000390}
391
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000392static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
Ted Kremenek78d46242008-07-22 16:21:24 +0000393 bool StandardWarnings) {
394
Ted Kremenekbc46f342008-07-02 16:35:50 +0000395 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
396 GCEnabled,
Ted Kremenekbc46f342008-07-02 16:35:50 +0000397 mgr.getLangOptions());
398
Ted Kremenek78d46242008-07-22 16:21:24 +0000399 ActionGRExprEngine(mgr, TF, StandardWarnings);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000400}
401
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000402static void ActionCheckerCFRef(AnalysisManager& mgr) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000403
404 switch (mgr.getLangOptions().getGCMode()) {
405 default:
406 assert (false && "Invalid GC mode.");
407 case LangOptions::NonGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000408 ActionCheckerCFRefAux(mgr, false, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000409 break;
410
411 case LangOptions::GCOnly:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000412 ActionCheckerCFRefAux(mgr, true, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000413 break;
414
415 case LangOptions::HybridGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000416 ActionCheckerCFRefAux(mgr, false, true);
417 ActionCheckerCFRefAux(mgr, true, false);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000418 break;
419 }
420}
421
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000422static void ActionCheckerSimple(AnalysisManager& mgr) {
Ted Kremenekbc46f342008-07-02 16:35:50 +0000423 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
424}
425
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000426static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000427 if (LiveVariables* L = mgr.getLiveVariables()) {
428 mgr.DisplayFunction();
429 L->dumpBlockLiveness(mgr.getSourceManager());
430 }
Ted Kremenek235e0312008-07-02 18:11:29 +0000431}
432
Ted Kremenek902141f2008-07-02 18:23:21 +0000433static void ActionCFGDump(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000434 if (CFG* c = mgr.getCFG()) {
435 mgr.DisplayFunction();
436 c->dump();
437 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000438}
439
440static void ActionCFGView(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000441 if (CFG* c = mgr.getCFG()) {
442 mgr.DisplayFunction();
443 c->viewCFG();
444 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000445}
446
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000447static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
Ted Kremenek4f4e7e42008-08-04 17:14:10 +0000448 if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
449 return;
450
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000451 BugReporter BR(mgr);
Ted Kremenek3cd483c2008-07-03 14:35:01 +0000452
453 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
454 mgr.getLangOptions(), BR);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000455}
456
Ted Kremenek395aaf22008-07-23 00:45:26 +0000457static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
458 BugReporter BR(mgr);
459 CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
460}
461
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000462static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
Ted Kremenek0d8019e2008-07-11 22:40:47 +0000463 BugReporter BR(mgr);
464
465 CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
466 BR);
467}
468
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000469//===----------------------------------------------------------------------===//
470// AnalysisConsumer creation.
471//===----------------------------------------------------------------------===//
472
473ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
Ted Kremenek95c7b002008-10-24 01:04:59 +0000474 AnalysisStores SM,
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000475 AnalysisDiagClients DC,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000476 Diagnostic &diags, Preprocessor* pp,
477 PreprocessorFactory* ppf,
478 const LangOptions& lopts,
479 const std::string& fname,
480 const std::string& htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000481 bool VisGraphviz, bool VisUbi,
482 bool trim,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000483 bool analyzeAll) {
484
485 llvm::OwningPtr<AnalysisConsumer>
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000486 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir, SM, DC,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000487 VisGraphviz, VisUbi, trim, analyzeAll));
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000488
489 for ( ; Beg != End ; ++Beg)
490 switch (*Beg) {
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000491#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000492 case NAME:\
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000493 C->add ## SCOPE ## Action(&Action ## NAME);\
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000494 break;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000495#include "Analyses.def"
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000496 default: break;
497 }
498
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000499 return C.take();
500}
501
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000502//===----------------------------------------------------------------------===//
503// Ubigraph Visualization. FIXME: Move to separate file.
504//===----------------------------------------------------------------------===//
505
506namespace {
507
508class UbigraphViz : public ExplodedNodeImpl::Auditor {
509 llvm::OwningPtr<llvm::raw_ostream> Out;
Ted Kremenek710ad932008-08-28 03:54:51 +0000510 llvm::sys::Path Dir, Filename;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000511 unsigned Cntr;
512
513 typedef llvm::DenseMap<void*,unsigned> VMap;
514 VMap M;
515
516public:
Ted Kremenek710ad932008-08-28 03:54:51 +0000517 UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
Ted Kremenek56b98712008-08-28 05:02:09 +0000518 llvm::sys::Path& filename);
Ted Kremenek710ad932008-08-28 03:54:51 +0000519
520 ~UbigraphViz();
521
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000522 virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
523};
524
525} // end anonymous namespace
526
527static ExplodedNodeImpl::Auditor* CreateUbiViz() {
528 std::string ErrMsg;
529
Ted Kremenek710ad932008-08-28 03:54:51 +0000530 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000531 if (!ErrMsg.empty())
532 return 0;
533
Ted Kremenek710ad932008-08-28 03:54:51 +0000534 llvm::sys::Path Filename = Dir;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000535 Filename.appendComponent("llvm_ubi");
536 Filename.makeUnique(true,&ErrMsg);
537
538 if (!ErrMsg.empty())
539 return 0;
540
541 llvm::cerr << "Writing '" << Filename << "'.\n";
542
543 llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
544 std::string filename = Filename.toString();
545 Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), ErrMsg));
546
547 if (!ErrMsg.empty())
548 return 0;
549
Ted Kremenek710ad932008-08-28 03:54:51 +0000550 return new UbigraphViz(Stream.take(), Dir, Filename);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000551}
552
553void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
Ted Kremenek45479c82008-08-28 18:34:41 +0000554
555 assert (Src != Dst && "Self-edges are not allowed.");
556
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000557 // Lookup the Src. If it is a new node, it's a root.
558 VMap::iterator SrcI= M.find(Src);
559 unsigned SrcID;
560
561 if (SrcI == M.end()) {
562 M[Src] = SrcID = Cntr++;
563 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
564 }
565 else
566 SrcID = SrcI->second;
567
568 // Lookup the Dst.
569 VMap::iterator DstI= M.find(Dst);
570 unsigned DstID;
571
572 if (DstI == M.end()) {
573 M[Dst] = DstID = Cntr++;
574 *Out << "('vertex', " << DstID << ")\n";
575 }
Ted Kremenek56b98712008-08-28 05:02:09 +0000576 else {
577 // We have hit DstID before. Change its style to reflect a cache hit.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000578 DstID = DstI->second;
Ted Kremenek56b98712008-08-28 05:02:09 +0000579 *Out << "('change_vertex_style', " << DstID << ", 1)\n";
580 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000581
582 // Add the edge.
Ted Kremenekd1289322008-08-27 22:46:55 +0000583 *Out << "('edge', " << SrcID << ", " << DstID
584 << ", ('arrow','true'), ('oriented', 'true'))\n";
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000585}
586
Ted Kremenek56b98712008-08-28 05:02:09 +0000587UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
588 llvm::sys::Path& filename)
589 : Out(out), Dir(dir), Filename(filename), Cntr(0) {
590
591 *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
592 *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
593 " ('size', '1.5'))\n";
594}
595
Ted Kremenek710ad932008-08-28 03:54:51 +0000596UbigraphViz::~UbigraphViz() {
597 Out.reset(0);
598 llvm::cerr << "Running 'ubiviz' program... ";
599 std::string ErrMsg;
600 llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
601 std::vector<const char*> args;
602 args.push_back(Ubiviz.c_str());
603 args.push_back(Filename.c_str());
604 args.push_back(0);
605
606 if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
607 llvm::cerr << "Error viewing graph: " << ErrMsg << "\n";
608 }
609
610 // Delete the directory.
611 Dir.eraseFromDisk(true);
Daniel Dunbar932680e2008-08-29 03:45:59 +0000612}