blob: cd24e2efea4c9e27f1b68ed608cc1fdea5fea497 [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 Kremenekb35a74a2008-07-02 00:44:58 +000015#include "HTMLDiagnostics.h"
Ted Kremenekf4381fd2008-07-02 00:03:09 +000016#include "clang/AST/ASTConsumer.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/DeclObjC.h"
19#include "llvm/Support/Compiler.h"
Ted Kremenekf4381fd2008-07-02 00:03:09 +000020#include "llvm/ADT/OwningPtr.h"
21#include "clang/AST/CFG.h"
22#include "clang/Analysis/Analyses/LiveVariables.h"
23#include "clang/Analysis/PathDiagnostic.h"
24#include "clang/Basic/SourceManager.h"
25#include "clang/Basic/FileManager.h"
26#include "clang/AST/ParentMap.h"
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000027#include "clang/AST/TranslationUnit.h"
Ted Kremenekc0959972008-07-02 21:24:01 +000028#include "clang/Analysis/PathSensitive/BugReporter.h"
Ted Kremenekf4381fd2008-07-02 00:03:09 +000029#include "clang/Analysis/Analyses/LiveVariables.h"
30#include "clang/Analysis/LocalCheckers.h"
31#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
32#include "clang/Analysis/PathSensitive/GRExprEngine.h"
Ted Kremenek34d77342008-07-02 16:49:11 +000033#include "llvm/Support/Streams.h"
Ted Kremenekf4381fd2008-07-02 00:03:09 +000034
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000035#include <vector>
36
Ted Kremenekf4381fd2008-07-02 00:03:09 +000037using namespace clang;
38
39
40//===----------------------------------------------------------------------===//
41// Basic type definitions.
42//===----------------------------------------------------------------------===//
43
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000044namespace {
Ted Kremenekf4381fd2008-07-02 00:03:09 +000045 class AnalysisManager;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +000046 typedef void (*CodeAction)(AnalysisManager& Mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +000047} // end anonymous namespace
48
49//===----------------------------------------------------------------------===//
50// AnalysisConsumer declaration.
51//===----------------------------------------------------------------------===//
52
53namespace {
54
55 class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000056 typedef std::vector<CodeAction> Actions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000057 Actions FunctionActions;
58 Actions ObjCMethodActions;
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000059 Actions ObjCImplementationActions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000060
61 public:
62 const bool Visualize;
63 const bool TrimGraph;
64 const LangOptions& LOpts;
65 Diagnostic &Diags;
66 ASTContext* Ctx;
67 Preprocessor* PP;
68 PreprocessorFactory* PPF;
69 const std::string HTMLDir;
70 const std::string FName;
71 llvm::OwningPtr<PathDiagnosticClient> PD;
72 bool AnalyzeAll;
73
74 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
75 PreprocessorFactory* ppf,
76 const LangOptions& lopts,
77 const std::string& fname,
78 const std::string& htmldir,
79 bool visualize, bool trim, bool analyzeAll)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000080 : Visualize(visualize), TrimGraph(trim), LOpts(lopts), Diags(diags),
Ted Kremenekf4381fd2008-07-02 00:03:09 +000081 Ctx(0), PP(pp), PPF(ppf),
82 HTMLDir(htmldir),
83 FName(fname),
84 AnalyzeAll(analyzeAll) {}
85
86 void addCodeAction(CodeAction action) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000087 FunctionActions.push_back(action);
88 ObjCMethodActions.push_back(action);
89 }
90
91 void addObjCImplementationAction(CodeAction action) {
92 ObjCImplementationActions.push_back(action);
Ted Kremenekf4381fd2008-07-02 00:03:09 +000093 }
94
95 virtual void Initialize(ASTContext &Context) {
96 Ctx = &Context;
97 }
98
99 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000100 virtual void HandleTranslationUnit(TranslationUnit &TU);
101
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000102 void HandleCode(Decl* D, Stmt* Body, Actions actions);
103 };
104
105
Ted Kremenekc0959972008-07-02 21:24:01 +0000106 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000107 Decl* D;
108 Stmt* Body;
109 AnalysisConsumer& C;
Ted Kremenek34d77342008-07-02 16:49:11 +0000110 bool DisplayedFunction;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000111
112 llvm::OwningPtr<CFG> cfg;
113 llvm::OwningPtr<LiveVariables> liveness;
114 llvm::OwningPtr<ParentMap> PM;
115
116 public:
117 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
Ted Kremenek34d77342008-07-02 16:49:11 +0000118 : D(d), Body(b), C(c), DisplayedFunction(false) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000119
120
121 Decl* getCodeDecl() const { return D; }
122 Stmt* getBody() const { return Body; }
123
Ted Kremenek7032f462008-07-03 05:26:14 +0000124 virtual CFG* getCFG() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000125 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenek7032f462008-07-03 05:26:14 +0000126 return cfg.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000127 }
128
Ted Kremenekc0959972008-07-02 21:24:01 +0000129 virtual ParentMap& getParentMap() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000130 if (!PM)
131 PM.reset(new ParentMap(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000132 return *PM.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000133 }
134
Ted Kremenekc0959972008-07-02 21:24:01 +0000135 virtual ASTContext& getContext() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000136 return *C.Ctx;
137 }
138
Ted Kremenekc0959972008-07-02 21:24:01 +0000139 virtual SourceManager& getSourceManager() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000140 return getContext().getSourceManager();
141 }
142
Ted Kremenekc0959972008-07-02 21:24:01 +0000143 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000144 return C.Diags;
145 }
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000146
147 const LangOptions& getLangOptions() const {
148 return C.LOpts;
149 }
150
Ted Kremenekc0959972008-07-02 21:24:01 +0000151 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000152 if (C.PD.get() == 0 && !C.HTMLDir.empty())
153 C.PD.reset(CreateHTMLDiagnosticClient(C.HTMLDir, C.PP, C.PPF));
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000154
Ted Kremeneke2075582008-07-02 23:16:33 +0000155 return C.PD.get();
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000156 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000157
Ted Kremenek7032f462008-07-03 05:26:14 +0000158 virtual LiveVariables* getLiveVariables() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000159 if (!liveness) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000160 CFG* c = getCFG();
161 if (!c) return 0;
162
163 liveness.reset(new LiveVariables(*c));
164 liveness->runOnCFG(*c);
165 liveness->runOnAllBlocks(*c, 0, true);
Ted Kremenek235e0312008-07-02 18:11:29 +0000166 }
Ted Kremenekc0959972008-07-02 21:24:01 +0000167
Ted Kremenek7032f462008-07-03 05:26:14 +0000168 return liveness.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000169 }
Ted Kremenek34d77342008-07-02 16:49:11 +0000170
171 bool shouldVisualize() const {
172 return C.Visualize;
173 }
174
175 bool shouldTrimGraph() const {
176 return C.TrimGraph;
177 }
178
179 void DisplayFunction() {
180
181 if (DisplayedFunction)
182 return;
183
184 DisplayedFunction = true;
185
186 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(getCodeDecl())) {
187 llvm::cerr << "ANALYZE: "
188 << getContext().getSourceManager().getSourceName(FD->getLocation())
189 << ' '
190 << FD->getIdentifier()->getName()
191 << '\n';
192 }
193 else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCodeDecl())) {
194 llvm::cerr << "ANALYZE (ObjC Method): "
195 << getContext().getSourceManager().getSourceName(MD->getLocation())
196 << " '"
197 << MD->getSelector().getName() << "'\n";
198 }
199 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000200 };
201
202} // end anonymous namespace
203
204namespace llvm {
205 template <> struct FoldingSetTrait<CodeAction> {
206 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
207 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
208 }
209 };
210}
211
212//===----------------------------------------------------------------------===//
213// AnalysisConsumer implementation.
214//===----------------------------------------------------------------------===//
215
216void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
217 switch (D->getKind()) {
218 case Decl::Function: {
219 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000220
221 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
222 break;
223
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000224 Stmt* Body = FD->getBody();
225 if (Body) HandleCode(FD, Body, FunctionActions);
226 break;
227 }
228
229 case Decl::ObjCMethod: {
230 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000231
232 if (FName.size() > 0 && FName != MD->getSelector().getName())
233 return;
234
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000235 Stmt* Body = MD->getBody();
236 if (Body) HandleCode(MD, Body, ObjCMethodActions);
237 break;
238 }
239
240 default:
241 break;
242 }
243}
244
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000245void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
246
247 if (ObjCImplementationActions.empty())
248 return;
249
250 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) {
251
252 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
253 HandleCode(ID, 0, ObjCImplementationActions);
254 }
255}
256
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000257void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
258
259 // Don't run the actions if an error has occured with parsing the file.
260 if (Diags.hasErrorOccurred())
261 return;
262
263 SourceLocation Loc = D->getLocation();
264
265 // Only run actions on declarations defined in actual source.
266 if (!Loc.isFileID())
267 return;
268
269 // Don't run the actions on declarations in header files unless
270 // otherwise specified.
271 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
272 return;
273
274 // Create an AnalysisManager that will manage the state for analyzing
275 // this method/function.
276 AnalysisManager mgr(*this, D, Body);
277
278 // Dispatch on the actions.
Ted Kremenekc0959972008-07-02 21:24:01 +0000279 for (Actions::iterator I = actions.begin(),
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000280 E = actions.end(); I != E; ++I)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000281 (*I)(mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000282}
283
284//===----------------------------------------------------------------------===//
285// Analyses
286//===----------------------------------------------------------------------===//
287
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000288static void ActionWarnDeadStores(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000289 if (LiveVariables* L = mgr.getLiveVariables()) {
290 BugReporter BR(mgr);
291 CheckDeadStores(*L, BR);
292 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000293}
294
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000295static void ActionWarnUninitVals(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000296 if (CFG* c = mgr.getCFG())
297 CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000298}
299
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000300
Ted Kremenekbc46f342008-07-02 16:35:50 +0000301static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000302
Ted Kremenek7032f462008-07-03 05:26:14 +0000303
Ted Kremenekbc46f342008-07-02 16:35:50 +0000304 llvm::OwningPtr<GRTransferFuncs> TF(tf);
Ted Kremenek7032f462008-07-03 05:26:14 +0000305
306 // Construct the analysis engine.
307 LiveVariables* L = mgr.getLiveVariables();
308 if (!L) return;
Ted Kremenekbc46f342008-07-02 16:35:50 +0000309
Ted Kremenek34d77342008-07-02 16:49:11 +0000310 // Display progress.
311 if (!mgr.shouldVisualize())
312 mgr.DisplayFunction();
313
Ted Kremenek7032f462008-07-03 05:26:14 +0000314 GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L);
Ted Kremenekbc46f342008-07-02 16:35:50 +0000315 Eng.setTransferFunctions(tf);
316
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000317 // Execute the worklist algorithm.
318 Eng.ExecuteWorkList();
Ted Kremenekbc46f342008-07-02 16:35:50 +0000319
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000320 // Display warnings.
Ted Kremenekc0959972008-07-02 21:24:01 +0000321 Eng.EmitWarnings(mgr);
Ted Kremenek34d77342008-07-02 16:49:11 +0000322
323 // Visualize the exploded graph.
324 if (mgr.shouldVisualize())
325 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000326}
327
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000328static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
Ted Kremenekbc46f342008-07-02 16:35:50 +0000329 bool StandardWarnings) {
330
331 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
332 GCEnabled,
333 StandardWarnings,
334 mgr.getLangOptions());
335
336 ActionGRExprEngine(mgr, TF);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000337}
338
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000339static void ActionCheckerCFRef(AnalysisManager& mgr) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000340
341 switch (mgr.getLangOptions().getGCMode()) {
342 default:
343 assert (false && "Invalid GC mode.");
344 case LangOptions::NonGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000345 ActionCheckerCFRefAux(mgr, false, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000346 break;
347
348 case LangOptions::GCOnly:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000349 ActionCheckerCFRefAux(mgr, true, true);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000350 break;
351
352 case LangOptions::HybridGC:
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000353 ActionCheckerCFRefAux(mgr, false, true);
354 ActionCheckerCFRefAux(mgr, true, false);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000355 break;
356 }
357}
358
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000359static void ActionCheckerSimple(AnalysisManager& mgr) {
Ted Kremenekbc46f342008-07-02 16:35:50 +0000360 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
361}
362
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000363static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000364 if (LiveVariables* L = mgr.getLiveVariables()) {
365 mgr.DisplayFunction();
366 L->dumpBlockLiveness(mgr.getSourceManager());
367 }
Ted Kremenek235e0312008-07-02 18:11:29 +0000368}
369
Ted Kremenek902141f2008-07-02 18:23:21 +0000370static void ActionCFGDump(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000371 if (CFG* c = mgr.getCFG()) {
372 mgr.DisplayFunction();
373 c->dump();
374 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000375}
376
377static void ActionCFGView(AnalysisManager& mgr) {
Ted Kremenek7032f462008-07-03 05:26:14 +0000378 if (CFG* c = mgr.getCFG()) {
379 mgr.DisplayFunction();
380 c->viewCFG();
381 }
Ted Kremenek902141f2008-07-02 18:23:21 +0000382}
383
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000384static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000385 BugReporter BR(mgr);
Ted Kremenek3cd483c2008-07-03 14:35:01 +0000386
387 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
388 mgr.getLangOptions(), BR);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000389}
390
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000391static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
Ted Kremenek0d8019e2008-07-11 22:40:47 +0000392 BugReporter BR(mgr);
393
394 CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
395 BR);
396}
397
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000398//===----------------------------------------------------------------------===//
399// AnalysisConsumer creation.
400//===----------------------------------------------------------------------===//
401
402ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
403 Diagnostic &diags, Preprocessor* pp,
404 PreprocessorFactory* ppf,
405 const LangOptions& lopts,
406 const std::string& fname,
407 const std::string& htmldir,
408 bool visualize, bool trim,
409 bool analyzeAll) {
410
411 llvm::OwningPtr<AnalysisConsumer>
412 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir,
413 visualize, trim, analyzeAll));
414
415 for ( ; Beg != End ; ++Beg)
416 switch (*Beg) {
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000417#define ANALYSIS(NAME, CMD, DESC)\
418 case NAME:\
419 C->addCodeAction(&Action ## NAME);\
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000420 break;
Ted Kremenekfb9a48c2008-07-14 23:41:13 +0000421#include "Analyses.def"
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000422 default: break;
423 }
424
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000425 return C.take();
426}
427