blob: 236cc1d865dcfe3087e1907cf7797b69424c449f [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"
Zhongxing Xuff944a82008-12-22 01:52:37 +000034#include "llvm/Support/CommandLine.h"
Ted Kremenek34d77342008-07-02 16:49:11 +000035#include "llvm/Support/Streams.h"
Ted Kremenekf8ce6992008-08-27 22:31:43 +000036#include "llvm/Support/raw_ostream.h"
37#include "llvm/System/Path.h"
Ted Kremenek710ad932008-08-28 03:54:51 +000038#include "llvm/System/Program.h"
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000039#include <vector>
40
Ted Kremenekf4381fd2008-07-02 00:03:09 +000041using namespace clang;
42
Ted Kremenekf8ce6992008-08-27 22:31:43 +000043static ExplodedNodeImpl::Auditor* CreateUbiViz();
Zhongxing Xuff944a82008-12-22 01:52:37 +000044
45// Analyzer options.
46static llvm::cl::opt<bool>
47PurgeDead("analyzer-purge-dead",
48 llvm::cl::init(true),
49 llvm::cl::desc("Remove dead symbols, bindings, and constraints before"
50 " processing a statement."));
Ted Kremenekf4381fd2008-07-02 00:03:09 +000051
52//===----------------------------------------------------------------------===//
53// Basic type definitions.
54//===----------------------------------------------------------------------===//
55
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000056namespace {
Ted Kremenekf4381fd2008-07-02 00:03:09 +000057 class AnalysisManager;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000058 typedef void (*CodeAction)(AnalysisManager& Mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +000059} // end anonymous namespace
60
61//===----------------------------------------------------------------------===//
62// AnalysisConsumer declaration.
63//===----------------------------------------------------------------------===//
64
65namespace {
66
67 class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000068 typedef std::vector<CodeAction> Actions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000069 Actions FunctionActions;
70 Actions ObjCMethodActions;
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000071 Actions ObjCImplementationActions;
Ted Kremenekdaac6342008-11-07 02:09:25 +000072 Actions TranslationUnitActions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000073
74 public:
Ted Kremenekf8ce6992008-08-27 22:31:43 +000075 const bool VisGraphviz;
76 const bool VisUbigraph;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000077 const bool TrimGraph;
Ted Kremenek95c7b002008-10-24 01:04:59 +000078 const LangOptions& LOpts;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000079 Diagnostic &Diags;
80 ASTContext* Ctx;
81 Preprocessor* PP;
82 PreprocessorFactory* PPF;
83 const std::string HTMLDir;
84 const std::string FName;
85 llvm::OwningPtr<PathDiagnosticClient> PD;
86 bool AnalyzeAll;
Ted Kremenek95c7b002008-10-24 01:04:59 +000087 AnalysisStores SM;
Ted Kremenek4fc82c82008-11-03 23:18:07 +000088 AnalysisDiagClients DC;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000089
90 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
91 PreprocessorFactory* ppf,
92 const LangOptions& lopts,
93 const std::string& fname,
94 const std::string& htmldir,
Ted Kremenek4fc82c82008-11-03 23:18:07 +000095 AnalysisStores sm, AnalysisDiagClients dc,
Zhongxing Xuff944a82008-12-22 01:52:37 +000096 bool visgraphviz, bool visubi, bool trim, bool analyzeAll)
Ted Kremenekf8ce6992008-08-27 22:31:43 +000097 : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
98 LOpts(lopts), Diags(diags),
Ted Kremenekf4381fd2008-07-02 00:03:09 +000099 Ctx(0), PP(pp), PPF(ppf),
100 HTMLDir(htmldir),
101 FName(fname),
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000102 AnalyzeAll(analyzeAll), SM(sm), DC(dc) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000103
104 void addCodeAction(CodeAction action) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000105 FunctionActions.push_back(action);
106 ObjCMethodActions.push_back(action);
107 }
108
109 void addObjCImplementationAction(CodeAction action) {
110 ObjCImplementationActions.push_back(action);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000111 }
112
Ted Kremenekdaac6342008-11-07 02:09:25 +0000113 void addTranslationUnitAction(CodeAction action) {
114 TranslationUnitActions.push_back(action);
115 }
116
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000117 virtual void Initialize(ASTContext &Context) {
118 Ctx = &Context;
119 }
120
121 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000122 virtual void HandleTranslationUnit(TranslationUnit &TU);
123
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000124 void HandleCode(Decl* D, Stmt* Body, Actions actions);
125 };
126
127
Ted Kremenekc0959972008-07-02 21:24:01 +0000128 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000129 Decl* D; Stmt* Body;
130 TranslationUnit* TU;
131
132 enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
133
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000134 AnalysisConsumer& C;
Ted Kremenek34d77342008-07-02 16:49:11 +0000135 bool DisplayedFunction;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000136
137 llvm::OwningPtr<CFG> cfg;
138 llvm::OwningPtr<LiveVariables> liveness;
139 llvm::OwningPtr<ParentMap> PM;
140
Zhongxing Xu22438a82008-11-27 01:55:08 +0000141 // Configurable components creators.
142 StoreManagerCreator CreateStoreMgr;
143 ConstraintManagerCreator CreateConstraintMgr;
144
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000145 public:
146 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
Zhongxing Xuff944a82008-12-22 01:52:37 +0000147 : D(d), Body(b), TU(0), AScope(ScopeDecl), C(c), DisplayedFunction(false){
Zhongxing Xu22438a82008-11-27 01:55:08 +0000148 setManagerCreators();
149 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000150
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000151 AnalysisManager(AnalysisConsumer& c, TranslationUnit* tu)
Zhongxing Xuff944a82008-12-22 01:52:37 +0000152 : D(0), Body(0), TU(tu), AScope(ScopeTU), C(c), DisplayedFunction(false) {
Zhongxing Xu22438a82008-11-27 01:55:08 +0000153 setManagerCreators();
154 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000155
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000156 Decl* getCodeDecl() const {
157 assert (AScope == ScopeDecl);
158 return D;
159 }
160
161 Stmt* getBody() const {
162 assert (AScope == ScopeDecl);
163 return Body;
164 }
165
166 TranslationUnit* getTranslationUnit() const {
167 assert (AScope == ScopeTU);
168 return TU;
169 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000170
Zhongxing Xu22438a82008-11-27 01:55:08 +0000171 StoreManagerCreator getStoreManagerCreator() {
172 return CreateStoreMgr;
Ted Kremenek95c7b002008-10-24 01:04:59 +0000173 };
Zhongxing Xu22438a82008-11-27 01:55:08 +0000174
175 ConstraintManagerCreator getConstraintManagerCreator() {
176 return CreateConstraintMgr;
177 }
Ted Kremenek95c7b002008-10-24 01:04:59 +0000178
Ted Kremenek7032f462008-07-03 05:26:14 +0000179 virtual CFG* getCFG() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000180 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenek7032f462008-07-03 05:26:14 +0000181 return cfg.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000182 }
183
Ted Kremenekc0959972008-07-02 21:24:01 +0000184 virtual ParentMap& getParentMap() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000185 if (!PM)
186 PM.reset(new ParentMap(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000187 return *PM.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000188 }
189
Ted Kremenekc0959972008-07-02 21:24:01 +0000190 virtual ASTContext& getContext() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000191 return *C.Ctx;
192 }
193
Ted Kremenekc0959972008-07-02 21:24:01 +0000194 virtual SourceManager& getSourceManager() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000195 return getContext().getSourceManager();
196 }
197
Ted Kremenekc0959972008-07-02 21:24:01 +0000198 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000199 return C.Diags;
200 }
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000201
202 const LangOptions& getLangOptions() const {
203 return C.LOpts;
204 }
205
Ted Kremenekc0959972008-07-02 21:24:01 +0000206 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000207 if (C.PD.get() == 0 && !C.HTMLDir.empty()) {
208 switch (C.DC) {
209 default:
Ted Kremenekc472d792009-01-23 20:06:20 +0000210#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000211case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break;
212#include "Analyses.def"
213 }
214 }
Ted Kremeneke2075582008-07-02 23:16:33 +0000215 return C.PD.get();
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000216 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000217
Ted Kremenek7032f462008-07-03 05:26:14 +0000218 virtual LiveVariables* getLiveVariables() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000219 if (!liveness) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000220 CFG* c = getCFG();
221 if (!c) return 0;
222
Ted Kremenekca9bab02008-12-09 00:17:51 +0000223 liveness.reset(new LiveVariables(getContext(), *c));
Ted Kremenek7032f462008-07-03 05:26:14 +0000224 liveness->runOnCFG(*c);
225 liveness->runOnAllBlocks(*c, 0, true);
Ted Kremenek235e0312008-07-02 18:11:29 +0000226 }
Ted Kremenekc0959972008-07-02 21:24:01 +0000227
Ted Kremenek7032f462008-07-03 05:26:14 +0000228 return liveness.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000229 }
Ted Kremenek34d77342008-07-02 16:49:11 +0000230
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000231 bool shouldVisualizeGraphviz() const {
232 return C.VisGraphviz;
233 }
Zhongxing Xu22438a82008-11-27 01:55:08 +0000234
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000235 bool shouldVisualizeUbigraph() const {
236 return C.VisUbigraph;
237 }
238
Ted Kremenek34d77342008-07-02 16:49:11 +0000239 bool shouldVisualize() const {
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000240 return C.VisGraphviz || C.VisUbigraph;
Ted Kremenek34d77342008-07-02 16:49:11 +0000241 }
242
243 bool shouldTrimGraph() const {
244 return C.TrimGraph;
245 }
246
247 void DisplayFunction() {
248
249 if (DisplayedFunction)
250 return;
251
252 DisplayedFunction = true;
253
254 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(getCodeDecl())) {
Ted Kremeneka88fcef2008-11-20 16:14:48 +0000255 llvm::cerr << "ANALYZE: "
Ted Kremenek34d77342008-07-02 16:49:11 +0000256 << getContext().getSourceManager().getSourceName(FD->getLocation())
257 << ' '
258 << FD->getIdentifier()->getName()
259 << '\n';
260 }
261 else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCodeDecl())) {
Ted Kremeneka88fcef2008-11-20 16:14:48 +0000262 llvm::cerr << "ANALYZE (ObjC Method): "
Ted Kremenek34d77342008-07-02 16:49:11 +0000263 << getContext().getSourceManager().getSourceName(MD->getLocation())
264 << " '"
Chris Lattner077bf5e2008-11-24 03:33:13 +0000265 << MD->getSelector().getAsString() << "'\n";
Ted Kremenek34d77342008-07-02 16:49:11 +0000266 }
267 }
Zhongxing Xu22438a82008-11-27 01:55:08 +0000268
269 private:
270 /// Set configurable analyzer components creators. First check if there are
271 /// components registered at runtime. Otherwise fall back to builtin
272 /// components.
273 void setManagerCreators() {
274 if (ManagerRegistry::StoreMgrCreator != 0) {
275 CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
276 }
277 else {
278 switch (C.SM) {
279 default:
280 assert(0 && "Unknown store manager.");
281#define ANALYSIS_STORE(NAME, CMDFLAG, DESC) \
282 case NAME##Model: CreateStoreMgr = Create##NAME##Manager; break;
283#include "Analyses.def"
284 }
285 }
286
287 if (ManagerRegistry::ConstraintMgrCreator != 0)
288 CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
289 else
290 CreateConstraintMgr = CreateBasicConstraintManager;
Ted Kremenekc472d792009-01-23 20:06:20 +0000291
292 // Some DiagnosticClients should be created all the time instead of
293 // lazily. Create those now.
294 switch (C.DC) {
295 default: break;
296#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\
297case PD_##NAME: if (AUTOCREATE) getPathDiagnosticClient(); break;
298#include "Analyses.def"
299 }
Zhongxing Xu22438a82008-11-27 01:55:08 +0000300 }
301
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000302 };
Zhongxing Xu22438a82008-11-27 01:55:08 +0000303
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000304} // end anonymous namespace
305
306namespace llvm {
307 template <> struct FoldingSetTrait<CodeAction> {
308 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
309 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
310 }
311 };
312}
313
314//===----------------------------------------------------------------------===//
315// AnalysisConsumer implementation.
316//===----------------------------------------------------------------------===//
317
318void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
319 switch (D->getKind()) {
320 case Decl::Function: {
321 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000322
323 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
324 break;
325
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000326 Stmt* Body = FD->getBody();
327 if (Body) HandleCode(FD, Body, FunctionActions);
328 break;
329 }
330
331 case Decl::ObjCMethod: {
332 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000333
Chris Lattner077bf5e2008-11-24 03:33:13 +0000334 if (FName.size() > 0 && FName != MD->getSelector().getAsString())
Ted Kremenek235e0312008-07-02 18:11:29 +0000335 return;
336
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000337 Stmt* Body = MD->getBody();
338 if (Body) HandleCode(MD, Body, ObjCMethodActions);
339 break;
340 }
341
342 default:
343 break;
344 }
345}
346
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000347void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
348
Ted Kremenekdaac6342008-11-07 02:09:25 +0000349 if(!TranslationUnitActions.empty()) {
350 AnalysisManager mgr(*this, &TU);
351 for (Actions::iterator I = TranslationUnitActions.begin(),
352 E = TranslationUnitActions.end(); I != E; ++I)
353 (*I)(mgr);
354 }
355
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000356 if (ObjCImplementationActions.empty())
357 return;
358
359 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) {
360
361 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
362 HandleCode(ID, 0, ObjCImplementationActions);
363 }
364}
365
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000366void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
367
368 // Don't run the actions if an error has occured with parsing the file.
369 if (Diags.hasErrorOccurred())
370 return;
371
372 SourceLocation Loc = D->getLocation();
373
374 // Only run actions on declarations defined in actual source.
375 if (!Loc.isFileID())
376 return;
377
378 // Don't run the actions on declarations in header files unless
379 // otherwise specified.
380 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
381 return;
382
383 // Create an AnalysisManager that will manage the state for analyzing
384 // this method/function.
385 AnalysisManager mgr(*this, D, Body);
386
387 // Dispatch on the actions.
Zhongxing Xu3702af52008-10-30 05:03:28 +0000388 for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000389 (*I)(mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000390}
391
392//===----------------------------------------------------------------------===//
393// Analyses
394//===----------------------------------------------------------------------===//
395
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000396static void ActionWarnDeadStores(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000397 if (LiveVariables* L = mgr.getLiveVariables()) {
398 BugReporter BR(mgr);
399 CheckDeadStores(*L, BR);
400 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000401}
402
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000403static void ActionWarnUninitVals(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000404 if (CFG* c = mgr.getCFG())
405 CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000406}
407
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000408
Ted Kremenek78d46242008-07-22 16:21:24 +0000409static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
410 bool StandardWarnings = true) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000411
Ted Kremenek7032f462008-07-03 05:26:14 +0000412
Ted Kremenekbc46f342008-07-02 16:35:50 +0000413 llvm::OwningPtr<GRTransferFuncs> TF(tf);
Ted Kremenek7032f462008-07-03 05:26:14 +0000414
Ted Kremenek8ffc8a52008-11-24 20:53:32 +0000415 // Display progress.
416 mgr.DisplayFunction();
417
Ted Kremenek7032f462008-07-03 05:26:14 +0000418 // Construct the analysis engine.
419 LiveVariables* L = mgr.getLiveVariables();
420 if (!L) return;
Ted Kremenek8ffc8a52008-11-24 20:53:32 +0000421
Ted Kremenek95c7b002008-10-24 01:04:59 +0000422 GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L,
Zhongxing Xuff944a82008-12-22 01:52:37 +0000423 PurgeDead,
Zhongxing Xu22438a82008-11-27 01:55:08 +0000424 mgr.getStoreManagerCreator(),
425 mgr.getConstraintManagerCreator());
Ted Kremenek95c7b002008-10-24 01:04:59 +0000426
Ted Kremenekbc46f342008-07-02 16:35:50 +0000427 Eng.setTransferFunctions(tf);
428
Ted Kremenek78d46242008-07-22 16:21:24 +0000429 if (StandardWarnings) {
430 Eng.RegisterInternalChecks();
431 RegisterAppleChecks(Eng);
432 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000433
434 // Set the graph auditor.
435 llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor;
436 if (mgr.shouldVisualizeUbigraph()) {
437 Auditor.reset(CreateUbiViz());
438 ExplodedNodeImpl::SetAuditor(Auditor.get());
439 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000440
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000441 // Execute the worklist algorithm.
442 Eng.ExecuteWorkList();
Ted Kremenekbc46f342008-07-02 16:35:50 +0000443
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000444 // Release the auditor (if any) so that it doesn't monitor the graph
445 // created BugReporter.
446 ExplodedNodeImpl::SetAuditor(0);
447
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000448 // Display warnings.
Ted Kremenekc0959972008-07-02 21:24:01 +0000449 Eng.EmitWarnings(mgr);
Ted Kremenek34d77342008-07-02 16:49:11 +0000450
451 // Visualize the exploded graph.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000452 if (mgr.shouldVisualizeGraphviz())
Ted Kremenek34d77342008-07-02 16:49:11 +0000453 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000454}
455
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000456static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
Ted Kremenek78d46242008-07-22 16:21:24 +0000457 bool StandardWarnings) {
458
Ted Kremenekbc46f342008-07-02 16:35:50 +0000459 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
460 GCEnabled,
Ted Kremenekbc46f342008-07-02 16:35:50 +0000461 mgr.getLangOptions());
462
Ted Kremenek78d46242008-07-22 16:21:24 +0000463 ActionGRExprEngine(mgr, TF, StandardWarnings);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000464}
465
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000466static void ActionCheckerCFRef(AnalysisManager& mgr) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000467
468 switch (mgr.getLangOptions().getGCMode()) {
469 default:
470 assert (false && "Invalid GC mode.");
471 case LangOptions::NonGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000472 ActionCheckerCFRefAux(mgr, false, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000473 break;
474
475 case LangOptions::GCOnly:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000476 ActionCheckerCFRefAux(mgr, true, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000477 break;
478
479 case LangOptions::HybridGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000480 ActionCheckerCFRefAux(mgr, false, true);
481 ActionCheckerCFRefAux(mgr, true, false);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000482 break;
483 }
484}
485
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000486static void ActionCheckerSimple(AnalysisManager& mgr) {
Ted Kremenekbc46f342008-07-02 16:35:50 +0000487 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
488}
489
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000490static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000491 if (LiveVariables* L = mgr.getLiveVariables()) {
492 mgr.DisplayFunction();
493 L->dumpBlockLiveness(mgr.getSourceManager());
494 }
Ted Kremenek235e0312008-07-02 18:11:29 +0000495}
496
Ted Kremenek902141f2008-07-02 18:23:21 +0000497static void ActionCFGDump(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000498 if (CFG* c = mgr.getCFG()) {
499 mgr.DisplayFunction();
500 c->dump();
501 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000502}
503
504static void ActionCFGView(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000505 if (CFG* c = mgr.getCFG()) {
506 mgr.DisplayFunction();
507 c->viewCFG();
508 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000509}
510
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000511static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
Ted Kremenek4f4e7e42008-08-04 17:14:10 +0000512 if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
513 return;
514
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000515 BugReporter BR(mgr);
Ted Kremenek3cd483c2008-07-03 14:35:01 +0000516
517 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
518 mgr.getLangOptions(), BR);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000519}
520
Ted Kremenek395aaf22008-07-23 00:45:26 +0000521static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
522 BugReporter BR(mgr);
523 CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
524}
525
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000526static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
Ted Kremenek0d8019e2008-07-11 22:40:47 +0000527 BugReporter BR(mgr);
528
529 CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
530 BR);
531}
532
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000533//===----------------------------------------------------------------------===//
534// AnalysisConsumer creation.
535//===----------------------------------------------------------------------===//
536
537ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
Ted Kremenek95c7b002008-10-24 01:04:59 +0000538 AnalysisStores SM,
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000539 AnalysisDiagClients DC,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000540 Diagnostic &diags, Preprocessor* pp,
541 PreprocessorFactory* ppf,
542 const LangOptions& lopts,
543 const std::string& fname,
544 const std::string& htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000545 bool VisGraphviz, bool VisUbi,
546 bool trim,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000547 bool analyzeAll) {
548
549 llvm::OwningPtr<AnalysisConsumer>
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000550 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir, SM, DC,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000551 VisGraphviz, VisUbi, trim, analyzeAll));
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000552
553 for ( ; Beg != End ; ++Beg)
554 switch (*Beg) {
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000555#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000556 case NAME:\
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000557 C->add ## SCOPE ## Action(&Action ## NAME);\
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000558 break;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000559#include "Analyses.def"
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000560 default: break;
561 }
562
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000563 return C.take();
564}
565
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000566//===----------------------------------------------------------------------===//
567// Ubigraph Visualization. FIXME: Move to separate file.
568//===----------------------------------------------------------------------===//
569
570namespace {
571
572class UbigraphViz : public ExplodedNodeImpl::Auditor {
573 llvm::OwningPtr<llvm::raw_ostream> Out;
Ted Kremenek710ad932008-08-28 03:54:51 +0000574 llvm::sys::Path Dir, Filename;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000575 unsigned Cntr;
576
577 typedef llvm::DenseMap<void*,unsigned> VMap;
578 VMap M;
579
580public:
Ted Kremenek710ad932008-08-28 03:54:51 +0000581 UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
Ted Kremenek56b98712008-08-28 05:02:09 +0000582 llvm::sys::Path& filename);
Ted Kremenek710ad932008-08-28 03:54:51 +0000583
584 ~UbigraphViz();
585
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000586 virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
587};
588
589} // end anonymous namespace
590
591static ExplodedNodeImpl::Auditor* CreateUbiViz() {
592 std::string ErrMsg;
593
Ted Kremenek710ad932008-08-28 03:54:51 +0000594 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000595 if (!ErrMsg.empty())
596 return 0;
597
Ted Kremenek710ad932008-08-28 03:54:51 +0000598 llvm::sys::Path Filename = Dir;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000599 Filename.appendComponent("llvm_ubi");
600 Filename.makeUnique(true,&ErrMsg);
601
602 if (!ErrMsg.empty())
603 return 0;
604
605 llvm::cerr << "Writing '" << Filename << "'.\n";
606
607 llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
608 std::string filename = Filename.toString();
Daniel Dunbar26fb2722008-11-13 05:09:21 +0000609 Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), false, ErrMsg));
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000610
611 if (!ErrMsg.empty())
612 return 0;
613
Ted Kremenek710ad932008-08-28 03:54:51 +0000614 return new UbigraphViz(Stream.take(), Dir, Filename);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000615}
616
617void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
Ted Kremenek45479c82008-08-28 18:34:41 +0000618
619 assert (Src != Dst && "Self-edges are not allowed.");
620
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000621 // Lookup the Src. If it is a new node, it's a root.
622 VMap::iterator SrcI= M.find(Src);
623 unsigned SrcID;
624
625 if (SrcI == M.end()) {
626 M[Src] = SrcID = Cntr++;
627 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
628 }
629 else
630 SrcID = SrcI->second;
631
632 // Lookup the Dst.
633 VMap::iterator DstI= M.find(Dst);
634 unsigned DstID;
635
636 if (DstI == M.end()) {
637 M[Dst] = DstID = Cntr++;
638 *Out << "('vertex', " << DstID << ")\n";
639 }
Ted Kremenek56b98712008-08-28 05:02:09 +0000640 else {
641 // We have hit DstID before. Change its style to reflect a cache hit.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000642 DstID = DstI->second;
Ted Kremenek56b98712008-08-28 05:02:09 +0000643 *Out << "('change_vertex_style', " << DstID << ", 1)\n";
644 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000645
646 // Add the edge.
Ted Kremenekd1289322008-08-27 22:46:55 +0000647 *Out << "('edge', " << SrcID << ", " << DstID
648 << ", ('arrow','true'), ('oriented', 'true'))\n";
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000649}
650
Ted Kremenek56b98712008-08-28 05:02:09 +0000651UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
652 llvm::sys::Path& filename)
653 : Out(out), Dir(dir), Filename(filename), Cntr(0) {
654
655 *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
656 *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
657 " ('size', '1.5'))\n";
658}
659
Ted Kremenek710ad932008-08-28 03:54:51 +0000660UbigraphViz::~UbigraphViz() {
661 Out.reset(0);
662 llvm::cerr << "Running 'ubiviz' program... ";
663 std::string ErrMsg;
664 llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
665 std::vector<const char*> args;
666 args.push_back(Ubiviz.c_str());
667 args.push_back(Filename.c_str());
668 args.push_back(0);
669
670 if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
671 llvm::cerr << "Error viewing graph: " << ErrMsg << "\n";
672 }
673
674 // Delete the directory.
675 Dir.eraseFromDisk(true);
Daniel Dunbar932680e2008-08-29 03:45:59 +0000676}