blob: 12ba732bd9cff1e8fbbbd4d58259e61f4bd6b44f [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;
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 Kremenekf4381fd2008-07-02 00:03:09 +000078
79 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
80 PreprocessorFactory* ppf,
81 const LangOptions& lopts,
82 const std::string& fname,
83 const std::string& htmldir,
Ted Kremenek95c7b002008-10-24 01:04:59 +000084 AnalysisStores sm,
Ted Kremenekf8ce6992008-08-27 22:31:43 +000085 bool visgraphviz, bool visubi, bool trim, bool analyzeAll)
86 : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
87 LOpts(lopts), Diags(diags),
Ted Kremenekf4381fd2008-07-02 00:03:09 +000088 Ctx(0), PP(pp), PPF(ppf),
89 HTMLDir(htmldir),
90 FName(fname),
Ted Kremenek95c7b002008-10-24 01:04:59 +000091 AnalyzeAll(analyzeAll), SM(sm) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +000092
93 void addCodeAction(CodeAction action) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000094 FunctionActions.push_back(action);
95 ObjCMethodActions.push_back(action);
96 }
97
98 void addObjCImplementationAction(CodeAction action) {
99 ObjCImplementationActions.push_back(action);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000100 }
101
102 virtual void Initialize(ASTContext &Context) {
103 Ctx = &Context;
104 }
105
106 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000107 virtual void HandleTranslationUnit(TranslationUnit &TU);
108
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000109 void HandleCode(Decl* D, Stmt* Body, Actions actions);
110 };
111
112
Ted Kremenekc0959972008-07-02 21:24:01 +0000113 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000114 Decl* D;
115 Stmt* Body;
116 AnalysisConsumer& C;
Ted Kremenek34d77342008-07-02 16:49:11 +0000117 bool DisplayedFunction;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000118
119 llvm::OwningPtr<CFG> cfg;
120 llvm::OwningPtr<LiveVariables> liveness;
121 llvm::OwningPtr<ParentMap> PM;
122
123 public:
124 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
Ted Kremenek34d77342008-07-02 16:49:11 +0000125 : D(d), Body(b), C(c), DisplayedFunction(false) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000126
127
128 Decl* getCodeDecl() const { return D; }
129 Stmt* getBody() const { return Body; }
130
Ted Kremenek95c7b002008-10-24 01:04:59 +0000131 GRStateManager::StoreManagerCreator getStoreManagerCreator() {
132 switch (C.SM) {
133 default:
134#define ANALYSIS_STORE(NAME, CMDFLAG, DESC)\
135case NAME##Model: return Create##NAME##Manager;
136#include "Analyses.def"
137 }
138 };
139
Ted Kremenek7032f462008-07-03 05:26:14 +0000140 virtual CFG* getCFG() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000141 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenek7032f462008-07-03 05:26:14 +0000142 return cfg.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000143 }
144
Ted Kremenekc0959972008-07-02 21:24:01 +0000145 virtual ParentMap& getParentMap() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000146 if (!PM)
147 PM.reset(new ParentMap(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000148 return *PM.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000149 }
150
Ted Kremenekc0959972008-07-02 21:24:01 +0000151 virtual ASTContext& getContext() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000152 return *C.Ctx;
153 }
154
Ted Kremenekc0959972008-07-02 21:24:01 +0000155 virtual SourceManager& getSourceManager() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000156 return getContext().getSourceManager();
157 }
158
Ted Kremenekc0959972008-07-02 21:24:01 +0000159 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000160 return C.Diags;
161 }
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000162
163 const LangOptions& getLangOptions() const {
164 return C.LOpts;
165 }
166
Ted Kremenekc0959972008-07-02 21:24:01 +0000167 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000168 if (C.PD.get() == 0 && !C.HTMLDir.empty())
169 C.PD.reset(CreateHTMLDiagnosticClient(C.HTMLDir, C.PP, C.PPF));
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000170
Ted Kremeneke2075582008-07-02 23:16:33 +0000171 return C.PD.get();
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000172 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000173
Ted Kremenek7032f462008-07-03 05:26:14 +0000174 virtual LiveVariables* getLiveVariables() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000175 if (!liveness) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000176 CFG* c = getCFG();
177 if (!c) return 0;
178
179 liveness.reset(new LiveVariables(*c));
180 liveness->runOnCFG(*c);
181 liveness->runOnAllBlocks(*c, 0, true);
Ted Kremenek235e0312008-07-02 18:11:29 +0000182 }
Ted Kremenekc0959972008-07-02 21:24:01 +0000183
Ted Kremenek7032f462008-07-03 05:26:14 +0000184 return liveness.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000185 }
Ted Kremenek34d77342008-07-02 16:49:11 +0000186
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000187 bool shouldVisualizeGraphviz() const {
188 return C.VisGraphviz;
189 }
190
191 bool shouldVisualizeUbigraph() const {
192 return C.VisUbigraph;
193 }
194
Ted Kremenek34d77342008-07-02 16:49:11 +0000195 bool shouldVisualize() const {
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000196 return C.VisGraphviz || C.VisUbigraph;
Ted Kremenek34d77342008-07-02 16:49:11 +0000197 }
198
199 bool shouldTrimGraph() const {
200 return C.TrimGraph;
201 }
202
203 void DisplayFunction() {
204
205 if (DisplayedFunction)
206 return;
207
208 DisplayedFunction = true;
209
210 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(getCodeDecl())) {
Ted Kremenek628a42e2008-09-04 00:02:50 +0000211 llvm::cout << "ANALYZE: "
Ted Kremenek34d77342008-07-02 16:49:11 +0000212 << getContext().getSourceManager().getSourceName(FD->getLocation())
213 << ' '
214 << FD->getIdentifier()->getName()
215 << '\n';
216 }
217 else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCodeDecl())) {
Ted Kremenek628a42e2008-09-04 00:02:50 +0000218 llvm::cout << "ANALYZE (ObjC Method): "
Ted Kremenek34d77342008-07-02 16:49:11 +0000219 << getContext().getSourceManager().getSourceName(MD->getLocation())
220 << " '"
221 << MD->getSelector().getName() << "'\n";
222 }
223 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000224 };
225
226} // end anonymous namespace
227
228namespace llvm {
229 template <> struct FoldingSetTrait<CodeAction> {
230 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
231 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
232 }
233 };
234}
235
236//===----------------------------------------------------------------------===//
237// AnalysisConsumer implementation.
238//===----------------------------------------------------------------------===//
239
240void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
241 switch (D->getKind()) {
242 case Decl::Function: {
243 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000244
245 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
246 break;
247
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000248 Stmt* Body = FD->getBody();
249 if (Body) HandleCode(FD, Body, FunctionActions);
250 break;
251 }
252
253 case Decl::ObjCMethod: {
254 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000255
256 if (FName.size() > 0 && FName != MD->getSelector().getName())
257 return;
258
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000259 Stmt* Body = MD->getBody();
260 if (Body) HandleCode(MD, Body, ObjCMethodActions);
261 break;
262 }
263
264 default:
265 break;
266 }
267}
268
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000269void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
270
271 if (ObjCImplementationActions.empty())
272 return;
273
274 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) {
275
276 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
277 HandleCode(ID, 0, ObjCImplementationActions);
278 }
279}
280
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000281void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
282
283 // Don't run the actions if an error has occured with parsing the file.
284 if (Diags.hasErrorOccurred())
285 return;
286
287 SourceLocation Loc = D->getLocation();
288
289 // Only run actions on declarations defined in actual source.
290 if (!Loc.isFileID())
291 return;
292
293 // Don't run the actions on declarations in header files unless
294 // otherwise specified.
295 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
296 return;
297
298 // Create an AnalysisManager that will manage the state for analyzing
299 // this method/function.
300 AnalysisManager mgr(*this, D, Body);
301
302 // Dispatch on the actions.
Ted Kremenekc0959972008-07-02 21:24:01 +0000303 for (Actions::iterator I = actions.begin(),
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000304 E = actions.end(); I != E; ++I)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000305 (*I)(mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000306}
307
308//===----------------------------------------------------------------------===//
309// Analyses
310//===----------------------------------------------------------------------===//
311
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000312static void ActionWarnDeadStores(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000313 if (LiveVariables* L = mgr.getLiveVariables()) {
314 BugReporter BR(mgr);
315 CheckDeadStores(*L, BR);
316 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000317}
318
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000319static void ActionWarnUninitVals(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000320 if (CFG* c = mgr.getCFG())
321 CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000322}
323
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000324
Ted Kremenek78d46242008-07-22 16:21:24 +0000325static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
326 bool StandardWarnings = true) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000327
Ted Kremenek7032f462008-07-03 05:26:14 +0000328
Ted Kremenekbc46f342008-07-02 16:35:50 +0000329 llvm::OwningPtr<GRTransferFuncs> TF(tf);
Ted Kremenek7032f462008-07-03 05:26:14 +0000330
331 // Construct the analysis engine.
332 LiveVariables* L = mgr.getLiveVariables();
333 if (!L) return;
Ted Kremenekbc46f342008-07-02 16:35:50 +0000334
Ted Kremenek34d77342008-07-02 16:49:11 +0000335 // Display progress.
Ted Kremenek45479c82008-08-28 18:34:41 +0000336 mgr.DisplayFunction();
Ted Kremenek34d77342008-07-02 16:49:11 +0000337
Ted Kremenek95c7b002008-10-24 01:04:59 +0000338 GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L,
339 mgr.getStoreManagerCreator());
340
Ted Kremenekbc46f342008-07-02 16:35:50 +0000341 Eng.setTransferFunctions(tf);
342
Ted Kremenek78d46242008-07-22 16:21:24 +0000343 if (StandardWarnings) {
344 Eng.RegisterInternalChecks();
345 RegisterAppleChecks(Eng);
346 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000347
348 // Set the graph auditor.
349 llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor;
350 if (mgr.shouldVisualizeUbigraph()) {
351 Auditor.reset(CreateUbiViz());
352 ExplodedNodeImpl::SetAuditor(Auditor.get());
353 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000354
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000355 // Execute the worklist algorithm.
356 Eng.ExecuteWorkList();
Ted Kremenekbc46f342008-07-02 16:35:50 +0000357
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000358 // Release the auditor (if any) so that it doesn't monitor the graph
359 // created BugReporter.
360 ExplodedNodeImpl::SetAuditor(0);
361
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000362 // Display warnings.
Ted Kremenekc0959972008-07-02 21:24:01 +0000363 Eng.EmitWarnings(mgr);
Ted Kremenek34d77342008-07-02 16:49:11 +0000364
365 // Visualize the exploded graph.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000366 if (mgr.shouldVisualizeGraphviz())
Ted Kremenek34d77342008-07-02 16:49:11 +0000367 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000368}
369
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000370static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
Ted Kremenek78d46242008-07-22 16:21:24 +0000371 bool StandardWarnings) {
372
Ted Kremenekbc46f342008-07-02 16:35:50 +0000373 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
374 GCEnabled,
Ted Kremenekbc46f342008-07-02 16:35:50 +0000375 mgr.getLangOptions());
376
Ted Kremenek78d46242008-07-22 16:21:24 +0000377 ActionGRExprEngine(mgr, TF, StandardWarnings);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000378}
379
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000380static void ActionCheckerCFRef(AnalysisManager& mgr) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000381
382 switch (mgr.getLangOptions().getGCMode()) {
383 default:
384 assert (false && "Invalid GC mode.");
385 case LangOptions::NonGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000386 ActionCheckerCFRefAux(mgr, false, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000387 break;
388
389 case LangOptions::GCOnly:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000390 ActionCheckerCFRefAux(mgr, true, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000391 break;
392
393 case LangOptions::HybridGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000394 ActionCheckerCFRefAux(mgr, false, true);
395 ActionCheckerCFRefAux(mgr, true, false);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000396 break;
397 }
398}
399
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000400static void ActionCheckerSimple(AnalysisManager& mgr) {
Ted Kremenekbc46f342008-07-02 16:35:50 +0000401 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
402}
403
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000404static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000405 if (LiveVariables* L = mgr.getLiveVariables()) {
406 mgr.DisplayFunction();
407 L->dumpBlockLiveness(mgr.getSourceManager());
408 }
Ted Kremenek235e0312008-07-02 18:11:29 +0000409}
410
Ted Kremenek902141f2008-07-02 18:23:21 +0000411static void ActionCFGDump(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000412 if (CFG* c = mgr.getCFG()) {
413 mgr.DisplayFunction();
414 c->dump();
415 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000416}
417
418static void ActionCFGView(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000419 if (CFG* c = mgr.getCFG()) {
420 mgr.DisplayFunction();
421 c->viewCFG();
422 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000423}
424
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000425static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
Ted Kremenek4f4e7e42008-08-04 17:14:10 +0000426 if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
427 return;
428
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000429 BugReporter BR(mgr);
Ted Kremenek3cd483c2008-07-03 14:35:01 +0000430
431 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
432 mgr.getLangOptions(), BR);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000433}
434
Ted Kremenek395aaf22008-07-23 00:45:26 +0000435static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
436 BugReporter BR(mgr);
437 CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
438}
439
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000440static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
Ted Kremenek0d8019e2008-07-11 22:40:47 +0000441 BugReporter BR(mgr);
442
443 CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
444 BR);
445}
446
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000447//===----------------------------------------------------------------------===//
448// AnalysisConsumer creation.
449//===----------------------------------------------------------------------===//
450
451ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
Ted Kremenek95c7b002008-10-24 01:04:59 +0000452 AnalysisStores SM,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000453 Diagnostic &diags, Preprocessor* pp,
454 PreprocessorFactory* ppf,
455 const LangOptions& lopts,
456 const std::string& fname,
457 const std::string& htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000458 bool VisGraphviz, bool VisUbi,
459 bool trim,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000460 bool analyzeAll) {
461
462 llvm::OwningPtr<AnalysisConsumer>
Ted Kremenek95c7b002008-10-24 01:04:59 +0000463 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir, SM,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000464 VisGraphviz, VisUbi, trim, analyzeAll));
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000465
466 for ( ; Beg != End ; ++Beg)
467 switch (*Beg) {
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000468#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000469 case NAME:\
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000470 C->add ## SCOPE ## Action(&Action ## NAME);\
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000471 break;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000472#include "Analyses.def"
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000473 default: break;
474 }
475
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000476 return C.take();
477}
478
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000479//===----------------------------------------------------------------------===//
480// Ubigraph Visualization. FIXME: Move to separate file.
481//===----------------------------------------------------------------------===//
482
483namespace {
484
485class UbigraphViz : public ExplodedNodeImpl::Auditor {
486 llvm::OwningPtr<llvm::raw_ostream> Out;
Ted Kremenek710ad932008-08-28 03:54:51 +0000487 llvm::sys::Path Dir, Filename;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000488 unsigned Cntr;
489
490 typedef llvm::DenseMap<void*,unsigned> VMap;
491 VMap M;
492
493public:
Ted Kremenek710ad932008-08-28 03:54:51 +0000494 UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
Ted Kremenek56b98712008-08-28 05:02:09 +0000495 llvm::sys::Path& filename);
Ted Kremenek710ad932008-08-28 03:54:51 +0000496
497 ~UbigraphViz();
498
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000499 virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
500};
501
502} // end anonymous namespace
503
504static ExplodedNodeImpl::Auditor* CreateUbiViz() {
505 std::string ErrMsg;
506
Ted Kremenek710ad932008-08-28 03:54:51 +0000507 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000508 if (!ErrMsg.empty())
509 return 0;
510
Ted Kremenek710ad932008-08-28 03:54:51 +0000511 llvm::sys::Path Filename = Dir;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000512 Filename.appendComponent("llvm_ubi");
513 Filename.makeUnique(true,&ErrMsg);
514
515 if (!ErrMsg.empty())
516 return 0;
517
518 llvm::cerr << "Writing '" << Filename << "'.\n";
519
520 llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
521 std::string filename = Filename.toString();
522 Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), ErrMsg));
523
524 if (!ErrMsg.empty())
525 return 0;
526
Ted Kremenek710ad932008-08-28 03:54:51 +0000527 return new UbigraphViz(Stream.take(), Dir, Filename);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000528}
529
530void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
Ted Kremenek45479c82008-08-28 18:34:41 +0000531
532 assert (Src != Dst && "Self-edges are not allowed.");
533
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000534 // Lookup the Src. If it is a new node, it's a root.
535 VMap::iterator SrcI= M.find(Src);
536 unsigned SrcID;
537
538 if (SrcI == M.end()) {
539 M[Src] = SrcID = Cntr++;
540 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
541 }
542 else
543 SrcID = SrcI->second;
544
545 // Lookup the Dst.
546 VMap::iterator DstI= M.find(Dst);
547 unsigned DstID;
548
549 if (DstI == M.end()) {
550 M[Dst] = DstID = Cntr++;
551 *Out << "('vertex', " << DstID << ")\n";
552 }
Ted Kremenek56b98712008-08-28 05:02:09 +0000553 else {
554 // We have hit DstID before. Change its style to reflect a cache hit.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000555 DstID = DstI->second;
Ted Kremenek56b98712008-08-28 05:02:09 +0000556 *Out << "('change_vertex_style', " << DstID << ", 1)\n";
557 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000558
559 // Add the edge.
Ted Kremenekd1289322008-08-27 22:46:55 +0000560 *Out << "('edge', " << SrcID << ", " << DstID
561 << ", ('arrow','true'), ('oriented', 'true'))\n";
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000562}
563
Ted Kremenek56b98712008-08-28 05:02:09 +0000564UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
565 llvm::sys::Path& filename)
566 : Out(out), Dir(dir), Filename(filename), Cntr(0) {
567
568 *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
569 *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
570 " ('size', '1.5'))\n";
571}
572
Ted Kremenek710ad932008-08-28 03:54:51 +0000573UbigraphViz::~UbigraphViz() {
574 Out.reset(0);
575 llvm::cerr << "Running 'ubiviz' program... ";
576 std::string ErrMsg;
577 llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
578 std::vector<const char*> args;
579 args.push_back(Ubiviz.c_str());
580 args.push_back(Filename.c_str());
581 args.push_back(0);
582
583 if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
584 llvm::cerr << "Error viewing graph: " << ErrMsg << "\n";
585 }
586
587 // Delete the directory.
588 Dir.eraseFromDisk(true);
Daniel Dunbar932680e2008-08-29 03:45:59 +0000589}