blob: 14b4440695f96e86db8f00d78dfebcc6d0c5a8ec [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"
Zhongxing Xu22438a82008-11-27 01:55:08 +000016#include "clang/Driver/ManagerRegistry.h"
Ted Kremenekf4381fd2008-07-02 00:03:09 +000017#include "clang/AST/ASTConsumer.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclObjC.h"
20#include "llvm/Support/Compiler.h"
Ted Kremenekf4381fd2008-07-02 00:03:09 +000021#include "llvm/ADT/OwningPtr.h"
22#include "clang/AST/CFG.h"
23#include "clang/Analysis/Analyses/LiveVariables.h"
24#include "clang/Analysis/PathDiagnostic.h"
25#include "clang/Basic/SourceManager.h"
26#include "clang/Basic/FileManager.h"
27#include "clang/AST/ParentMap.h"
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000028#include "clang/AST/TranslationUnit.h"
Ted Kremenekc0959972008-07-02 21:24:01 +000029#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenekf4381fd2008-07-02 00:03:09 +000030#include "clang/Analysis/Analyses/LiveVariables.h"
31#include "clang/Analysis/LocalCheckers.h"
32#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
33#include "clang/Analysis/PathSensitive/GRExprEngine.h"
Ted Kremenek34d77342008-07-02 16:49:11 +000034#include "llvm/Support/Streams.h"
Ted Kremenekf8ce6992008-08-27 22:31:43 +000035#include "llvm/Support/raw_ostream.h"
36#include "llvm/System/Path.h"
Ted Kremenek710ad932008-08-28 03:54:51 +000037#include "llvm/System/Program.h"
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000038#include <vector>
39
Ted Kremenekf4381fd2008-07-02 00:03:09 +000040using namespace clang;
41
Ted Kremenekf8ce6992008-08-27 22:31:43 +000042static ExplodedNodeImpl::Auditor* CreateUbiViz();
Ted Kremenekf4381fd2008-07-02 00:03:09 +000043
44//===----------------------------------------------------------------------===//
45// Basic type definitions.
46//===----------------------------------------------------------------------===//
47
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000048namespace {
Ted Kremenekf4381fd2008-07-02 00:03:09 +000049 class AnalysisManager;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000050 typedef void (*CodeAction)(AnalysisManager& Mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +000051} // end anonymous namespace
52
53//===----------------------------------------------------------------------===//
54// AnalysisConsumer declaration.
55//===----------------------------------------------------------------------===//
56
57namespace {
58
59 class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000060 typedef std::vector<CodeAction> Actions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000061 Actions FunctionActions;
62 Actions ObjCMethodActions;
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000063 Actions ObjCImplementationActions;
Ted Kremenekdaac6342008-11-07 02:09:25 +000064 Actions TranslationUnitActions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000065
66 public:
Ted Kremenekf8ce6992008-08-27 22:31:43 +000067 const bool VisGraphviz;
68 const bool VisUbigraph;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000069 const bool TrimGraph;
Ted Kremenek95c7b002008-10-24 01:04:59 +000070 const LangOptions& LOpts;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000071 Diagnostic &Diags;
72 ASTContext* Ctx;
73 Preprocessor* PP;
74 PreprocessorFactory* PPF;
75 const std::string HTMLDir;
76 const std::string FName;
77 llvm::OwningPtr<PathDiagnosticClient> PD;
78 bool AnalyzeAll;
Ted Kremenek95c7b002008-10-24 01:04:59 +000079 AnalysisStores SM;
Ted Kremenek4fc82c82008-11-03 23:18:07 +000080 AnalysisDiagClients DC;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000081
82 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
83 PreprocessorFactory* ppf,
84 const LangOptions& lopts,
85 const std::string& fname,
86 const std::string& htmldir,
Ted Kremenek4fc82c82008-11-03 23:18:07 +000087 AnalysisStores sm, AnalysisDiagClients dc,
Ted Kremenekf8ce6992008-08-27 22:31:43 +000088 bool visgraphviz, bool visubi, bool trim, bool analyzeAll)
89 : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
90 LOpts(lopts), Diags(diags),
Ted Kremenekf4381fd2008-07-02 00:03:09 +000091 Ctx(0), PP(pp), PPF(ppf),
92 HTMLDir(htmldir),
93 FName(fname),
Ted Kremenek4fc82c82008-11-03 23:18:07 +000094 AnalyzeAll(analyzeAll), SM(sm), DC(dc) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +000095
96 void addCodeAction(CodeAction action) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000097 FunctionActions.push_back(action);
98 ObjCMethodActions.push_back(action);
99 }
100
101 void addObjCImplementationAction(CodeAction action) {
102 ObjCImplementationActions.push_back(action);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000103 }
104
Ted Kremenekdaac6342008-11-07 02:09:25 +0000105 void addTranslationUnitAction(CodeAction action) {
106 TranslationUnitActions.push_back(action);
107 }
108
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000109 virtual void Initialize(ASTContext &Context) {
110 Ctx = &Context;
111 }
112
113 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000114 virtual void HandleTranslationUnit(TranslationUnit &TU);
115
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000116 void HandleCode(Decl* D, Stmt* Body, Actions actions);
117 };
118
119
Ted Kremenekc0959972008-07-02 21:24:01 +0000120 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000121 Decl* D; Stmt* Body;
122 TranslationUnit* TU;
123
124 enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
125
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000126 AnalysisConsumer& C;
Ted Kremenek34d77342008-07-02 16:49:11 +0000127 bool DisplayedFunction;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000128
129 llvm::OwningPtr<CFG> cfg;
130 llvm::OwningPtr<LiveVariables> liveness;
131 llvm::OwningPtr<ParentMap> PM;
132
Zhongxing Xu22438a82008-11-27 01:55:08 +0000133 // Configurable components creators.
134 StoreManagerCreator CreateStoreMgr;
135 ConstraintManagerCreator CreateConstraintMgr;
136
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000137 public:
138 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
Zhongxing Xu22438a82008-11-27 01:55:08 +0000139 : D(d), Body(b), TU(0), AScope(ScopeDecl), C(c), DisplayedFunction(false) {
140 setManagerCreators();
141 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000142
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000143 AnalysisManager(AnalysisConsumer& c, TranslationUnit* tu)
Zhongxing Xu22438a82008-11-27 01:55:08 +0000144 : D(0), Body(0), TU(tu), AScope(ScopeTU), C(c), DisplayedFunction(false) {
145 setManagerCreators();
146 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000147
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000148 Decl* getCodeDecl() const {
149 assert (AScope == ScopeDecl);
150 return D;
151 }
152
153 Stmt* getBody() const {
154 assert (AScope == ScopeDecl);
155 return Body;
156 }
157
158 TranslationUnit* getTranslationUnit() const {
159 assert (AScope == ScopeTU);
160 return TU;
161 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000162
Zhongxing Xu22438a82008-11-27 01:55:08 +0000163 StoreManagerCreator getStoreManagerCreator() {
164 return CreateStoreMgr;
Ted Kremenek95c7b002008-10-24 01:04:59 +0000165 };
Zhongxing Xu22438a82008-11-27 01:55:08 +0000166
167 ConstraintManagerCreator getConstraintManagerCreator() {
168 return CreateConstraintMgr;
169 }
Ted Kremenek95c7b002008-10-24 01:04:59 +0000170
Ted Kremenek7032f462008-07-03 05:26:14 +0000171 virtual CFG* getCFG() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000172 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenek7032f462008-07-03 05:26:14 +0000173 return cfg.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000174 }
175
Ted Kremenekc0959972008-07-02 21:24:01 +0000176 virtual ParentMap& getParentMap() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000177 if (!PM)
178 PM.reset(new ParentMap(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000179 return *PM.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000180 }
181
Ted Kremenekc0959972008-07-02 21:24:01 +0000182 virtual ASTContext& getContext() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000183 return *C.Ctx;
184 }
185
Ted Kremenekc0959972008-07-02 21:24:01 +0000186 virtual SourceManager& getSourceManager() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000187 return getContext().getSourceManager();
188 }
189
Ted Kremenekc0959972008-07-02 21:24:01 +0000190 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000191 return C.Diags;
192 }
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000193
194 const LangOptions& getLangOptions() const {
195 return C.LOpts;
196 }
197
Ted Kremenekc0959972008-07-02 21:24:01 +0000198 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000199 if (C.PD.get() == 0 && !C.HTMLDir.empty()) {
200 switch (C.DC) {
201 default:
202#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)\
203case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break;
204#include "Analyses.def"
205 }
206 }
Ted Kremeneke2075582008-07-02 23:16:33 +0000207 return C.PD.get();
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000208 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000209
Ted Kremenek7032f462008-07-03 05:26:14 +0000210 virtual LiveVariables* getLiveVariables() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000211 if (!liveness) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000212 CFG* c = getCFG();
213 if (!c) return 0;
214
215 liveness.reset(new LiveVariables(*c));
216 liveness->runOnCFG(*c);
217 liveness->runOnAllBlocks(*c, 0, true);
Ted Kremenek235e0312008-07-02 18:11:29 +0000218 }
Ted Kremenekc0959972008-07-02 21:24:01 +0000219
Ted Kremenek7032f462008-07-03 05:26:14 +0000220 return liveness.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000221 }
Ted Kremenek34d77342008-07-02 16:49:11 +0000222
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000223 bool shouldVisualizeGraphviz() const {
224 return C.VisGraphviz;
225 }
Zhongxing Xu22438a82008-11-27 01:55:08 +0000226
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000227 bool shouldVisualizeUbigraph() const {
228 return C.VisUbigraph;
229 }
230
Ted Kremenek34d77342008-07-02 16:49:11 +0000231 bool shouldVisualize() const {
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000232 return C.VisGraphviz || C.VisUbigraph;
Ted Kremenek34d77342008-07-02 16:49:11 +0000233 }
234
235 bool shouldTrimGraph() const {
236 return C.TrimGraph;
237 }
238
239 void DisplayFunction() {
240
241 if (DisplayedFunction)
242 return;
243
244 DisplayedFunction = true;
245
246 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(getCodeDecl())) {
Ted Kremeneka88fcef2008-11-20 16:14:48 +0000247 llvm::cerr << "ANALYZE: "
Ted Kremenek34d77342008-07-02 16:49:11 +0000248 << getContext().getSourceManager().getSourceName(FD->getLocation())
249 << ' '
250 << FD->getIdentifier()->getName()
251 << '\n';
252 }
253 else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCodeDecl())) {
Ted Kremeneka88fcef2008-11-20 16:14:48 +0000254 llvm::cerr << "ANALYZE (ObjC Method): "
Ted Kremenek34d77342008-07-02 16:49:11 +0000255 << getContext().getSourceManager().getSourceName(MD->getLocation())
256 << " '"
Chris Lattner077bf5e2008-11-24 03:33:13 +0000257 << MD->getSelector().getAsString() << "'\n";
Ted Kremenek34d77342008-07-02 16:49:11 +0000258 }
259 }
Zhongxing Xu22438a82008-11-27 01:55:08 +0000260
261 private:
262 /// Set configurable analyzer components creators. First check if there are
263 /// components registered at runtime. Otherwise fall back to builtin
264 /// components.
265 void setManagerCreators() {
266 if (ManagerRegistry::StoreMgrCreator != 0) {
267 CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
268 }
269 else {
270 switch (C.SM) {
271 default:
272 assert(0 && "Unknown store manager.");
273#define ANALYSIS_STORE(NAME, CMDFLAG, DESC) \
274 case NAME##Model: CreateStoreMgr = Create##NAME##Manager; break;
275#include "Analyses.def"
276 }
277 }
278
279 if (ManagerRegistry::ConstraintMgrCreator != 0)
280 CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
281 else
282 CreateConstraintMgr = CreateBasicConstraintManager;
283 }
284
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000285 };
Zhongxing Xu22438a82008-11-27 01:55:08 +0000286
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000287} // end anonymous namespace
288
289namespace llvm {
290 template <> struct FoldingSetTrait<CodeAction> {
291 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
292 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
293 }
294 };
295}
296
297//===----------------------------------------------------------------------===//
298// AnalysisConsumer implementation.
299//===----------------------------------------------------------------------===//
300
301void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
302 switch (D->getKind()) {
303 case Decl::Function: {
304 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000305
306 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
307 break;
308
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000309 Stmt* Body = FD->getBody();
310 if (Body) HandleCode(FD, Body, FunctionActions);
311 break;
312 }
313
314 case Decl::ObjCMethod: {
315 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000316
Chris Lattner077bf5e2008-11-24 03:33:13 +0000317 if (FName.size() > 0 && FName != MD->getSelector().getAsString())
Ted Kremenek235e0312008-07-02 18:11:29 +0000318 return;
319
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000320 Stmt* Body = MD->getBody();
321 if (Body) HandleCode(MD, Body, ObjCMethodActions);
322 break;
323 }
324
325 default:
326 break;
327 }
328}
329
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000330void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
331
Ted Kremenekdaac6342008-11-07 02:09:25 +0000332 if(!TranslationUnitActions.empty()) {
333 AnalysisManager mgr(*this, &TU);
334 for (Actions::iterator I = TranslationUnitActions.begin(),
335 E = TranslationUnitActions.end(); I != E; ++I)
336 (*I)(mgr);
337 }
338
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000339 if (ObjCImplementationActions.empty())
340 return;
341
342 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) {
343
344 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
345 HandleCode(ID, 0, ObjCImplementationActions);
346 }
347}
348
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000349void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
350
351 // Don't run the actions if an error has occured with parsing the file.
352 if (Diags.hasErrorOccurred())
353 return;
354
355 SourceLocation Loc = D->getLocation();
356
357 // Only run actions on declarations defined in actual source.
358 if (!Loc.isFileID())
359 return;
360
361 // Don't run the actions on declarations in header files unless
362 // otherwise specified.
363 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
364 return;
365
366 // Create an AnalysisManager that will manage the state for analyzing
367 // this method/function.
368 AnalysisManager mgr(*this, D, Body);
369
370 // Dispatch on the actions.
Zhongxing Xu3702af52008-10-30 05:03:28 +0000371 for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000372 (*I)(mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000373}
374
375//===----------------------------------------------------------------------===//
376// Analyses
377//===----------------------------------------------------------------------===//
378
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000379static void ActionWarnDeadStores(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000380 if (LiveVariables* L = mgr.getLiveVariables()) {
381 BugReporter BR(mgr);
382 CheckDeadStores(*L, BR);
383 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000384}
385
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000386static void ActionWarnUninitVals(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000387 if (CFG* c = mgr.getCFG())
388 CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000389}
390
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000391
Ted Kremenek78d46242008-07-22 16:21:24 +0000392static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
393 bool StandardWarnings = true) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000394
Ted Kremenek7032f462008-07-03 05:26:14 +0000395
Ted Kremenekbc46f342008-07-02 16:35:50 +0000396 llvm::OwningPtr<GRTransferFuncs> TF(tf);
Ted Kremenek7032f462008-07-03 05:26:14 +0000397
Ted Kremenek8ffc8a52008-11-24 20:53:32 +0000398 // Display progress.
399 mgr.DisplayFunction();
400
Ted Kremenek7032f462008-07-03 05:26:14 +0000401 // Construct the analysis engine.
402 LiveVariables* L = mgr.getLiveVariables();
403 if (!L) return;
Ted Kremenek8ffc8a52008-11-24 20:53:32 +0000404
Ted Kremenek95c7b002008-10-24 01:04:59 +0000405 GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L,
Zhongxing Xu22438a82008-11-27 01:55:08 +0000406 mgr.getStoreManagerCreator(),
407 mgr.getConstraintManagerCreator());
Ted Kremenek95c7b002008-10-24 01:04:59 +0000408
Ted Kremenekbc46f342008-07-02 16:35:50 +0000409 Eng.setTransferFunctions(tf);
410
Ted Kremenek78d46242008-07-22 16:21:24 +0000411 if (StandardWarnings) {
412 Eng.RegisterInternalChecks();
413 RegisterAppleChecks(Eng);
414 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000415
416 // Set the graph auditor.
417 llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor;
418 if (mgr.shouldVisualizeUbigraph()) {
419 Auditor.reset(CreateUbiViz());
420 ExplodedNodeImpl::SetAuditor(Auditor.get());
421 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000422
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000423 // Execute the worklist algorithm.
424 Eng.ExecuteWorkList();
Ted Kremenekbc46f342008-07-02 16:35:50 +0000425
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000426 // Release the auditor (if any) so that it doesn't monitor the graph
427 // created BugReporter.
428 ExplodedNodeImpl::SetAuditor(0);
429
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000430 // Display warnings.
Ted Kremenekc0959972008-07-02 21:24:01 +0000431 Eng.EmitWarnings(mgr);
Ted Kremenek34d77342008-07-02 16:49:11 +0000432
433 // Visualize the exploded graph.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000434 if (mgr.shouldVisualizeGraphviz())
Ted Kremenek34d77342008-07-02 16:49:11 +0000435 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000436}
437
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000438static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
Ted Kremenek78d46242008-07-22 16:21:24 +0000439 bool StandardWarnings) {
440
Ted Kremenekbc46f342008-07-02 16:35:50 +0000441 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
442 GCEnabled,
Ted Kremenekbc46f342008-07-02 16:35:50 +0000443 mgr.getLangOptions());
444
Ted Kremenek78d46242008-07-22 16:21:24 +0000445 ActionGRExprEngine(mgr, TF, StandardWarnings);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000446}
447
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000448static void ActionCheckerCFRef(AnalysisManager& mgr) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000449
450 switch (mgr.getLangOptions().getGCMode()) {
451 default:
452 assert (false && "Invalid GC mode.");
453 case LangOptions::NonGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000454 ActionCheckerCFRefAux(mgr, false, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000455 break;
456
457 case LangOptions::GCOnly:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000458 ActionCheckerCFRefAux(mgr, true, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000459 break;
460
461 case LangOptions::HybridGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000462 ActionCheckerCFRefAux(mgr, false, true);
463 ActionCheckerCFRefAux(mgr, true, false);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000464 break;
465 }
466}
467
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000468static void ActionCheckerSimple(AnalysisManager& mgr) {
Ted Kremenekbc46f342008-07-02 16:35:50 +0000469 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
470}
471
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000472static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000473 if (LiveVariables* L = mgr.getLiveVariables()) {
474 mgr.DisplayFunction();
475 L->dumpBlockLiveness(mgr.getSourceManager());
476 }
Ted Kremenek235e0312008-07-02 18:11:29 +0000477}
478
Ted Kremenek902141f2008-07-02 18:23:21 +0000479static void ActionCFGDump(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000480 if (CFG* c = mgr.getCFG()) {
481 mgr.DisplayFunction();
482 c->dump();
483 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000484}
485
486static void ActionCFGView(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000487 if (CFG* c = mgr.getCFG()) {
488 mgr.DisplayFunction();
489 c->viewCFG();
490 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000491}
492
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000493static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
Ted Kremenek4f4e7e42008-08-04 17:14:10 +0000494 if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
495 return;
496
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000497 BugReporter BR(mgr);
Ted Kremenek3cd483c2008-07-03 14:35:01 +0000498
499 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
500 mgr.getLangOptions(), BR);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000501}
502
Ted Kremenek395aaf22008-07-23 00:45:26 +0000503static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
504 BugReporter BR(mgr);
505 CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
506}
507
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000508static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
Ted Kremenek0d8019e2008-07-11 22:40:47 +0000509 BugReporter BR(mgr);
510
511 CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
512 BR);
513}
514
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000515//===----------------------------------------------------------------------===//
516// AnalysisConsumer creation.
517//===----------------------------------------------------------------------===//
518
519ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
Ted Kremenek95c7b002008-10-24 01:04:59 +0000520 AnalysisStores SM,
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000521 AnalysisDiagClients DC,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000522 Diagnostic &diags, Preprocessor* pp,
523 PreprocessorFactory* ppf,
524 const LangOptions& lopts,
525 const std::string& fname,
526 const std::string& htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000527 bool VisGraphviz, bool VisUbi,
528 bool trim,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000529 bool analyzeAll) {
530
531 llvm::OwningPtr<AnalysisConsumer>
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000532 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir, SM, DC,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000533 VisGraphviz, VisUbi, trim, analyzeAll));
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000534
535 for ( ; Beg != End ; ++Beg)
536 switch (*Beg) {
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000537#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000538 case NAME:\
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000539 C->add ## SCOPE ## Action(&Action ## NAME);\
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000540 break;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000541#include "Analyses.def"
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000542 default: break;
543 }
544
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000545 return C.take();
546}
547
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000548//===----------------------------------------------------------------------===//
549// Ubigraph Visualization. FIXME: Move to separate file.
550//===----------------------------------------------------------------------===//
551
552namespace {
553
554class UbigraphViz : public ExplodedNodeImpl::Auditor {
555 llvm::OwningPtr<llvm::raw_ostream> Out;
Ted Kremenek710ad932008-08-28 03:54:51 +0000556 llvm::sys::Path Dir, Filename;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000557 unsigned Cntr;
558
559 typedef llvm::DenseMap<void*,unsigned> VMap;
560 VMap M;
561
562public:
Ted Kremenek710ad932008-08-28 03:54:51 +0000563 UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
Ted Kremenek56b98712008-08-28 05:02:09 +0000564 llvm::sys::Path& filename);
Ted Kremenek710ad932008-08-28 03:54:51 +0000565
566 ~UbigraphViz();
567
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000568 virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
569};
570
571} // end anonymous namespace
572
573static ExplodedNodeImpl::Auditor* CreateUbiViz() {
574 std::string ErrMsg;
575
Ted Kremenek710ad932008-08-28 03:54:51 +0000576 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000577 if (!ErrMsg.empty())
578 return 0;
579
Ted Kremenek710ad932008-08-28 03:54:51 +0000580 llvm::sys::Path Filename = Dir;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000581 Filename.appendComponent("llvm_ubi");
582 Filename.makeUnique(true,&ErrMsg);
583
584 if (!ErrMsg.empty())
585 return 0;
586
587 llvm::cerr << "Writing '" << Filename << "'.\n";
588
589 llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
590 std::string filename = Filename.toString();
Daniel Dunbar26fb2722008-11-13 05:09:21 +0000591 Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), false, ErrMsg));
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000592
593 if (!ErrMsg.empty())
594 return 0;
595
Ted Kremenek710ad932008-08-28 03:54:51 +0000596 return new UbigraphViz(Stream.take(), Dir, Filename);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000597}
598
599void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
Ted Kremenek45479c82008-08-28 18:34:41 +0000600
601 assert (Src != Dst && "Self-edges are not allowed.");
602
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000603 // Lookup the Src. If it is a new node, it's a root.
604 VMap::iterator SrcI= M.find(Src);
605 unsigned SrcID;
606
607 if (SrcI == M.end()) {
608 M[Src] = SrcID = Cntr++;
609 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
610 }
611 else
612 SrcID = SrcI->second;
613
614 // Lookup the Dst.
615 VMap::iterator DstI= M.find(Dst);
616 unsigned DstID;
617
618 if (DstI == M.end()) {
619 M[Dst] = DstID = Cntr++;
620 *Out << "('vertex', " << DstID << ")\n";
621 }
Ted Kremenek56b98712008-08-28 05:02:09 +0000622 else {
623 // We have hit DstID before. Change its style to reflect a cache hit.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000624 DstID = DstI->second;
Ted Kremenek56b98712008-08-28 05:02:09 +0000625 *Out << "('change_vertex_style', " << DstID << ", 1)\n";
626 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000627
628 // Add the edge.
Ted Kremenekd1289322008-08-27 22:46:55 +0000629 *Out << "('edge', " << SrcID << ", " << DstID
630 << ", ('arrow','true'), ('oriented', 'true'))\n";
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000631}
632
Ted Kremenek56b98712008-08-28 05:02:09 +0000633UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
634 llvm::sys::Path& filename)
635 : Out(out), Dir(dir), Filename(filename), Cntr(0) {
636
637 *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
638 *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
639 " ('size', '1.5'))\n";
640}
641
Ted Kremenek710ad932008-08-28 03:54:51 +0000642UbigraphViz::~UbigraphViz() {
643 Out.reset(0);
644 llvm::cerr << "Running 'ubiviz' program... ";
645 std::string ErrMsg;
646 llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
647 std::vector<const char*> args;
648 args.push_back(Ubiviz.c_str());
649 args.push_back(Filename.c_str());
650 args.push_back(0);
651
652 if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
653 llvm::cerr << "Error viewing graph: " << ErrMsg << "\n";
654 }
655
656 // Delete the directory.
657 Dir.eraseFromDisk(true);
Daniel Dunbar932680e2008-08-29 03:45:59 +0000658}