blob: 10e69686adc39f07eba81df0858b014269b81432 [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 Kremenekdaac6342008-11-07 02:09:25 +000063 Actions TranslationUnitActions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000064
65 public:
Ted Kremenekf8ce6992008-08-27 22:31:43 +000066 const bool VisGraphviz;
67 const bool VisUbigraph;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000068 const bool TrimGraph;
Ted Kremenek95c7b002008-10-24 01:04:59 +000069 const LangOptions& LOpts;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000070 Diagnostic &Diags;
71 ASTContext* Ctx;
72 Preprocessor* PP;
73 PreprocessorFactory* PPF;
74 const std::string HTMLDir;
75 const std::string FName;
76 llvm::OwningPtr<PathDiagnosticClient> PD;
77 bool AnalyzeAll;
Ted Kremenek95c7b002008-10-24 01:04:59 +000078 AnalysisStores SM;
Ted Kremenek4fc82c82008-11-03 23:18:07 +000079 AnalysisDiagClients DC;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000080
81 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
82 PreprocessorFactory* ppf,
83 const LangOptions& lopts,
84 const std::string& fname,
85 const std::string& htmldir,
Ted Kremenek4fc82c82008-11-03 23:18:07 +000086 AnalysisStores sm, AnalysisDiagClients dc,
Ted Kremenekf8ce6992008-08-27 22:31:43 +000087 bool visgraphviz, bool visubi, bool trim, bool analyzeAll)
88 : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
89 LOpts(lopts), Diags(diags),
Ted Kremenekf4381fd2008-07-02 00:03:09 +000090 Ctx(0), PP(pp), PPF(ppf),
91 HTMLDir(htmldir),
92 FName(fname),
Ted Kremenek4fc82c82008-11-03 23:18:07 +000093 AnalyzeAll(analyzeAll), SM(sm), DC(dc) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +000094
95 void addCodeAction(CodeAction action) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000096 FunctionActions.push_back(action);
97 ObjCMethodActions.push_back(action);
98 }
99
100 void addObjCImplementationAction(CodeAction action) {
101 ObjCImplementationActions.push_back(action);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000102 }
103
Ted Kremenekdaac6342008-11-07 02:09:25 +0000104 void addTranslationUnitAction(CodeAction action) {
105 TranslationUnitActions.push_back(action);
106 }
107
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000108 virtual void Initialize(ASTContext &Context) {
109 Ctx = &Context;
110 }
111
112 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000113 virtual void HandleTranslationUnit(TranslationUnit &TU);
114
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000115 void HandleCode(Decl* D, Stmt* Body, Actions actions);
116 };
117
118
Ted Kremenekc0959972008-07-02 21:24:01 +0000119 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000120 Decl* D; Stmt* Body;
121 TranslationUnit* TU;
122
123 enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
124
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000125 AnalysisConsumer& C;
Ted Kremenek34d77342008-07-02 16:49:11 +0000126 bool DisplayedFunction;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000127
128 llvm::OwningPtr<CFG> cfg;
129 llvm::OwningPtr<LiveVariables> liveness;
130 llvm::OwningPtr<ParentMap> PM;
131
132 public:
133 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000134 : D(d), Body(b), TU(0), AScope(ScopeDecl), C(c), DisplayedFunction(false) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000135
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000136 AnalysisManager(AnalysisConsumer& c, TranslationUnit* tu)
137 : D(0), Body(0), TU(tu), AScope(ScopeTU), C(c), DisplayedFunction(false) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000138
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000139 Decl* getCodeDecl() const {
140 assert (AScope == ScopeDecl);
141 return D;
142 }
143
144 Stmt* getBody() const {
145 assert (AScope == ScopeDecl);
146 return Body;
147 }
148
149 TranslationUnit* getTranslationUnit() const {
150 assert (AScope == ScopeTU);
151 return TU;
152 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000153
Ted Kremenek95c7b002008-10-24 01:04:59 +0000154 GRStateManager::StoreManagerCreator getStoreManagerCreator() {
155 switch (C.SM) {
156 default:
157#define ANALYSIS_STORE(NAME, CMDFLAG, DESC)\
158case NAME##Model: return Create##NAME##Manager;
159#include "Analyses.def"
160 }
161 };
162
Ted Kremenek7032f462008-07-03 05:26:14 +0000163 virtual CFG* getCFG() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000164 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenek7032f462008-07-03 05:26:14 +0000165 return cfg.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000166 }
167
Ted Kremenekc0959972008-07-02 21:24:01 +0000168 virtual ParentMap& getParentMap() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000169 if (!PM)
170 PM.reset(new ParentMap(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000171 return *PM.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000172 }
173
Ted Kremenekc0959972008-07-02 21:24:01 +0000174 virtual ASTContext& getContext() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000175 return *C.Ctx;
176 }
177
Ted Kremenekc0959972008-07-02 21:24:01 +0000178 virtual SourceManager& getSourceManager() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000179 return getContext().getSourceManager();
180 }
181
Ted Kremenekc0959972008-07-02 21:24:01 +0000182 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000183 return C.Diags;
184 }
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000185
186 const LangOptions& getLangOptions() const {
187 return C.LOpts;
188 }
189
Ted Kremenekc0959972008-07-02 21:24:01 +0000190 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000191 if (C.PD.get() == 0 && !C.HTMLDir.empty()) {
192 switch (C.DC) {
193 default:
194#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)\
195case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break;
196#include "Analyses.def"
197 }
198 }
Ted Kremeneke2075582008-07-02 23:16:33 +0000199 return C.PD.get();
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000200 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000201
Ted Kremenek7032f462008-07-03 05:26:14 +0000202 virtual LiveVariables* getLiveVariables() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000203 if (!liveness) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000204 CFG* c = getCFG();
205 if (!c) return 0;
206
207 liveness.reset(new LiveVariables(*c));
208 liveness->runOnCFG(*c);
209 liveness->runOnAllBlocks(*c, 0, true);
Ted Kremenek235e0312008-07-02 18:11:29 +0000210 }
Ted Kremenekc0959972008-07-02 21:24:01 +0000211
Ted Kremenek7032f462008-07-03 05:26:14 +0000212 return liveness.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000213 }
Ted Kremenek34d77342008-07-02 16:49:11 +0000214
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000215 bool shouldVisualizeGraphviz() const {
216 return C.VisGraphviz;
217 }
218
219 bool shouldVisualizeUbigraph() const {
220 return C.VisUbigraph;
221 }
222
Ted Kremenek34d77342008-07-02 16:49:11 +0000223 bool shouldVisualize() const {
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000224 return C.VisGraphviz || C.VisUbigraph;
Ted Kremenek34d77342008-07-02 16:49:11 +0000225 }
226
227 bool shouldTrimGraph() const {
228 return C.TrimGraph;
229 }
230
231 void DisplayFunction() {
232
233 if (DisplayedFunction)
234 return;
235
236 DisplayedFunction = true;
237
238 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(getCodeDecl())) {
Ted Kremenek628a42e2008-09-04 00:02:50 +0000239 llvm::cout << "ANALYZE: "
Ted Kremenek34d77342008-07-02 16:49:11 +0000240 << getContext().getSourceManager().getSourceName(FD->getLocation())
241 << ' '
242 << FD->getIdentifier()->getName()
243 << '\n';
244 }
245 else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCodeDecl())) {
Ted Kremenek628a42e2008-09-04 00:02:50 +0000246 llvm::cout << "ANALYZE (ObjC Method): "
Ted Kremenek34d77342008-07-02 16:49:11 +0000247 << getContext().getSourceManager().getSourceName(MD->getLocation())
248 << " '"
249 << MD->getSelector().getName() << "'\n";
250 }
251 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000252 };
253
254} // end anonymous namespace
255
256namespace llvm {
257 template <> struct FoldingSetTrait<CodeAction> {
258 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
259 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
260 }
261 };
262}
263
264//===----------------------------------------------------------------------===//
265// AnalysisConsumer implementation.
266//===----------------------------------------------------------------------===//
267
268void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
269 switch (D->getKind()) {
270 case Decl::Function: {
271 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000272
273 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
274 break;
275
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000276 Stmt* Body = FD->getBody();
277 if (Body) HandleCode(FD, Body, FunctionActions);
278 break;
279 }
280
281 case Decl::ObjCMethod: {
282 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000283
284 if (FName.size() > 0 && FName != MD->getSelector().getName())
285 return;
286
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000287 Stmt* Body = MD->getBody();
288 if (Body) HandleCode(MD, Body, ObjCMethodActions);
289 break;
290 }
291
292 default:
293 break;
294 }
295}
296
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000297void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
298
Ted Kremenekdaac6342008-11-07 02:09:25 +0000299 if(!TranslationUnitActions.empty()) {
300 AnalysisManager mgr(*this, &TU);
301 for (Actions::iterator I = TranslationUnitActions.begin(),
302 E = TranslationUnitActions.end(); I != E; ++I)
303 (*I)(mgr);
304 }
305
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000306 if (ObjCImplementationActions.empty())
307 return;
308
309 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) {
310
311 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
312 HandleCode(ID, 0, ObjCImplementationActions);
313 }
314}
315
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000316void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
317
318 // Don't run the actions if an error has occured with parsing the file.
319 if (Diags.hasErrorOccurred())
320 return;
321
322 SourceLocation Loc = D->getLocation();
323
324 // Only run actions on declarations defined in actual source.
325 if (!Loc.isFileID())
326 return;
327
328 // Don't run the actions on declarations in header files unless
329 // otherwise specified.
330 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
331 return;
332
333 // Create an AnalysisManager that will manage the state for analyzing
334 // this method/function.
335 AnalysisManager mgr(*this, D, Body);
336
337 // Dispatch on the actions.
Zhongxing Xu3702af52008-10-30 05:03:28 +0000338 for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000339 (*I)(mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000340}
341
342//===----------------------------------------------------------------------===//
343// Analyses
344//===----------------------------------------------------------------------===//
345
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000346static void ActionWarnDeadStores(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000347 if (LiveVariables* L = mgr.getLiveVariables()) {
348 BugReporter BR(mgr);
349 CheckDeadStores(*L, BR);
350 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000351}
352
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000353static void ActionWarnUninitVals(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000354 if (CFG* c = mgr.getCFG())
355 CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000356}
357
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000358
Ted Kremenek78d46242008-07-22 16:21:24 +0000359static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
360 bool StandardWarnings = true) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000361
Ted Kremenek7032f462008-07-03 05:26:14 +0000362
Ted Kremenekbc46f342008-07-02 16:35:50 +0000363 llvm::OwningPtr<GRTransferFuncs> TF(tf);
Ted Kremenek7032f462008-07-03 05:26:14 +0000364
365 // Construct the analysis engine.
366 LiveVariables* L = mgr.getLiveVariables();
367 if (!L) return;
Ted Kremenekbc46f342008-07-02 16:35:50 +0000368
Ted Kremenek34d77342008-07-02 16:49:11 +0000369 // Display progress.
Ted Kremenek45479c82008-08-28 18:34:41 +0000370 mgr.DisplayFunction();
Ted Kremenek34d77342008-07-02 16:49:11 +0000371
Ted Kremenek95c7b002008-10-24 01:04:59 +0000372 GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L,
373 mgr.getStoreManagerCreator());
374
Ted Kremenekbc46f342008-07-02 16:35:50 +0000375 Eng.setTransferFunctions(tf);
376
Ted Kremenek78d46242008-07-22 16:21:24 +0000377 if (StandardWarnings) {
378 Eng.RegisterInternalChecks();
379 RegisterAppleChecks(Eng);
380 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000381
382 // Set the graph auditor.
383 llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor;
384 if (mgr.shouldVisualizeUbigraph()) {
385 Auditor.reset(CreateUbiViz());
386 ExplodedNodeImpl::SetAuditor(Auditor.get());
387 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000388
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000389 // Execute the worklist algorithm.
390 Eng.ExecuteWorkList();
Ted Kremenekbc46f342008-07-02 16:35:50 +0000391
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000392 // Release the auditor (if any) so that it doesn't monitor the graph
393 // created BugReporter.
394 ExplodedNodeImpl::SetAuditor(0);
395
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000396 // Display warnings.
Ted Kremenekc0959972008-07-02 21:24:01 +0000397 Eng.EmitWarnings(mgr);
Ted Kremenek34d77342008-07-02 16:49:11 +0000398
399 // Visualize the exploded graph.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000400 if (mgr.shouldVisualizeGraphviz())
Ted Kremenek34d77342008-07-02 16:49:11 +0000401 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000402}
403
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000404static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
Ted Kremenek78d46242008-07-22 16:21:24 +0000405 bool StandardWarnings) {
406
Ted Kremenekbc46f342008-07-02 16:35:50 +0000407 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
408 GCEnabled,
Ted Kremenekbc46f342008-07-02 16:35:50 +0000409 mgr.getLangOptions());
410
Ted Kremenek78d46242008-07-22 16:21:24 +0000411 ActionGRExprEngine(mgr, TF, StandardWarnings);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000412}
413
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000414static void ActionCheckerCFRef(AnalysisManager& mgr) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000415
416 switch (mgr.getLangOptions().getGCMode()) {
417 default:
418 assert (false && "Invalid GC mode.");
419 case LangOptions::NonGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000420 ActionCheckerCFRefAux(mgr, false, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000421 break;
422
423 case LangOptions::GCOnly:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000424 ActionCheckerCFRefAux(mgr, true, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000425 break;
426
427 case LangOptions::HybridGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000428 ActionCheckerCFRefAux(mgr, false, true);
429 ActionCheckerCFRefAux(mgr, true, false);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000430 break;
431 }
432}
433
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000434static void ActionCheckerSimple(AnalysisManager& mgr) {
Ted Kremenekbc46f342008-07-02 16:35:50 +0000435 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
436}
437
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000438static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000439 if (LiveVariables* L = mgr.getLiveVariables()) {
440 mgr.DisplayFunction();
441 L->dumpBlockLiveness(mgr.getSourceManager());
442 }
Ted Kremenek235e0312008-07-02 18:11:29 +0000443}
444
Ted Kremenek902141f2008-07-02 18:23:21 +0000445static void ActionCFGDump(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000446 if (CFG* c = mgr.getCFG()) {
447 mgr.DisplayFunction();
448 c->dump();
449 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000450}
451
452static void ActionCFGView(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000453 if (CFG* c = mgr.getCFG()) {
454 mgr.DisplayFunction();
455 c->viewCFG();
456 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000457}
458
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000459static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
Ted Kremenek4f4e7e42008-08-04 17:14:10 +0000460 if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
461 return;
462
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000463 BugReporter BR(mgr);
Ted Kremenek3cd483c2008-07-03 14:35:01 +0000464
465 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
466 mgr.getLangOptions(), BR);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000467}
468
Ted Kremenek395aaf22008-07-23 00:45:26 +0000469static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
470 BugReporter BR(mgr);
471 CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
472}
473
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000474static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
Ted Kremenek0d8019e2008-07-11 22:40:47 +0000475 BugReporter BR(mgr);
476
477 CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
478 BR);
479}
480
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000481//===----------------------------------------------------------------------===//
482// AnalysisConsumer creation.
483//===----------------------------------------------------------------------===//
484
485ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
Ted Kremenek95c7b002008-10-24 01:04:59 +0000486 AnalysisStores SM,
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000487 AnalysisDiagClients DC,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000488 Diagnostic &diags, Preprocessor* pp,
489 PreprocessorFactory* ppf,
490 const LangOptions& lopts,
491 const std::string& fname,
492 const std::string& htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000493 bool VisGraphviz, bool VisUbi,
494 bool trim,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000495 bool analyzeAll) {
496
497 llvm::OwningPtr<AnalysisConsumer>
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000498 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir, SM, DC,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000499 VisGraphviz, VisUbi, trim, analyzeAll));
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000500
501 for ( ; Beg != End ; ++Beg)
502 switch (*Beg) {
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000503#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000504 case NAME:\
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000505 C->add ## SCOPE ## Action(&Action ## NAME);\
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000506 break;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000507#include "Analyses.def"
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000508 default: break;
509 }
510
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000511 return C.take();
512}
513
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000514//===----------------------------------------------------------------------===//
515// Ubigraph Visualization. FIXME: Move to separate file.
516//===----------------------------------------------------------------------===//
517
518namespace {
519
520class UbigraphViz : public ExplodedNodeImpl::Auditor {
521 llvm::OwningPtr<llvm::raw_ostream> Out;
Ted Kremenek710ad932008-08-28 03:54:51 +0000522 llvm::sys::Path Dir, Filename;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000523 unsigned Cntr;
524
525 typedef llvm::DenseMap<void*,unsigned> VMap;
526 VMap M;
527
528public:
Ted Kremenek710ad932008-08-28 03:54:51 +0000529 UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
Ted Kremenek56b98712008-08-28 05:02:09 +0000530 llvm::sys::Path& filename);
Ted Kremenek710ad932008-08-28 03:54:51 +0000531
532 ~UbigraphViz();
533
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000534 virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
535};
536
537} // end anonymous namespace
538
539static ExplodedNodeImpl::Auditor* CreateUbiViz() {
540 std::string ErrMsg;
541
Ted Kremenek710ad932008-08-28 03:54:51 +0000542 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000543 if (!ErrMsg.empty())
544 return 0;
545
Ted Kremenek710ad932008-08-28 03:54:51 +0000546 llvm::sys::Path Filename = Dir;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000547 Filename.appendComponent("llvm_ubi");
548 Filename.makeUnique(true,&ErrMsg);
549
550 if (!ErrMsg.empty())
551 return 0;
552
553 llvm::cerr << "Writing '" << Filename << "'.\n";
554
555 llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
556 std::string filename = Filename.toString();
Daniel Dunbar26fb2722008-11-13 05:09:21 +0000557 Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), false, ErrMsg));
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000558
559 if (!ErrMsg.empty())
560 return 0;
561
Ted Kremenek710ad932008-08-28 03:54:51 +0000562 return new UbigraphViz(Stream.take(), Dir, Filename);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000563}
564
565void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
Ted Kremenek45479c82008-08-28 18:34:41 +0000566
567 assert (Src != Dst && "Self-edges are not allowed.");
568
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000569 // Lookup the Src. If it is a new node, it's a root.
570 VMap::iterator SrcI= M.find(Src);
571 unsigned SrcID;
572
573 if (SrcI == M.end()) {
574 M[Src] = SrcID = Cntr++;
575 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
576 }
577 else
578 SrcID = SrcI->second;
579
580 // Lookup the Dst.
581 VMap::iterator DstI= M.find(Dst);
582 unsigned DstID;
583
584 if (DstI == M.end()) {
585 M[Dst] = DstID = Cntr++;
586 *Out << "('vertex', " << DstID << ")\n";
587 }
Ted Kremenek56b98712008-08-28 05:02:09 +0000588 else {
589 // We have hit DstID before. Change its style to reflect a cache hit.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000590 DstID = DstI->second;
Ted Kremenek56b98712008-08-28 05:02:09 +0000591 *Out << "('change_vertex_style', " << DstID << ", 1)\n";
592 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000593
594 // Add the edge.
Ted Kremenekd1289322008-08-27 22:46:55 +0000595 *Out << "('edge', " << SrcID << ", " << DstID
596 << ", ('arrow','true'), ('oriented', 'true'))\n";
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000597}
598
Ted Kremenek56b98712008-08-28 05:02:09 +0000599UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
600 llvm::sys::Path& filename)
601 : Out(out), Dir(dir), Filename(filename), Cntr(0) {
602
603 *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
604 *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
605 " ('size', '1.5'))\n";
606}
607
Ted Kremenek710ad932008-08-28 03:54:51 +0000608UbigraphViz::~UbigraphViz() {
609 Out.reset(0);
610 llvm::cerr << "Running 'ubiviz' program... ";
611 std::string ErrMsg;
612 llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
613 std::vector<const char*> args;
614 args.push_back(Ubiviz.c_str());
615 args.push_back(Filename.c_str());
616 args.push_back(0);
617
618 if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
619 llvm::cerr << "Error viewing graph: " << ErrMsg << "\n";
620 }
621
622 // Delete the directory.
623 Dir.eraseFromDisk(true);
Daniel Dunbar932680e2008-08-29 03:45:59 +0000624}