blob: c557b80c7ee86c8f883ec5cceaba6030f25d6ddb [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
44namespace {
45
46 class AnalysisManager;
47 typedef void (*CodeAction)(AnalysisManager& Mgr);
48
49} // end anonymous namespace
50
51//===----------------------------------------------------------------------===//
52// AnalysisConsumer declaration.
53//===----------------------------------------------------------------------===//
54
55namespace {
56
57 class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000058 typedef std::vector<CodeAction> Actions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000059 Actions FunctionActions;
60 Actions ObjCMethodActions;
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000061 Actions ObjCImplementationActions;
Ted Kremenekf4381fd2008-07-02 00:03:09 +000062
63 public:
64 const bool Visualize;
65 const bool TrimGraph;
66 const LangOptions& LOpts;
67 Diagnostic &Diags;
68 ASTContext* Ctx;
69 Preprocessor* PP;
70 PreprocessorFactory* PPF;
71 const std::string HTMLDir;
72 const std::string FName;
73 llvm::OwningPtr<PathDiagnosticClient> PD;
74 bool AnalyzeAll;
75
76 AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
77 PreprocessorFactory* ppf,
78 const LangOptions& lopts,
79 const std::string& fname,
80 const std::string& htmldir,
81 bool visualize, bool trim, bool analyzeAll)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000082 : Visualize(visualize), TrimGraph(trim), LOpts(lopts), Diags(diags),
Ted Kremenekf4381fd2008-07-02 00:03:09 +000083 Ctx(0), PP(pp), PPF(ppf),
84 HTMLDir(htmldir),
85 FName(fname),
86 AnalyzeAll(analyzeAll) {}
87
88 void addCodeAction(CodeAction action) {
Ted Kremenekdb09a4d2008-07-03 04:29:21 +000089 FunctionActions.push_back(action);
90 ObjCMethodActions.push_back(action);
91 }
92
93 void addObjCImplementationAction(CodeAction action) {
94 ObjCImplementationActions.push_back(action);
Ted Kremenekf4381fd2008-07-02 00:03:09 +000095 }
96
97 virtual void Initialize(ASTContext &Context) {
98 Ctx = &Context;
99 }
100
101 virtual void HandleTopLevelDecl(Decl *D);
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000102 virtual void HandleTranslationUnit(TranslationUnit &TU);
103
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000104 void HandleCode(Decl* D, Stmt* Body, Actions actions);
105 };
106
107
Ted Kremenekc0959972008-07-02 21:24:01 +0000108 class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000109 Decl* D;
110 Stmt* Body;
111 AnalysisConsumer& C;
Ted Kremenek34d77342008-07-02 16:49:11 +0000112 bool DisplayedFunction;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000113
114 llvm::OwningPtr<CFG> cfg;
115 llvm::OwningPtr<LiveVariables> liveness;
116 llvm::OwningPtr<ParentMap> PM;
117
118 public:
119 AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
Ted Kremenek34d77342008-07-02 16:49:11 +0000120 : D(d), Body(b), C(c), DisplayedFunction(false) {}
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000121
122
123 Decl* getCodeDecl() const { return D; }
124 Stmt* getBody() const { return Body; }
125
Ted Kremenekc0959972008-07-02 21:24:01 +0000126 virtual CFG& getCFG() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000127 if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000128 return *cfg.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000129 }
130
Ted Kremenekc0959972008-07-02 21:24:01 +0000131 virtual ParentMap& getParentMap() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000132 if (!PM)
133 PM.reset(new ParentMap(getBody()));
Ted Kremenekc0959972008-07-02 21:24:01 +0000134 return *PM.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000135 }
136
Ted Kremenekc0959972008-07-02 21:24:01 +0000137 virtual ASTContext& getContext() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000138 return *C.Ctx;
139 }
140
Ted Kremenekc0959972008-07-02 21:24:01 +0000141 virtual SourceManager& getSourceManager() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000142 return getContext().getSourceManager();
143 }
144
Ted Kremenekc0959972008-07-02 21:24:01 +0000145 virtual Diagnostic& getDiagnostic() {
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000146 return C.Diags;
147 }
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000148
149 const LangOptions& getLangOptions() const {
150 return C.LOpts;
151 }
152
Ted Kremenekc0959972008-07-02 21:24:01 +0000153 virtual PathDiagnosticClient* getPathDiagnosticClient() {
Ted Kremeneke2075582008-07-02 23:16:33 +0000154 if (C.PD.get() == 0 && !C.HTMLDir.empty())
155 C.PD.reset(CreateHTMLDiagnosticClient(C.HTMLDir, C.PP, C.PPF));
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000156
Ted Kremeneke2075582008-07-02 23:16:33 +0000157 return C.PD.get();
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000158 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000159
Ted Kremenekc0959972008-07-02 21:24:01 +0000160 virtual LiveVariables& getLiveVariables() {
Ted Kremenek235e0312008-07-02 18:11:29 +0000161 if (!liveness) {
Ted Kremenekc0959972008-07-02 21:24:01 +0000162 liveness.reset(new LiveVariables(getCFG()));
163 liveness->runOnCFG(getCFG());
164 liveness->runOnAllBlocks(getCFG(), 0, true);
Ted Kremenek235e0312008-07-02 18:11:29 +0000165 }
Ted Kremenekc0959972008-07-02 21:24:01 +0000166
167 return *liveness.get();
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000168 }
Ted Kremenek34d77342008-07-02 16:49:11 +0000169
170 bool shouldVisualize() const {
171 return C.Visualize;
172 }
173
174 bool shouldTrimGraph() const {
175 return C.TrimGraph;
176 }
177
178 void DisplayFunction() {
179
180 if (DisplayedFunction)
181 return;
182
183 DisplayedFunction = true;
184
185 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(getCodeDecl())) {
186 llvm::cerr << "ANALYZE: "
187 << getContext().getSourceManager().getSourceName(FD->getLocation())
188 << ' '
189 << FD->getIdentifier()->getName()
190 << '\n';
191 }
192 else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCodeDecl())) {
193 llvm::cerr << "ANALYZE (ObjC Method): "
194 << getContext().getSourceManager().getSourceName(MD->getLocation())
195 << " '"
196 << MD->getSelector().getName() << "'\n";
197 }
198 }
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000199 };
200
201} // end anonymous namespace
202
203namespace llvm {
204 template <> struct FoldingSetTrait<CodeAction> {
205 static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
206 ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
207 }
208 };
209}
210
211//===----------------------------------------------------------------------===//
212// AnalysisConsumer implementation.
213//===----------------------------------------------------------------------===//
214
215void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
216 switch (D->getKind()) {
217 case Decl::Function: {
218 FunctionDecl* FD = cast<FunctionDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000219
220 if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
221 break;
222
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000223 Stmt* Body = FD->getBody();
224 if (Body) HandleCode(FD, Body, FunctionActions);
225 break;
226 }
227
228 case Decl::ObjCMethod: {
229 ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
Ted Kremenek235e0312008-07-02 18:11:29 +0000230
231 if (FName.size() > 0 && FName != MD->getSelector().getName())
232 return;
233
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000234 Stmt* Body = MD->getBody();
235 if (Body) HandleCode(MD, Body, ObjCMethodActions);
236 break;
237 }
238
239 default:
240 break;
241 }
242}
243
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000244void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
245
246 if (ObjCImplementationActions.empty())
247 return;
248
249 for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) {
250
251 if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
252 HandleCode(ID, 0, ObjCImplementationActions);
253 }
254}
255
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000256void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
257
258 // Don't run the actions if an error has occured with parsing the file.
259 if (Diags.hasErrorOccurred())
260 return;
261
262 SourceLocation Loc = D->getLocation();
263
264 // Only run actions on declarations defined in actual source.
265 if (!Loc.isFileID())
266 return;
267
268 // Don't run the actions on declarations in header files unless
269 // otherwise specified.
270 if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
271 return;
272
273 // Create an AnalysisManager that will manage the state for analyzing
274 // this method/function.
275 AnalysisManager mgr(*this, D, Body);
276
277 // Dispatch on the actions.
Ted Kremenekc0959972008-07-02 21:24:01 +0000278 for (Actions::iterator I = actions.begin(),
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000279 E = actions.end(); I != E; ++I)
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000280 (*I)(mgr);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000281}
282
283//===----------------------------------------------------------------------===//
284// Analyses
285//===----------------------------------------------------------------------===//
286
287static void ActionDeadStores(AnalysisManager& mgr) {
Ted Kremeneke2075582008-07-02 23:16:33 +0000288 BugReporter BR(mgr);
289 CheckDeadStores(mgr.getLiveVariables(), BR);
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000290}
291
292static void ActionUninitVals(AnalysisManager& mgr) {
Ted Kremenekc0959972008-07-02 21:24:01 +0000293 CheckUninitializedValues(mgr.getCFG(), mgr.getContext(),
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000294 mgr.getDiagnostic());
295}
296
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000297
Ted Kremenekbc46f342008-07-02 16:35:50 +0000298static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf) {
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000299
Ted Kremenekbc46f342008-07-02 16:35:50 +0000300 llvm::OwningPtr<GRTransferFuncs> TF(tf);
301
Ted Kremenek34d77342008-07-02 16:49:11 +0000302 // Display progress.
303 if (!mgr.shouldVisualize())
304 mgr.DisplayFunction();
305
Ted Kremenekbc46f342008-07-02 16:35:50 +0000306 // Construct the analysis engine.
Ted Kremenekc0959972008-07-02 21:24:01 +0000307 GRExprEngine Eng(mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(),
308 mgr.getLiveVariables());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000309 Eng.setTransferFunctions(tf);
310
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000311 // Execute the worklist algorithm.
312 Eng.ExecuteWorkList();
Ted Kremenekbc46f342008-07-02 16:35:50 +0000313
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000314 // Display warnings.
Ted Kremenekc0959972008-07-02 21:24:01 +0000315 Eng.EmitWarnings(mgr);
Ted Kremenek34d77342008-07-02 16:49:11 +0000316
317 // Visualize the exploded graph.
318 if (mgr.shouldVisualize())
319 Eng.ViewGraph(mgr.shouldTrimGraph());
Ted Kremenekbc46f342008-07-02 16:35:50 +0000320}
321
322static void ActionRefLeakCheckerAux(AnalysisManager& mgr, bool GCEnabled,
323 bool StandardWarnings) {
324
325 GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
326 GCEnabled,
327 StandardWarnings,
328 mgr.getLangOptions());
329
330 ActionGRExprEngine(mgr, TF);
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000331}
332
333static void ActionRefLeakChecker(AnalysisManager& mgr) {
334
335 switch (mgr.getLangOptions().getGCMode()) {
336 default:
337 assert (false && "Invalid GC mode.");
338 case LangOptions::NonGC:
339 ActionRefLeakCheckerAux(mgr, false, true);
340 break;
341
342 case LangOptions::GCOnly:
343 ActionRefLeakCheckerAux(mgr, true, true);
344 break;
345
346 case LangOptions::HybridGC:
347 ActionRefLeakCheckerAux(mgr, false, true);
348 ActionRefLeakCheckerAux(mgr, true, false);
349 break;
350 }
351}
352
Ted Kremenekbc46f342008-07-02 16:35:50 +0000353static void ActionSimpleChecks(AnalysisManager& mgr) {
354 ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
355}
356
Ted Kremenek235e0312008-07-02 18:11:29 +0000357static void ActionLiveness(AnalysisManager& mgr) {
358 mgr.DisplayFunction();
Ted Kremenekc0959972008-07-02 21:24:01 +0000359 mgr.getLiveVariables().dumpBlockLiveness(mgr.getSourceManager());
Ted Kremenek235e0312008-07-02 18:11:29 +0000360}
361
Ted Kremenek902141f2008-07-02 18:23:21 +0000362static void ActionCFGDump(AnalysisManager& mgr) {
363 mgr.DisplayFunction();
Ted Kremenekc0959972008-07-02 21:24:01 +0000364 mgr.getCFG().dump();
Ted Kremenek902141f2008-07-02 18:23:21 +0000365}
366
367static void ActionCFGView(AnalysisManager& mgr) {
368 mgr.DisplayFunction();
Ted Kremenekc0959972008-07-02 21:24:01 +0000369 mgr.getCFG().viewCFG();
Ted Kremenek902141f2008-07-02 18:23:21 +0000370}
371
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000372static void ActionCheckObjCDealloc(AnalysisManager& mgr) {
373 BugReporter BR(mgr);
374 CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
375}
376
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000377//===----------------------------------------------------------------------===//
378// AnalysisConsumer creation.
379//===----------------------------------------------------------------------===//
380
381ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
382 Diagnostic &diags, Preprocessor* pp,
383 PreprocessorFactory* ppf,
384 const LangOptions& lopts,
385 const std::string& fname,
386 const std::string& htmldir,
387 bool visualize, bool trim,
388 bool analyzeAll) {
389
390 llvm::OwningPtr<AnalysisConsumer>
391 C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir,
392 visualize, trim, analyzeAll));
393
394 for ( ; Beg != End ; ++Beg)
395 switch (*Beg) {
396 case WarnDeadStores:
397 C->addCodeAction(&ActionDeadStores);
398 break;
399
400 case WarnUninitVals:
401 C->addCodeAction(&ActionUninitVals);
402 break;
Ted Kremenek235e0312008-07-02 18:11:29 +0000403
404 case DisplayLiveVariables:
405 C->addCodeAction(&ActionLiveness);
406 break;
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000407
Ted Kremenekb35a74a2008-07-02 00:44:58 +0000408 case CheckerCFRef:
409 C->addCodeAction(&ActionRefLeakChecker);
410 break;
411
Ted Kremenekbc46f342008-07-02 16:35:50 +0000412 case CheckerSimple:
413 C->addCodeAction(&ActionSimpleChecks);
414 break;
415
Ted Kremenek902141f2008-07-02 18:23:21 +0000416 case CFGDump:
417 C->addCodeAction(&ActionCFGDump);
418 break;
419
420 case CFGView:
421 C->addCodeAction(&ActionCFGView);
422 break;
423
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000424 default: break;
425 }
426
Ted Kremenekdb09a4d2008-07-03 04:29:21 +0000427 // Checks we always perform:
428 C->addObjCImplementationAction(&ActionCheckObjCDealloc);
429
Ted Kremenekf4381fd2008-07-02 00:03:09 +0000430 return C.take();
431}
432