blob: 5c1e3d87bf21550da910de9de5bba9433b2493ce [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 Kremenek45021952009-02-14 17:08:39 +000051static llvm::cl::opt<bool>
52UseRanges("analyzer-range-constraints",
Ted Kremenekf06e9c52009-02-16 17:26:11 +000053 llvm::cl::init(false),
Ted Kremenek45021952009-02-14 17:08:39 +000054 llvm::cl::desc("Use the range constraint manager instead of the basic"
55 " constraint manager"));
Ted Kremenekf4381fd2008-07-02 00:03:09 +000056
57//===----------------------------------------------------------------------===//
58// Basic type definitions.
59//===----------------------------------------------------------------------===//
60
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000061namespace {
Ted Kremenekf4381fd2008-07-02 00:03:09 +000062 class AnalysisManager;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000063 typedef void (*CodeAction)(AnalysisManager& Mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +000064} // end anonymous namespace
65
66//===----------------------------------------------------------------------===//
67// AnalysisConsumer declaration.
68//===----------------------------------------------------------------------===//
69
70namespace {
71
72 class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000073 typedef std::vector<CodeAction> Actions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000074 Actions FunctionActions;
75 Actions ObjCMethodActions;
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000076 Actions ObjCImplementationActions;
Ted Kremenekdaac6342008-11-07 02:09:25 +000077 Actions TranslationUnitActions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000078
79 public:
Ted Kremenekf8ce6992008-08-27 22:31:43 +000080 const bool VisGraphviz;
81 const bool VisUbigraph;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000082 const bool TrimGraph;
Ted Kremenek95c7b002008-10-24 01:04:59 +000083 const LangOptions& LOpts;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000084 Diagnostic &Diags;
85 ASTContext* Ctx;
86 Preprocessor* PP;
87 PreprocessorFactory* PPF;
88 const std::string HTMLDir;
89 const std::string FName;
90 llvm::OwningPtr<PathDiagnosticClient> PD;
91 bool AnalyzeAll;
Ted Kremenek95c7b002008-10-24 01:04:59 +000092 AnalysisStores SM;
Ted Kremenek4fc82c82008-11-03 23:18:07 +000093 AnalysisDiagClients DC;
Ted Kremenek491918e2009-01-23 20:52:26 +000094 const bool DisplayProgress;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000095
96 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
97 PreprocessorFactory* ppf,
98 const LangOptions& lopts,
99 const std::string& fname,
100 const std::string& htmldir,
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000101 AnalysisStores sm, AnalysisDiagClients dc,
Ted Kremenek491918e2009-01-23 20:52:26 +0000102 bool visgraphviz, bool visubi, bool trim, bool analyzeAll,
103 bool displayProgress)
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000104 : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
105 LOpts(lopts), Diags(diags),
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000106 Ctx(0), PP(pp), PPF(ppf),
107 HTMLDir(htmldir),
108 FName(fname),
Ted Kremenek491918e2009-01-23 20:52:26 +0000109 AnalyzeAll(analyzeAll), SM(sm), DC(dc),
110 DisplayProgress(displayProgress) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000111
112 void addCodeAction(CodeAction action) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000113 FunctionActions.push_back(action);
114 ObjCMethodActions.push_back(action);
115 }
116
117 void addObjCImplementationAction(CodeAction action) {
118 ObjCImplementationActions.push_back(action);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000119 }
120
Ted Kremenekdaac6342008-11-07 02:09:25 +0000121 void addTranslationUnitAction(CodeAction action) {
122 TranslationUnitActions.push_back(action);
123 }
124
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000125 virtual void Initialize(ASTContext &Context) {
126 Ctx = &Context;
127 }
128
129 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000130 virtual void HandleTranslationUnit(TranslationUnit &TU);
131
Ted Kremenek81922f02009-02-02 20:52:40 +0000132 void HandleCode(Decl* D, Stmt* Body, Actions& actions);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000133 };
134
135
Ted Kremenekc0959972008-07-02 21:24:01 +0000136 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000137 Decl* D; Stmt* Body;
138 TranslationUnit* TU;
139
140 enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
141
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000142 AnalysisConsumer& C;
Ted Kremenek34d77342008-07-02 16:49:11 +0000143 bool DisplayedFunction;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000144
145 llvm::OwningPtr<CFG> cfg;
146 llvm::OwningPtr<LiveVariables> liveness;
147 llvm::OwningPtr<ParentMap> PM;
148
Zhongxing Xu22438a82008-11-27 01:55:08 +0000149 // Configurable components creators.
150 StoreManagerCreator CreateStoreMgr;
151 ConstraintManagerCreator CreateConstraintMgr;
152
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000153 public:
Ted Kremenek491918e2009-01-23 20:52:26 +0000154 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b, bool displayProgress)
155 : D(d), Body(b), TU(0), AScope(ScopeDecl), C(c),
156 DisplayedFunction(!displayProgress) {
Zhongxing Xu22438a82008-11-27 01:55:08 +0000157 setManagerCreators();
158 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000159
Ted Kremenek491918e2009-01-23 20:52:26 +0000160 AnalysisManager(AnalysisConsumer& c, TranslationUnit* tu,
161 bool displayProgress)
162 : D(0), Body(0), TU(tu), AScope(ScopeTU), C(c),
163 DisplayedFunction(!displayProgress) {
Zhongxing Xu22438a82008-11-27 01:55:08 +0000164 setManagerCreators();
165 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000166
Ted Kremenekf304ddc2008-11-05 19:05:06 +0000167 Decl* getCodeDecl() const {
168 assert (AScope == ScopeDecl);
169 return D;
170 }
171
172 Stmt* getBody() const {
173 assert (AScope == ScopeDecl);
174 return Body;
175 }
176
177 TranslationUnit* getTranslationUnit() const {
178 assert (AScope == ScopeTU);
179 return TU;
180 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000181
Zhongxing Xu22438a82008-11-27 01:55:08 +0000182 StoreManagerCreator getStoreManagerCreator() {
183 return CreateStoreMgr;
Ted Kremenek95c7b002008-10-24 01:04:59 +0000184 };
Zhongxing Xu22438a82008-11-27 01:55:08 +0000185
186 ConstraintManagerCreator getConstraintManagerCreator() {
187 return CreateConstraintMgr;
188 }
Ted Kremenek95c7b002008-10-24 01:04:59 +0000189
Ted Kremenek7032f462008-07-03 05:26:14 +0000190 virtual CFG* getCFG() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000191 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenek7032f462008-07-03 05:26:14 +0000192 return cfg.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000193 }
194
Ted Kremenekc0959972008-07-02 21:24:01 +0000195 virtual ParentMap& getParentMap() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000196 if (!PM)
197 PM.reset(new ParentMap(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000198 return *PM.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000199 }
200
Ted Kremenekc0959972008-07-02 21:24:01 +0000201 virtual ASTContext& getContext() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000202 return *C.Ctx;
203 }
204
Ted Kremenekc0959972008-07-02 21:24:01 +0000205 virtual SourceManager& getSourceManager() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000206 return getContext().getSourceManager();
207 }
208
Ted Kremenekc0959972008-07-02 21:24:01 +0000209 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000210 return C.Diags;
211 }
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000212
213 const LangOptions& getLangOptions() const {
214 return C.LOpts;
215 }
216
Ted Kremenekc0959972008-07-02 21:24:01 +0000217 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000218 if (C.PD.get() == 0 && !C.HTMLDir.empty()) {
219 switch (C.DC) {
220 default:
Ted Kremenekc472d792009-01-23 20:06:20 +0000221#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000222case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break;
223#include "Analyses.def"
224 }
225 }
Ted Kremeneke2075582008-07-02 23:16:33 +0000226 return C.PD.get();
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000227 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000228
Ted Kremenek7032f462008-07-03 05:26:14 +0000229 virtual LiveVariables* getLiveVariables() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000230 if (!liveness) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000231 CFG* c = getCFG();
232 if (!c) return 0;
233
Ted Kremenekca9bab02008-12-09 00:17:51 +0000234 liveness.reset(new LiveVariables(getContext(), *c));
Ted Kremenek7032f462008-07-03 05:26:14 +0000235 liveness->runOnCFG(*c);
236 liveness->runOnAllBlocks(*c, 0, true);
Ted Kremenek235e0312008-07-02 18:11:29 +0000237 }
Ted Kremenekc0959972008-07-02 21:24:01 +0000238
Ted Kremenek7032f462008-07-03 05:26:14 +0000239 return liveness.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000240 }
Ted Kremenek34d77342008-07-02 16:49:11 +0000241
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000242 bool shouldVisualizeGraphviz() const {
243 return C.VisGraphviz;
244 }
Zhongxing Xu22438a82008-11-27 01:55:08 +0000245
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000246 bool shouldVisualizeUbigraph() const {
247 return C.VisUbigraph;
248 }
249
Ted Kremenek34d77342008-07-02 16:49:11 +0000250 bool shouldVisualize() const {
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000251 return C.VisGraphviz || C.VisUbigraph;
Ted Kremenek34d77342008-07-02 16:49:11 +0000252 }
253
254 bool shouldTrimGraph() const {
255 return C.TrimGraph;
256 }
257
258 void DisplayFunction() {
259
260 if (DisplayedFunction)
261 return;
262
263 DisplayedFunction = true;
264
Chris Lattnerb9c3f962009-01-27 07:57:44 +0000265 // FIXME: Is getCodeDecl() always a named decl?
266 if (isa<FunctionDecl>(getCodeDecl()) ||
267 isa<ObjCMethodDecl>(getCodeDecl())) {
268 NamedDecl *ND = cast<NamedDecl>(getCodeDecl());
269 SourceManager &SM = getContext().getSourceManager();
Ted Kremeneka88fcef2008-11-20 16:14:48 +0000270 llvm::cerr << "ANALYZE: "
Chris Lattnerb9c3f962009-01-27 07:57:44 +0000271 << SM.getPresumedLoc(ND->getLocation()).getFilename()
272 << ' ' << ND->getNameAsString() << '\n';
Ted Kremenek34d77342008-07-02 16:49:11 +0000273 }
274 }
Zhongxing Xu22438a82008-11-27 01:55:08 +0000275
276 private:
277 /// Set configurable analyzer components creators. First check if there are
278 /// components registered at runtime. Otherwise fall back to builtin
279 /// components.
280 void setManagerCreators() {
281 if (ManagerRegistry::StoreMgrCreator != 0) {
282 CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
283 }
284 else {
285 switch (C.SM) {
286 default:
287 assert(0 && "Unknown store manager.");
288#define ANALYSIS_STORE(NAME, CMDFLAG, DESC) \
289 case NAME##Model: CreateStoreMgr = Create##NAME##Manager; break;
290#include "Analyses.def"
291 }
292 }
293
294 if (ManagerRegistry::ConstraintMgrCreator != 0)
295 CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
Ted Kremenek45021952009-02-14 17:08:39 +0000296 else if (UseRanges)
297 CreateConstraintMgr = CreateRangeConstraintManager;
Zhongxing Xu22438a82008-11-27 01:55:08 +0000298 else
299 CreateConstraintMgr = CreateBasicConstraintManager;
Ted Kremenekc472d792009-01-23 20:06:20 +0000300
301 // Some DiagnosticClients should be created all the time instead of
302 // lazily. Create those now.
303 switch (C.DC) {
304 default: break;
305#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\
306case PD_##NAME: if (AUTOCREATE) getPathDiagnosticClient(); break;
307#include "Analyses.def"
308 }
Zhongxing Xu22438a82008-11-27 01:55:08 +0000309 }
310
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000311 };
Zhongxing Xu22438a82008-11-27 01:55:08 +0000312
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000313} // end anonymous namespace
314
315namespace llvm {
316 template <> struct FoldingSetTrait<CodeAction> {
317 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
318 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
319 }
320 };
321}
322
323//===----------------------------------------------------------------------===//
324// AnalysisConsumer implementation.
325//===----------------------------------------------------------------------===//
326
327void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
328 switch (D->getKind()) {
329 case Decl::Function: {
330 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000331
332 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
333 break;
334
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000335 Stmt* Body = FD->getBody();
336 if (Body) HandleCode(FD, Body, FunctionActions);
337 break;
338 }
339
340 case Decl::ObjCMethod: {
341 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000342
Chris Lattner077bf5e2008-11-24 03:33:13 +0000343 if (FName.size() > 0 && FName != MD->getSelector().getAsString())
Ted Kremenek235e0312008-07-02 18:11:29 +0000344 return;
345
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000346 Stmt* Body = MD->getBody();
347 if (Body) HandleCode(MD, Body, ObjCMethodActions);
348 break;
349 }
350
351 default:
352 break;
353 }
354}
355
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000356void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
357
Ted Kremenekdaac6342008-11-07 02:09:25 +0000358 if(!TranslationUnitActions.empty()) {
Ted Kremenek491918e2009-01-23 20:52:26 +0000359 AnalysisManager mgr(*this, &TU, DisplayProgress);
Ted Kremenekdaac6342008-11-07 02:09:25 +0000360 for (Actions::iterator I = TranslationUnitActions.begin(),
361 E = TranslationUnitActions.end(); I != E; ++I)
362 (*I)(mgr);
363 }
364
Ted Kremenek4d53a532009-02-13 00:51:30 +0000365 if (!ObjCImplementationActions.empty())
366 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I)
367 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
368 HandleCode(ID, 0, ObjCImplementationActions);
369
370 // Delete the PathDiagnosticClient here just in case the AnalysisConsumer
371 // object doesn't get released. This will cause any side-effects in the
372 // destructor of the PathDiagnosticClient to get executed.
373 PD.reset();
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000374}
375
Ted Kremenek81922f02009-02-02 20:52:40 +0000376void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions& actions) {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000377
378 // Don't run the actions if an error has occured with parsing the file.
379 if (Diags.hasErrorOccurred())
380 return;
Ted Kremenek81922f02009-02-02 20:52:40 +0000381
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000382 // Don't run the actions on declarations in header files unless
383 // otherwise specified.
Ted Kremenek81922f02009-02-02 20:52:40 +0000384 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(D->getLocation()))
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000385 return;
386
387 // Create an AnalysisManager that will manage the state for analyzing
388 // this method/function.
Ted Kremenek491918e2009-01-23 20:52:26 +0000389 AnalysisManager mgr(*this, D, Body, DisplayProgress);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000390
391 // Dispatch on the actions.
Zhongxing Xu3702af52008-10-30 05:03:28 +0000392 for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000393 (*I)(mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000394}
395
396//===----------------------------------------------------------------------===//
397// Analyses
398//===----------------------------------------------------------------------===//
399
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000400static void ActionWarnDeadStores(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000401 if (LiveVariables* L = mgr.getLiveVariables()) {
402 BugReporter BR(mgr);
403 CheckDeadStores(*L, BR);
404 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000405}
406
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000407static void ActionWarnUninitVals(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000408 if (CFG* c = mgr.getCFG())
409 CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000410}
411
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000412
Ted Kremenek78d46242008-07-22 16:21:24 +0000413static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
414 bool StandardWarnings = true) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000415
Ted Kremenek7032f462008-07-03 05:26:14 +0000416
Ted Kremenekbc46f342008-07-02 16:35:50 +0000417 llvm::OwningPtr<GRTransferFuncs> TF(tf);
Ted Kremenek7032f462008-07-03 05:26:14 +0000418
Ted Kremenek8ffc8a52008-11-24 20:53:32 +0000419 // Display progress.
420 mgr.DisplayFunction();
421
Ted Kremenek7032f462008-07-03 05:26:14 +0000422 // Construct the analysis engine.
423 LiveVariables* L = mgr.getLiveVariables();
424 if (!L) return;
Ted Kremenek8ffc8a52008-11-24 20:53:32 +0000425
Ted Kremenekcf118d42009-02-04 23:49:09 +0000426 GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L, mgr,
Zhongxing Xuff944a82008-12-22 01:52:37 +0000427 PurgeDead,
Zhongxing Xu22438a82008-11-27 01:55:08 +0000428 mgr.getStoreManagerCreator(),
429 mgr.getConstraintManagerCreator());
Ted Kremenek95c7b002008-10-24 01:04:59 +0000430
Ted Kremenekbc46f342008-07-02 16:35:50 +0000431 Eng.setTransferFunctions(tf);
432
Ted Kremenek78d46242008-07-22 16:21:24 +0000433 if (StandardWarnings) {
434 Eng.RegisterInternalChecks();
435 RegisterAppleChecks(Eng);
436 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000437
438 // Set the graph auditor.
439 llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor;
440 if (mgr.shouldVisualizeUbigraph()) {
441 Auditor.reset(CreateUbiViz());
442 ExplodedNodeImpl::SetAuditor(Auditor.get());
443 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000444
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000445 // Execute the worklist algorithm.
446 Eng.ExecuteWorkList();
Ted Kremenekbc46f342008-07-02 16:35:50 +0000447
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000448 // Release the auditor (if any) so that it doesn't monitor the graph
449 // created BugReporter.
450 ExplodedNodeImpl::SetAuditor(0);
451
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000452 // Display warnings.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000453 Eng.getBugReporter().FlushReports();
Ted Kremenek34d77342008-07-02 16:49:11 +0000454
455 // Visualize the exploded graph.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000456 if (mgr.shouldVisualizeGraphviz())
Ted Kremenek34d77342008-07-02 16:49:11 +0000457 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000458}
459
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000460static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
Ted Kremenek78d46242008-07-22 16:21:24 +0000461 bool StandardWarnings) {
462
Ted Kremenekbc46f342008-07-02 16:35:50 +0000463 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
464 GCEnabled,
Ted Kremenekbc46f342008-07-02 16:35:50 +0000465 mgr.getLangOptions());
466
Ted Kremenek78d46242008-07-22 16:21:24 +0000467 ActionGRExprEngine(mgr, TF, StandardWarnings);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000468}
469
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000470static void ActionCheckerCFRef(AnalysisManager& mgr) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000471
472 switch (mgr.getLangOptions().getGCMode()) {
473 default:
474 assert (false && "Invalid GC mode.");
475 case LangOptions::NonGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000476 ActionCheckerCFRefAux(mgr, false, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000477 break;
478
479 case LangOptions::GCOnly:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000480 ActionCheckerCFRefAux(mgr, true, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000481 break;
482
483 case LangOptions::HybridGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000484 ActionCheckerCFRefAux(mgr, false, true);
485 ActionCheckerCFRefAux(mgr, true, false);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000486 break;
487 }
488}
489
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000490static void ActionCheckerSimple(AnalysisManager& mgr) {
Ted Kremenekbc46f342008-07-02 16:35:50 +0000491 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
492}
493
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000494static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000495 if (LiveVariables* L = mgr.getLiveVariables()) {
496 mgr.DisplayFunction();
497 L->dumpBlockLiveness(mgr.getSourceManager());
498 }
Ted Kremenek235e0312008-07-02 18:11:29 +0000499}
500
Ted Kremenek902141f2008-07-02 18:23:21 +0000501static void ActionCFGDump(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000502 if (CFG* c = mgr.getCFG()) {
503 mgr.DisplayFunction();
504 c->dump();
505 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000506}
507
508static void ActionCFGView(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000509 if (CFG* c = mgr.getCFG()) {
510 mgr.DisplayFunction();
511 c->viewCFG();
512 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000513}
514
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000515static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
Ted Kremenek4f4e7e42008-08-04 17:14:10 +0000516 if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
517 return;
518
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000519 BugReporter BR(mgr);
Ted Kremenek3cd483c2008-07-03 14:35:01 +0000520
521 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
522 mgr.getLangOptions(), BR);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000523}
524
Ted Kremenek395aaf22008-07-23 00:45:26 +0000525static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
526 BugReporter BR(mgr);
527 CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
528}
529
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000530static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
Ted Kremenek0d8019e2008-07-11 22:40:47 +0000531 BugReporter BR(mgr);
532
533 CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
534 BR);
535}
536
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000537//===----------------------------------------------------------------------===//
538// AnalysisConsumer creation.
539//===----------------------------------------------------------------------===//
540
541ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
Ted Kremenek95c7b002008-10-24 01:04:59 +0000542 AnalysisStores SM,
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000543 AnalysisDiagClients DC,
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000544 Diagnostic &diags, Preprocessor* pp,
545 PreprocessorFactory* ppf,
546 const LangOptions& lopts,
547 const std::string& fname,
548 const std::string& htmldir,
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000549 bool VisGraphviz, bool VisUbi,
550 bool trim,
Ted Kremenek491918e2009-01-23 20:52:26 +0000551 bool analyzeAll,
552 bool displayProgress) {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000553
554 llvm::OwningPtr<AnalysisConsumer>
Ted Kremenek4fc82c82008-11-03 23:18:07 +0000555 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir, SM, DC,
Ted Kremenek491918e2009-01-23 20:52:26 +0000556 VisGraphviz, VisUbi, trim, analyzeAll,
557 displayProgress));
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000558
559 for ( ; Beg != End ; ++Beg)
560 switch (*Beg) {
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000561#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000562 case NAME:\
Ted Kremenekf7f3c202008-07-15 00:46:02 +0000563 C->add ## SCOPE ## Action(&Action ## NAME);\
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000564 break;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000565#include "Analyses.def"
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000566 default: break;
567 }
568
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000569 return C.take();
570}
571
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000572//===----------------------------------------------------------------------===//
573// Ubigraph Visualization. FIXME: Move to separate file.
574//===----------------------------------------------------------------------===//
575
576namespace {
577
578class UbigraphViz : public ExplodedNodeImpl::Auditor {
579 llvm::OwningPtr<llvm::raw_ostream> Out;
Ted Kremenek710ad932008-08-28 03:54:51 +0000580 llvm::sys::Path Dir, Filename;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000581 unsigned Cntr;
582
583 typedef llvm::DenseMap<void*,unsigned> VMap;
584 VMap M;
585
586public:
Ted Kremenek710ad932008-08-28 03:54:51 +0000587 UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
Ted Kremenek56b98712008-08-28 05:02:09 +0000588 llvm::sys::Path& filename);
Ted Kremenek710ad932008-08-28 03:54:51 +0000589
590 ~UbigraphViz();
591
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000592 virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
593};
594
595} // end anonymous namespace
596
597static ExplodedNodeImpl::Auditor* CreateUbiViz() {
598 std::string ErrMsg;
599
Ted Kremenek710ad932008-08-28 03:54:51 +0000600 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000601 if (!ErrMsg.empty())
602 return 0;
603
Ted Kremenek710ad932008-08-28 03:54:51 +0000604 llvm::sys::Path Filename = Dir;
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000605 Filename.appendComponent("llvm_ubi");
606 Filename.makeUnique(true,&ErrMsg);
607
608 if (!ErrMsg.empty())
609 return 0;
610
611 llvm::cerr << "Writing '" << Filename << "'.\n";
612
613 llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
614 std::string filename = Filename.toString();
Daniel Dunbar26fb2722008-11-13 05:09:21 +0000615 Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), false, ErrMsg));
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000616
617 if (!ErrMsg.empty())
618 return 0;
619
Ted Kremenek710ad932008-08-28 03:54:51 +0000620 return new UbigraphViz(Stream.take(), Dir, Filename);
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000621}
622
623void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
Ted Kremenek45479c82008-08-28 18:34:41 +0000624
625 assert (Src != Dst && "Self-edges are not allowed.");
626
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000627 // Lookup the Src. If it is a new node, it's a root.
628 VMap::iterator SrcI= M.find(Src);
629 unsigned SrcID;
630
631 if (SrcI == M.end()) {
632 M[Src] = SrcID = Cntr++;
633 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
634 }
635 else
636 SrcID = SrcI->second;
637
638 // Lookup the Dst.
639 VMap::iterator DstI= M.find(Dst);
640 unsigned DstID;
641
642 if (DstI == M.end()) {
643 M[Dst] = DstID = Cntr++;
644 *Out << "('vertex', " << DstID << ")\n";
645 }
Ted Kremenek56b98712008-08-28 05:02:09 +0000646 else {
647 // We have hit DstID before. Change its style to reflect a cache hit.
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000648 DstID = DstI->second;
Ted Kremenek56b98712008-08-28 05:02:09 +0000649 *Out << "('change_vertex_style', " << DstID << ", 1)\n";
650 }
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000651
652 // Add the edge.
Ted Kremenekd1289322008-08-27 22:46:55 +0000653 *Out << "('edge', " << SrcID << ", " << DstID
654 << ", ('arrow','true'), ('oriented', 'true'))\n";
Ted Kremenekf8ce6992008-08-27 22:31:43 +0000655}
656
Ted Kremenek56b98712008-08-28 05:02:09 +0000657UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
658 llvm::sys::Path& filename)
659 : Out(out), Dir(dir), Filename(filename), Cntr(0) {
660
661 *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
662 *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
663 " ('size', '1.5'))\n";
664}
665
Ted Kremenek710ad932008-08-28 03:54:51 +0000666UbigraphViz::~UbigraphViz() {
667 Out.reset(0);
668 llvm::cerr << "Running 'ubiviz' program... ";
669 std::string ErrMsg;
670 llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
671 std::vector<const char*> args;
672 args.push_back(Ubiviz.c_str());
673 args.push_back(Filename.c_str());
674 args.push_back(0);
675
676 if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
677 llvm::cerr << "Error viewing graph: " << ErrMsg << "\n";
678 }
679
680 // Delete the directory.
681 Dir.eraseFromDisk(true);
Daniel Dunbar932680e2008-08-29 03:45:59 +0000682}