blob: a5c253c62d4e15d90073bbbb62fbd2c65d5787c0 [file] [log] [blame]
Ted Kremenekf0413bf2008-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 Kremeneke868c002008-11-03 22:31:48 +000015#include "clang/Driver/PathDiagnosticClients.h"
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +000016#include "clang/Driver/ManagerRegistry.h"
Ted Kremenekf0413bf2008-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 Kremenekf0413bf2008-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 Kremenek0e7d2522008-07-03 04:29:21 +000028#include "clang/AST/TranslationUnit.h"
Ted Kremenekb1d01182008-07-02 21:24:01 +000029#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenekf0413bf2008-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 Xu5b0ae812008-12-22 01:52:37 +000034#include "llvm/Support/CommandLine.h"
Ted Kremenek71ac8322008-07-02 16:49:11 +000035#include "llvm/Support/Streams.h"
Ted Kremenekd461d7a2008-08-27 22:31:43 +000036#include "llvm/Support/raw_ostream.h"
37#include "llvm/System/Path.h"
Ted Kremenek266ec3f2008-08-28 03:54:51 +000038#include "llvm/System/Program.h"
Ted Kremenek0e7d2522008-07-03 04:29:21 +000039#include <vector>
40
Ted Kremenekf0413bf2008-07-02 00:03:09 +000041using namespace clang;
42
Ted Kremenekd461d7a2008-08-27 22:31:43 +000043static ExplodedNodeImpl::Auditor* CreateUbiViz();
Zhongxing Xu5b0ae812008-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 Kremenekf0413bf2008-07-02 00:03:09 +000051
52//===----------------------------------------------------------------------===//
53// Basic type definitions.
54//===----------------------------------------------------------------------===//
55
Ted Kremenek3063b732008-07-14 23:41:13 +000056namespace {
Ted Kremenekf0413bf2008-07-02 00:03:09 +000057 class AnalysisManager;
Ted Kremenek3063b732008-07-14 23:41:13 +000058 typedef void (*CodeAction)(AnalysisManager& Mgr);
Ted Kremenekf0413bf2008-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 Kremenek0e7d2522008-07-03 04:29:21 +000068 typedef std::vector<CodeAction> Actions;
Ted Kremenekf0413bf2008-07-02 00:03:09 +000069 Actions FunctionActions;
70 Actions ObjCMethodActions;
Ted Kremenek0e7d2522008-07-03 04:29:21 +000071 Actions ObjCImplementationActions;
Ted Kremenek3391cb02008-11-07 02:09:25 +000072 Actions TranslationUnitActions;
Ted Kremenekf0413bf2008-07-02 00:03:09 +000073
74 public:
Ted Kremenekd461d7a2008-08-27 22:31:43 +000075 const bool VisGraphviz;
76 const bool VisUbigraph;
Ted Kremenekf0413bf2008-07-02 00:03:09 +000077 const bool TrimGraph;
Ted Kremenek6779f892008-10-24 01:04:59 +000078 const LangOptions& LOpts;
Ted Kremenekf0413bf2008-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 Kremenek6779f892008-10-24 01:04:59 +000087 AnalysisStores SM;
Ted Kremenek14f18652008-11-03 23:18:07 +000088 AnalysisDiagClients DC;
Ted Kremenekec283912009-01-23 20:52:26 +000089 const bool DisplayProgress;
Ted Kremenekf0413bf2008-07-02 00:03:09 +000090
91 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
92 PreprocessorFactory* ppf,
93 const LangOptions& lopts,
94 const std::string& fname,
95 const std::string& htmldir,
Ted Kremenek14f18652008-11-03 23:18:07 +000096 AnalysisStores sm, AnalysisDiagClients dc,
Ted Kremenekec283912009-01-23 20:52:26 +000097 bool visgraphviz, bool visubi, bool trim, bool analyzeAll,
98 bool displayProgress)
Ted Kremenekd461d7a2008-08-27 22:31:43 +000099 : VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
100 LOpts(lopts), Diags(diags),
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000101 Ctx(0), PP(pp), PPF(ppf),
102 HTMLDir(htmldir),
103 FName(fname),
Ted Kremenekec283912009-01-23 20:52:26 +0000104 AnalyzeAll(analyzeAll), SM(sm), DC(dc),
105 DisplayProgress(displayProgress) {}
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000106
107 void addCodeAction(CodeAction action) {
Ted Kremenek0e7d2522008-07-03 04:29:21 +0000108 FunctionActions.push_back(action);
109 ObjCMethodActions.push_back(action);
110 }
111
112 void addObjCImplementationAction(CodeAction action) {
113 ObjCImplementationActions.push_back(action);
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000114 }
115
Ted Kremenek3391cb02008-11-07 02:09:25 +0000116 void addTranslationUnitAction(CodeAction action) {
117 TranslationUnitActions.push_back(action);
118 }
119
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000120 virtual void Initialize(ASTContext &Context) {
121 Ctx = &Context;
122 }
123
124 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenek0e7d2522008-07-03 04:29:21 +0000125 virtual void HandleTranslationUnit(TranslationUnit &TU);
126
Ted Kremenekbb70c082009-02-02 20:52:40 +0000127 void HandleCode(Decl* D, Stmt* Body, Actions& actions);
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000128 };
129
130
Ted Kremenekb1d01182008-07-02 21:24:01 +0000131 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekb4ebbc5a2008-11-05 19:05:06 +0000132 Decl* D; Stmt* Body;
133 TranslationUnit* TU;
134
135 enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
136
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000137 AnalysisConsumer& C;
Ted Kremenek71ac8322008-07-02 16:49:11 +0000138 bool DisplayedFunction;
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000139
140 llvm::OwningPtr<CFG> cfg;
141 llvm::OwningPtr<LiveVariables> liveness;
142 llvm::OwningPtr<ParentMap> PM;
143
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +0000144 // Configurable components creators.
145 StoreManagerCreator CreateStoreMgr;
146 ConstraintManagerCreator CreateConstraintMgr;
147
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000148 public:
Ted Kremenekec283912009-01-23 20:52:26 +0000149 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b, bool displayProgress)
150 : D(d), Body(b), TU(0), AScope(ScopeDecl), C(c),
151 DisplayedFunction(!displayProgress) {
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +0000152 setManagerCreators();
153 }
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000154
Ted Kremenekec283912009-01-23 20:52:26 +0000155 AnalysisManager(AnalysisConsumer& c, TranslationUnit* tu,
156 bool displayProgress)
157 : D(0), Body(0), TU(tu), AScope(ScopeTU), C(c),
158 DisplayedFunction(!displayProgress) {
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +0000159 setManagerCreators();
160 }
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000161
Ted Kremenekb4ebbc5a2008-11-05 19:05:06 +0000162 Decl* getCodeDecl() const {
163 assert (AScope == ScopeDecl);
164 return D;
165 }
166
167 Stmt* getBody() const {
168 assert (AScope == ScopeDecl);
169 return Body;
170 }
171
172 TranslationUnit* getTranslationUnit() const {
173 assert (AScope == ScopeTU);
174 return TU;
175 }
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000176
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +0000177 StoreManagerCreator getStoreManagerCreator() {
178 return CreateStoreMgr;
Ted Kremenek6779f892008-10-24 01:04:59 +0000179 };
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +0000180
181 ConstraintManagerCreator getConstraintManagerCreator() {
182 return CreateConstraintMgr;
183 }
Ted Kremenek6779f892008-10-24 01:04:59 +0000184
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000185 virtual CFG* getCFG() {
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000186 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000187 return cfg.get();
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000188 }
189
Ted Kremenekb1d01182008-07-02 21:24:01 +0000190 virtual ParentMap& getParentMap() {
Ted Kremenekc7efb532008-07-02 23:16:33 +0000191 if (!PM)
192 PM.reset(new ParentMap(getBody()));
Ted Kremenekb1d01182008-07-02 21:24:01 +0000193 return *PM.get();
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000194 }
195
Ted Kremenekb1d01182008-07-02 21:24:01 +0000196 virtual ASTContext& getContext() {
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000197 return *C.Ctx;
198 }
199
Ted Kremenekb1d01182008-07-02 21:24:01 +0000200 virtual SourceManager& getSourceManager() {
Ted Kremenekbdbe6132008-07-02 18:11:29 +0000201 return getContext().getSourceManager();
202 }
203
Ted Kremenekb1d01182008-07-02 21:24:01 +0000204 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000205 return C.Diags;
206 }
Ted Kremenek8e631a02008-07-02 00:44:58 +0000207
208 const LangOptions& getLangOptions() const {
209 return C.LOpts;
210 }
211
Ted Kremenekb1d01182008-07-02 21:24:01 +0000212 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremenek14f18652008-11-03 23:18:07 +0000213 if (C.PD.get() == 0 && !C.HTMLDir.empty()) {
214 switch (C.DC) {
215 default:
Ted Kremenek099243a2009-01-23 20:06:20 +0000216#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\
Ted Kremenek14f18652008-11-03 23:18:07 +0000217case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break;
218#include "Analyses.def"
219 }
220 }
Ted Kremenekc7efb532008-07-02 23:16:33 +0000221 return C.PD.get();
Ted Kremenek8e631a02008-07-02 00:44:58 +0000222 }
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000223
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000224 virtual LiveVariables* getLiveVariables() {
Ted Kremenekbdbe6132008-07-02 18:11:29 +0000225 if (!liveness) {
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000226 CFG* c = getCFG();
227 if (!c) return 0;
228
Ted Kremenek08134c92008-12-09 00:17:51 +0000229 liveness.reset(new LiveVariables(getContext(), *c));
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000230 liveness->runOnCFG(*c);
231 liveness->runOnAllBlocks(*c, 0, true);
Ted Kremenekbdbe6132008-07-02 18:11:29 +0000232 }
Ted Kremenekb1d01182008-07-02 21:24:01 +0000233
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000234 return liveness.get();
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000235 }
Ted Kremenek71ac8322008-07-02 16:49:11 +0000236
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000237 bool shouldVisualizeGraphviz() const {
238 return C.VisGraphviz;
239 }
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +0000240
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000241 bool shouldVisualizeUbigraph() const {
242 return C.VisUbigraph;
243 }
244
Ted Kremenek71ac8322008-07-02 16:49:11 +0000245 bool shouldVisualize() const {
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000246 return C.VisGraphviz || C.VisUbigraph;
Ted Kremenek71ac8322008-07-02 16:49:11 +0000247 }
248
249 bool shouldTrimGraph() const {
250 return C.TrimGraph;
251 }
252
253 void DisplayFunction() {
254
255 if (DisplayedFunction)
256 return;
257
258 DisplayedFunction = true;
259
Chris Lattnerf1ca7d32009-01-27 07:57:44 +0000260 // FIXME: Is getCodeDecl() always a named decl?
261 if (isa<FunctionDecl>(getCodeDecl()) ||
262 isa<ObjCMethodDecl>(getCodeDecl())) {
263 NamedDecl *ND = cast<NamedDecl>(getCodeDecl());
264 SourceManager &SM = getContext().getSourceManager();
Ted Kremenekb6df2732008-11-20 16:14:48 +0000265 llvm::cerr << "ANALYZE: "
Chris Lattnerf1ca7d32009-01-27 07:57:44 +0000266 << SM.getPresumedLoc(ND->getLocation()).getFilename()
267 << ' ' << ND->getNameAsString() << '\n';
Ted Kremenek71ac8322008-07-02 16:49:11 +0000268 }
269 }
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +0000270
271 private:
272 /// Set configurable analyzer components creators. First check if there are
273 /// components registered at runtime. Otherwise fall back to builtin
274 /// components.
275 void setManagerCreators() {
276 if (ManagerRegistry::StoreMgrCreator != 0) {
277 CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
278 }
279 else {
280 switch (C.SM) {
281 default:
282 assert(0 && "Unknown store manager.");
283#define ANALYSIS_STORE(NAME, CMDFLAG, DESC) \
284 case NAME##Model: CreateStoreMgr = Create##NAME##Manager; break;
285#include "Analyses.def"
286 }
287 }
288
289 if (ManagerRegistry::ConstraintMgrCreator != 0)
290 CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
291 else
292 CreateConstraintMgr = CreateBasicConstraintManager;
Ted Kremenek099243a2009-01-23 20:06:20 +0000293
294 // Some DiagnosticClients should be created all the time instead of
295 // lazily. Create those now.
296 switch (C.DC) {
297 default: break;
298#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\
299case PD_##NAME: if (AUTOCREATE) getPathDiagnosticClient(); break;
300#include "Analyses.def"
301 }
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +0000302 }
303
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000304 };
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +0000305
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000306} // end anonymous namespace
307
308namespace llvm {
309 template <> struct FoldingSetTrait<CodeAction> {
310 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
311 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
312 }
313 };
314}
315
316//===----------------------------------------------------------------------===//
317// AnalysisConsumer implementation.
318//===----------------------------------------------------------------------===//
319
320void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
321 switch (D->getKind()) {
322 case Decl::Function: {
323 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenekbdbe6132008-07-02 18:11:29 +0000324
325 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
326 break;
327
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000328 Stmt* Body = FD->getBody();
329 if (Body) HandleCode(FD, Body, FunctionActions);
330 break;
331 }
332
333 case Decl::ObjCMethod: {
334 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenekbdbe6132008-07-02 18:11:29 +0000335
Chris Lattnere4b95692008-11-24 03:33:13 +0000336 if (FName.size() > 0 && FName != MD->getSelector().getAsString())
Ted Kremenekbdbe6132008-07-02 18:11:29 +0000337 return;
338
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000339 Stmt* Body = MD->getBody();
340 if (Body) HandleCode(MD, Body, ObjCMethodActions);
341 break;
342 }
343
344 default:
345 break;
346 }
347}
348
Ted Kremenek0e7d2522008-07-03 04:29:21 +0000349void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
350
Ted Kremenek3391cb02008-11-07 02:09:25 +0000351 if(!TranslationUnitActions.empty()) {
Ted Kremenekec283912009-01-23 20:52:26 +0000352 AnalysisManager mgr(*this, &TU, DisplayProgress);
Ted Kremenek3391cb02008-11-07 02:09:25 +0000353 for (Actions::iterator I = TranslationUnitActions.begin(),
354 E = TranslationUnitActions.end(); I != E; ++I)
355 (*I)(mgr);
356 }
357
Ted Kremenekc14725d2009-02-13 00:51:30 +0000358 if (!ObjCImplementationActions.empty())
359 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I)
360 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
361 HandleCode(ID, 0, ObjCImplementationActions);
362
363 // Delete the PathDiagnosticClient here just in case the AnalysisConsumer
364 // object doesn't get released. This will cause any side-effects in the
365 // destructor of the PathDiagnosticClient to get executed.
366 PD.reset();
Ted Kremenek0e7d2522008-07-03 04:29:21 +0000367}
368
Ted Kremenekbb70c082009-02-02 20:52:40 +0000369void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions& actions) {
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000370
371 // Don't run the actions if an error has occured with parsing the file.
372 if (Diags.hasErrorOccurred())
373 return;
Ted Kremenekbb70c082009-02-02 20:52:40 +0000374
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000375 // Don't run the actions on declarations in header files unless
376 // otherwise specified.
Ted Kremenekbb70c082009-02-02 20:52:40 +0000377 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(D->getLocation()))
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000378 return;
379
380 // Create an AnalysisManager that will manage the state for analyzing
381 // this method/function.
Ted Kremenekec283912009-01-23 20:52:26 +0000382 AnalysisManager mgr(*this, D, Body, DisplayProgress);
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000383
384 // Dispatch on the actions.
Zhongxing Xu96553942008-10-30 05:03:28 +0000385 for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
Ted Kremenek0e7d2522008-07-03 04:29:21 +0000386 (*I)(mgr);
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000387}
388
389//===----------------------------------------------------------------------===//
390// Analyses
391//===----------------------------------------------------------------------===//
392
Ted Kremenek3063b732008-07-14 23:41:13 +0000393static void ActionWarnDeadStores(AnalysisManager& mgr) {
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000394 if (LiveVariables* L = mgr.getLiveVariables()) {
395 BugReporter BR(mgr);
396 CheckDeadStores(*L, BR);
397 }
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000398}
399
Ted Kremenek3063b732008-07-14 23:41:13 +0000400static void ActionWarnUninitVals(AnalysisManager& mgr) {
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000401 if (CFG* c = mgr.getCFG())
402 CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000403}
404
Ted Kremenek8e631a02008-07-02 00:44:58 +0000405
Ted Kremenek1f352db2008-07-22 16:21:24 +0000406static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
407 bool StandardWarnings = true) {
Ted Kremenek8e631a02008-07-02 00:44:58 +0000408
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000409
Ted Kremenekbecec2c2008-07-02 16:35:50 +0000410 llvm::OwningPtr<GRTransferFuncs> TF(tf);
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000411
Ted Kremenek3ca000a2008-11-24 20:53:32 +0000412 // Display progress.
413 mgr.DisplayFunction();
414
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000415 // Construct the analysis engine.
416 LiveVariables* L = mgr.getLiveVariables();
417 if (!L) return;
Ted Kremenek3ca000a2008-11-24 20:53:32 +0000418
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000419 GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L, mgr,
Zhongxing Xu5b0ae812008-12-22 01:52:37 +0000420 PurgeDead,
Zhongxing Xu16e3f0e2008-11-27 01:55:08 +0000421 mgr.getStoreManagerCreator(),
422 mgr.getConstraintManagerCreator());
Ted Kremenek6779f892008-10-24 01:04:59 +0000423
Ted Kremenekbecec2c2008-07-02 16:35:50 +0000424 Eng.setTransferFunctions(tf);
425
Ted Kremenek1f352db2008-07-22 16:21:24 +0000426 if (StandardWarnings) {
427 Eng.RegisterInternalChecks();
428 RegisterAppleChecks(Eng);
429 }
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000430
431 // Set the graph auditor.
432 llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor;
433 if (mgr.shouldVisualizeUbigraph()) {
434 Auditor.reset(CreateUbiViz());
435 ExplodedNodeImpl::SetAuditor(Auditor.get());
436 }
Ted Kremenek1f352db2008-07-22 16:21:24 +0000437
Ted Kremenek8e631a02008-07-02 00:44:58 +0000438 // Execute the worklist algorithm.
439 Eng.ExecuteWorkList();
Ted Kremenekbecec2c2008-07-02 16:35:50 +0000440
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000441 // Release the auditor (if any) so that it doesn't monitor the graph
442 // created BugReporter.
443 ExplodedNodeImpl::SetAuditor(0);
444
Ted Kremenek8e631a02008-07-02 00:44:58 +0000445 // Display warnings.
Ted Kremenekfc5d0672009-02-04 23:49:09 +0000446 Eng.getBugReporter().FlushReports();
Ted Kremenek71ac8322008-07-02 16:49:11 +0000447
448 // Visualize the exploded graph.
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000449 if (mgr.shouldVisualizeGraphviz())
Ted Kremenek71ac8322008-07-02 16:49:11 +0000450 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbecec2c2008-07-02 16:35:50 +0000451}
452
Ted Kremenek3063b732008-07-14 23:41:13 +0000453static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
Ted Kremenek1f352db2008-07-22 16:21:24 +0000454 bool StandardWarnings) {
455
Ted Kremenekbecec2c2008-07-02 16:35:50 +0000456 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
457 GCEnabled,
Ted Kremenekbecec2c2008-07-02 16:35:50 +0000458 mgr.getLangOptions());
459
Ted Kremenek1f352db2008-07-22 16:21:24 +0000460 ActionGRExprEngine(mgr, TF, StandardWarnings);
Ted Kremenek8e631a02008-07-02 00:44:58 +0000461}
462
Ted Kremenek3063b732008-07-14 23:41:13 +0000463static void ActionCheckerCFRef(AnalysisManager& mgr) {
Ted Kremenek8e631a02008-07-02 00:44:58 +0000464
465 switch (mgr.getLangOptions().getGCMode()) {
466 default:
467 assert (false && "Invalid GC mode.");
468 case LangOptions::NonGC:
Ted Kremenek3063b732008-07-14 23:41:13 +0000469 ActionCheckerCFRefAux(mgr, false, true);
Ted Kremenek8e631a02008-07-02 00:44:58 +0000470 break;
471
472 case LangOptions::GCOnly:
Ted Kremenek3063b732008-07-14 23:41:13 +0000473 ActionCheckerCFRefAux(mgr, true, true);
Ted Kremenek8e631a02008-07-02 00:44:58 +0000474 break;
475
476 case LangOptions::HybridGC:
Ted Kremenek3063b732008-07-14 23:41:13 +0000477 ActionCheckerCFRefAux(mgr, false, true);
478 ActionCheckerCFRefAux(mgr, true, false);
Ted Kremenek8e631a02008-07-02 00:44:58 +0000479 break;
480 }
481}
482
Ted Kremenek3063b732008-07-14 23:41:13 +0000483static void ActionCheckerSimple(AnalysisManager& mgr) {
Ted Kremenekbecec2c2008-07-02 16:35:50 +0000484 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
485}
486
Ted Kremenek3063b732008-07-14 23:41:13 +0000487static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000488 if (LiveVariables* L = mgr.getLiveVariables()) {
489 mgr.DisplayFunction();
490 L->dumpBlockLiveness(mgr.getSourceManager());
491 }
Ted Kremenekbdbe6132008-07-02 18:11:29 +0000492}
493
Ted Kremenekf992cfb2008-07-02 18:23:21 +0000494static void ActionCFGDump(AnalysisManager& mgr) {
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000495 if (CFG* c = mgr.getCFG()) {
496 mgr.DisplayFunction();
497 c->dump();
498 }
Ted Kremenekf992cfb2008-07-02 18:23:21 +0000499}
500
501static void ActionCFGView(AnalysisManager& mgr) {
Ted Kremenek1d3c7972008-07-03 05:26:14 +0000502 if (CFG* c = mgr.getCFG()) {
503 mgr.DisplayFunction();
504 c->viewCFG();
505 }
Ted Kremenekf992cfb2008-07-02 18:23:21 +0000506}
507
Ted Kremenek3063b732008-07-14 23:41:13 +0000508static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
Ted Kremenek98980282008-08-04 17:14:10 +0000509 if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
510 return;
511
Ted Kremenek0e7d2522008-07-03 04:29:21 +0000512 BugReporter BR(mgr);
Ted Kremeneke66ca6f2008-07-03 14:35:01 +0000513
514 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
515 mgr.getLangOptions(), BR);
Ted Kremenek0e7d2522008-07-03 04:29:21 +0000516}
517
Ted Kremenek3b28f492008-07-23 00:45:26 +0000518static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
519 BugReporter BR(mgr);
520 CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
521}
522
Ted Kremenek3063b732008-07-14 23:41:13 +0000523static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
Ted Kremenek3bfb3142008-07-11 22:40:47 +0000524 BugReporter BR(mgr);
525
526 CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
527 BR);
528}
529
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000530//===----------------------------------------------------------------------===//
531// AnalysisConsumer creation.
532//===----------------------------------------------------------------------===//
533
534ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
Ted Kremenek6779f892008-10-24 01:04:59 +0000535 AnalysisStores SM,
Ted Kremenek14f18652008-11-03 23:18:07 +0000536 AnalysisDiagClients DC,
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000537 Diagnostic &diags, Preprocessor* pp,
538 PreprocessorFactory* ppf,
539 const LangOptions& lopts,
540 const std::string& fname,
541 const std::string& htmldir,
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000542 bool VisGraphviz, bool VisUbi,
543 bool trim,
Ted Kremenekec283912009-01-23 20:52:26 +0000544 bool analyzeAll,
545 bool displayProgress) {
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000546
547 llvm::OwningPtr<AnalysisConsumer>
Ted Kremenek14f18652008-11-03 23:18:07 +0000548 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir, SM, DC,
Ted Kremenekec283912009-01-23 20:52:26 +0000549 VisGraphviz, VisUbi, trim, analyzeAll,
550 displayProgress));
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000551
552 for ( ; Beg != End ; ++Beg)
553 switch (*Beg) {
Ted Kremenekfd7efdf2008-07-15 00:46:02 +0000554#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
Ted Kremenek3063b732008-07-14 23:41:13 +0000555 case NAME:\
Ted Kremenekfd7efdf2008-07-15 00:46:02 +0000556 C->add ## SCOPE ## Action(&Action ## NAME);\
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000557 break;
Ted Kremenek3063b732008-07-14 23:41:13 +0000558#include "Analyses.def"
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000559 default: break;
560 }
561
Ted Kremenekf0413bf2008-07-02 00:03:09 +0000562 return C.take();
563}
564
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000565//===----------------------------------------------------------------------===//
566// Ubigraph Visualization. FIXME: Move to separate file.
567//===----------------------------------------------------------------------===//
568
569namespace {
570
571class UbigraphViz : public ExplodedNodeImpl::Auditor {
572 llvm::OwningPtr<llvm::raw_ostream> Out;
Ted Kremenek266ec3f2008-08-28 03:54:51 +0000573 llvm::sys::Path Dir, Filename;
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000574 unsigned Cntr;
575
576 typedef llvm::DenseMap<void*,unsigned> VMap;
577 VMap M;
578
579public:
Ted Kremenek266ec3f2008-08-28 03:54:51 +0000580 UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
Ted Kremenek803e7e12008-08-28 05:02:09 +0000581 llvm::sys::Path& filename);
Ted Kremenek266ec3f2008-08-28 03:54:51 +0000582
583 ~UbigraphViz();
584
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000585 virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
586};
587
588} // end anonymous namespace
589
590static ExplodedNodeImpl::Auditor* CreateUbiViz() {
591 std::string ErrMsg;
592
Ted Kremenek266ec3f2008-08-28 03:54:51 +0000593 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000594 if (!ErrMsg.empty())
595 return 0;
596
Ted Kremenek266ec3f2008-08-28 03:54:51 +0000597 llvm::sys::Path Filename = Dir;
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000598 Filename.appendComponent("llvm_ubi");
599 Filename.makeUnique(true,&ErrMsg);
600
601 if (!ErrMsg.empty())
602 return 0;
603
604 llvm::cerr << "Writing '" << Filename << "'.\n";
605
606 llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
607 std::string filename = Filename.toString();
Daniel Dunbarf3502db2008-11-13 05:09:21 +0000608 Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), false, ErrMsg));
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000609
610 if (!ErrMsg.empty())
611 return 0;
612
Ted Kremenek266ec3f2008-08-28 03:54:51 +0000613 return new UbigraphViz(Stream.take(), Dir, Filename);
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000614}
615
616void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
Ted Kremenek2eb49f22008-08-28 18:34:41 +0000617
618 assert (Src != Dst && "Self-edges are not allowed.");
619
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000620 // Lookup the Src. If it is a new node, it's a root.
621 VMap::iterator SrcI= M.find(Src);
622 unsigned SrcID;
623
624 if (SrcI == M.end()) {
625 M[Src] = SrcID = Cntr++;
626 *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
627 }
628 else
629 SrcID = SrcI->second;
630
631 // Lookup the Dst.
632 VMap::iterator DstI= M.find(Dst);
633 unsigned DstID;
634
635 if (DstI == M.end()) {
636 M[Dst] = DstID = Cntr++;
637 *Out << "('vertex', " << DstID << ")\n";
638 }
Ted Kremenek803e7e12008-08-28 05:02:09 +0000639 else {
640 // We have hit DstID before. Change its style to reflect a cache hit.
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000641 DstID = DstI->second;
Ted Kremenek803e7e12008-08-28 05:02:09 +0000642 *Out << "('change_vertex_style', " << DstID << ", 1)\n";
643 }
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000644
645 // Add the edge.
Ted Kremenekc8288b42008-08-27 22:46:55 +0000646 *Out << "('edge', " << SrcID << ", " << DstID
647 << ", ('arrow','true'), ('oriented', 'true'))\n";
Ted Kremenekd461d7a2008-08-27 22:31:43 +0000648}
649
Ted Kremenek803e7e12008-08-28 05:02:09 +0000650UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
651 llvm::sys::Path& filename)
652 : Out(out), Dir(dir), Filename(filename), Cntr(0) {
653
654 *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
655 *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
656 " ('size', '1.5'))\n";
657}
658
Ted Kremenek266ec3f2008-08-28 03:54:51 +0000659UbigraphViz::~UbigraphViz() {
660 Out.reset(0);
661 llvm::cerr << "Running 'ubiviz' program... ";
662 std::string ErrMsg;
663 llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
664 std::vector<const char*> args;
665 args.push_back(Ubiviz.c_str());
666 args.push_back(Filename.c_str());
667 args.push_back(0);
668
669 if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
670 llvm::cerr << "Error viewing graph: " << ErrMsg << "\n";
671 }
672
673 // Delete the directory.
674 Dir.eraseFromDisk(true);
Daniel Dunbar9a0ea042008-08-29 03:45:59 +0000675}