 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
43.8% |
81 / 185 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
61.1% |
113 / 185 |
| |
|
Line Coverage: |
55.1% |
147 / 267 |
| |
 |
|
 |
1 : //===--- 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 "clang/Frontend/AnalysisConsumer.h"
15 : #include "clang/AST/ASTConsumer.h"
16 : #include "clang/AST/Decl.h"
17 : #include "clang/AST/DeclCXX.h"
18 : #include "clang/AST/DeclObjC.h"
19 : #include "clang/AST/ParentMap.h"
20 : #include "clang/Analysis/Analyses/LiveVariables.h"
21 : #include "clang/Analysis/Analyses/UninitializedValues.h"
22 : #include "clang/Analysis/CFG.h"
23 : #include "clang/Checker/Checkers/LocalCheckers.h"
24 : #include "clang/Checker/ManagerRegistry.h"
25 : #include "clang/Checker/BugReporter/PathDiagnostic.h"
26 : #include "clang/Checker/PathSensitive/AnalysisManager.h"
27 : #include "clang/Checker/BugReporter/BugReporter.h"
28 : #include "clang/Checker/PathSensitive/GRExprEngine.h"
29 : #include "clang/Checker/PathSensitive/GRTransferFuncs.h"
30 : #include "clang/Basic/FileManager.h"
31 : #include "clang/Basic/SourceManager.h"
32 : #include "clang/Frontend/PathDiagnosticClients.h"
33 : #include "clang/Lex/Preprocessor.h"
34 : #include "llvm/Support/raw_ostream.h"
35 : #include "llvm/System/Path.h"
36 : #include "llvm/System/Program.h"
37 : #include "llvm/ADT/OwningPtr.h"
38 :
39 : using namespace clang;
40 :
41 : static ExplodedNode::Auditor* CreateUbiViz();
42 :
43 : //===----------------------------------------------------------------------===//
44 : // Basic type definitions.
45 : //===----------------------------------------------------------------------===//
46 :
47 : //===----------------------------------------------------------------------===//
48 : // Special PathDiagnosticClients.
49 : //===----------------------------------------------------------------------===//
50 :
51 : static PathDiagnosticClient*
52 : CreatePlistHTMLDiagnosticClient(const std::string& prefix,
53 0: const Preprocessor &PP) {
54 0: llvm::sys::Path F(prefix);
55 0: PathDiagnosticClient *PD = CreateHTMLDiagnosticClient(F.getDirname(), PP);
56 0: return CreatePlistDiagnosticClient(prefix, PP, PD);
57 : }
58 :
59 : //===----------------------------------------------------------------------===//
60 : // AnalysisConsumer declaration.
61 : //===----------------------------------------------------------------------===//
62 :
63 : namespace {
64 :
187: branch 8 taken
0: branch 9 not taken
0: branch 19 not taken
0: branch 20 not taken
65 187: class AnalysisConsumer : public ASTConsumer {
66 : public:
67 : typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
68 :
69 : private:
70 : typedef std::vector<CodeAction> Actions;
71 : Actions FunctionActions;
72 : Actions ObjCMethodActions;
73 : Actions ObjCImplementationActions;
74 : Actions TranslationUnitActions;
75 :
76 : public:
77 : ASTContext* Ctx;
78 : const Preprocessor &PP;
79 : const std::string OutDir;
80 : AnalyzerOptions Opts;
81 : bool declDisplayed;
82 :
83 :
84 : // PD is owned by AnalysisManager.
85 : PathDiagnosticClient *PD;
86 :
87 : StoreManagerCreator CreateStoreMgr;
88 : ConstraintManagerCreator CreateConstraintMgr;
89 :
90 : llvm::OwningPtr<AnalysisManager> Mgr;
91 :
92 : AnalysisConsumer(const Preprocessor& pp,
93 : const std::string& outdir,
94 188: const AnalyzerOptions& opts)
95 : : Ctx(0), PP(pp), OutDir(outdir),
96 188: Opts(opts), declDisplayed(false), PD(0) {
97 188: DigestAnalyzerOptions();
98 188: }
99 :
100 188: void DigestAnalyzerOptions() {
101 : // Create the PathDiagnosticClient.
2: branch 1 taken
186: branch 2 taken
102 188: if (!OutDir.empty()) {
1: branch 0 taken
1: branch 1 taken
0: branch 2 not taken
103 2: switch (Opts.AnalysisDiagOpt) {
104 : default:
105 : #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
106 : case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
107 : #include "clang/Frontend/Analyses.def"
108 : }
109 : }
110 :
111 : // Create the analyzer component creators.
0: branch 0 not taken
188: branch 1 taken
112 188: if (ManagerRegistry::StoreMgrCreator != 0) {
113 0: CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
114 : }
115 : else {
0: branch 0 not taken
90: branch 1 taken
97: branch 2 taken
1: branch 3 taken
116 188: switch (Opts.AnalysisStoreOpt) {
117 : default:
118 0: assert(0 && "Unknown store manager.");
119 : #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \
120 : case NAME##Model: CreateStoreMgr = CREATEFN; break;
121 : #include "clang/Frontend/Analyses.def"
122 : }
123 : }
124 :
0: branch 0 not taken
188: branch 1 taken
125 188: if (ManagerRegistry::ConstraintMgrCreator != 0)
126 0: CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
127 : else {
0: branch 0 not taken
51: branch 1 taken
137: branch 2 taken
128 188: switch (Opts.AnalysisConstraintsOpt) {
129 : default:
130 0: assert(0 && "Unknown store manager.");
131 : #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \
132 : case NAME##Model: CreateConstraintMgr = CREATEFN; break;
133 : #include "clang/Frontend/Analyses.def"
134 : }
135 : }
136 188: }
137 :
138 2422: void DisplayFunction(const Decl *D) {
0: branch 0 not taken
2422: branch 1 taken
2422: branch 2 taken
2422: branch 3 taken
139 2422: if (!Opts.AnalyzerDisplayProgress || declDisplayed)
140 2422: return;
141 :
142 0: declDisplayed = true;
143 0: SourceManager &SM = Mgr->getASTContext().getSourceManager();
144 0: PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
145 0: llvm::errs() << "ANALYZE: " << Loc.getFilename();
146 :
0: branch 1 not taken
0: branch 2 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 7 not taken
147 0: if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
148 0: const NamedDecl *ND = cast<NamedDecl>(D);
149 0: llvm::errs() << ' ' << ND->getNameAsString() << '\n';
150 : }
0: branch 1 not taken
0: branch 2 not taken
151 0: else if (isa<BlockDecl>(D)) {
152 : llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
153 0: << Loc.getColumn() << '\n';
154 : }
155 : }
156 :
157 197: void addCodeAction(CodeAction action) {
158 197: FunctionActions.push_back(action);
159 197: ObjCMethodActions.push_back(action);
160 197: }
161 :
162 4: void addObjCImplementationAction(CodeAction action) {
163 4: ObjCImplementationActions.push_back(action);
164 4: }
165 :
166 0: void addTranslationUnitAction(CodeAction action) {
167 0: TranslationUnitActions.push_back(action);
168 0: }
169 :
170 188: virtual void Initialize(ASTContext &Context) {
171 188: Ctx = &Context;
172 : Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
173 : PP.getLangOptions(), PD,
174 : CreateStoreMgr, CreateConstraintMgr,
175 : Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
176 : Opts.PurgeDead, Opts.EagerlyAssume,
177 188: Opts.TrimGraph));
178 188: }
179 :
180 6132: virtual void HandleTopLevelDecl(DeclGroupRef D) {
181 6132: declDisplayed = false;
6638: branch 2 taken
6132: branch 3 taken
182 12770: for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
183 6638: HandleTopLevelSingleDecl(*I);
184 6132: }
185 :
186 : void HandleTopLevelSingleDecl(Decl *D);
187 : virtual void HandleTranslationUnit(ASTContext &C);
188 :
189 : void HandleCode(Decl* D, Stmt* Body, Actions& actions);
190 : };
191 : } // end anonymous namespace
192 :
193 : namespace llvm {
194 : template <> struct FoldingSetTrait<AnalysisConsumer::CodeAction> {
195 : static inline void Profile(AnalysisConsumer::CodeAction X,
196 : FoldingSetNodeID& ID) {
197 : ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
198 : }
199 : };
200 : }
201 :
202 : //===----------------------------------------------------------------------===//
203 : // AnalysisConsumer implementation.
204 : //===----------------------------------------------------------------------===//
205 :
206 6638: void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) {
2551: branch 1 taken
269: branch 2 taken
16: branch 3 taken
3802: branch 4 taken
207 6638: switch (D->getKind()) {
208 : case Decl::Function: {
209 2551: FunctionDecl* FD = cast<FunctionDecl>(D);
210 :
0: branch 1 not taken
2551: branch 2 taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 9 not taken
2551: branch 10 taken
211 2551: if (!Opts.AnalyzeSpecificFunction.empty() &&
212 : Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName())
213 0: break;
214 :
215 2551: Stmt* Body = FD->getBody();
1719: branch 0 taken
832: branch 1 taken
216 2551: if (Body) HandleCode(FD, Body, FunctionActions);
217 2551: break;
218 : }
219 :
220 : case Decl::ObjCMethod: {
221 269: ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
222 :
0: branch 1 not taken
269: branch 2 taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
269: branch 9 taken
0: branch 11 not taken
269: branch 12 taken
223 269: if (Opts.AnalyzeSpecificFunction.size() > 0 &&
224 : Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
225 0: return;
226 :
227 269: Stmt* Body = MD->getBody();
269: branch 0 taken
0: branch 1 not taken
228 269: if (Body) HandleCode(MD, Body, ObjCMethodActions);
229 269: break;
230 : }
231 :
232 : case Decl::CXXConstructor:
233 : case Decl::CXXDestructor:
234 : case Decl::CXXConversion:
235 : case Decl::CXXMethod: {
236 16: CXXMethodDecl *CXXMD = cast<CXXMethodDecl>(D);
237 :
0: branch 1 not taken
16: branch 2 taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
16: branch 9 taken
238 16: if (Opts.AnalyzeSpecificFunction.size() > 0 &&
239 : Opts.AnalyzeSpecificFunction != CXXMD->getName())
240 0: return;
241 :
242 16: Stmt *Body = CXXMD->getBody();
16: branch 0 taken
0: branch 1 not taken
243 16: if (Body) HandleCode(CXXMD, Body, FunctionActions);
244 : break;
245 : }
246 :
247 : default:
248 : break;
249 : }
250 : }
251 :
252 188: void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
253 :
254 188: TranslationUnitDecl *TU = C.getTranslationUnitDecl();
255 :
0: branch 1 not taken
188: branch 2 taken
256 188: if (!TranslationUnitActions.empty()) {
257 : // Find the entry function definition (if any).
258 0: FunctionDecl *FD = 0;
259 : // Must specify an entry function.
0: branch 1 not taken
0: branch 2 not taken
260 0: if (!Opts.AnalyzeSpecificFunction.empty()) {
0: branch 4 not taken
0: branch 5 not taken
261 0: for (DeclContext::decl_iterator I=TU->decls_begin(), E=TU->decls_end();
262 : I != E; ++I) {
0: branch 2 not taken
0: branch 3 not taken
263 0: if (FunctionDecl *fd = dyn_cast<FunctionDecl>(*I))
0: branch 1 not taken
0: branch 2 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 10 not taken
0: branch 11 not taken
264 0: if (fd->isThisDeclarationADefinition() &&
265 : fd->getNameAsString() == Opts.AnalyzeSpecificFunction) {
266 0: FD = fd;
267 0: break;
268 : }
269 : }
270 : }
271 :
0: branch 0 not taken
0: branch 1 not taken
272 0: if (FD) {
0: branch 3 not taken
0: branch 4 not taken
273 0: for (Actions::iterator I = TranslationUnitActions.begin(),
274 0: E = TranslationUnitActions.end(); I != E; ++I)
275 0: (*I)(*this, *Mgr, FD);
276 : }
277 : }
278 :
4: branch 1 taken
184: branch 2 taken
279 188: if (!ObjCImplementationActions.empty()) {
57: branch 3 taken
4: branch 4 taken
280 65: for (DeclContext::decl_iterator I = TU->decls_begin(),
281 4: E = TU->decls_end();
282 : I != E; ++I)
12: branch 2 taken
45: branch 3 taken
283 57: if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
284 12: HandleCode(ID, 0, ObjCImplementationActions);
285 : }
286 :
287 : // Explicitly destroy the PathDiagnosticClient. This will flush its output.
288 : // FIXME: This should be replaced with something that doesn't rely on
289 : // side-effects in PathDiagnosticClient's destructor. This is required when
290 : // used with option -disable-free.
291 188: Mgr.reset(NULL);
292 188: }
293 :
294 158: static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) {
24: branch 1 taken
134: branch 2 taken
295 158: if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
296 24: WL.push_back(BD);
297 :
314: branch 4 taken
158: branch 5 taken
298 472: for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
299 : I!=E; ++I)
26: branch 2 taken
288: branch 3 taken
300 314: if (DeclContext *DC = dyn_cast<DeclContext>(*I))
301 26: FindBlocks(DC, WL);
302 158: }
303 :
304 2016: void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
305 :
306 : // Don't run the actions if an error has occured with parsing the file.
0: branch 2 not taken
2016: branch 3 taken
307 2016: if (PP.getDiagnostics().hasErrorOccurred())
308 0: return;
309 :
310 : // Don't run the actions on declarations in header files unless
311 : // otherwise specified.
2016: branch 0 taken
0: branch 1 not taken
0: branch 5 not taken
2016: branch 6 taken
0: branch 7 not taken
2016: branch 8 taken
312 2016: if (!Opts.AnalyzeAll &&
313 : !Ctx->getSourceManager().isFromMainFile(D->getLocation()))
314 0: return;
315 :
316 : // Clear the AnalysisManager of old AnalysisContexts.
317 2016: Mgr->ClearContexts();
318 :
319 : // Dispatch on the actions.
320 2016: llvm::SmallVector<Decl*, 10> WL;
321 2016: WL.push_back(D);
322 :
2004: branch 0 taken
12: branch 1 taken
132: branch 2 taken
1872: branch 3 taken
323 2016: if (Body && Opts.AnalyzeNestedBlocks)
324 132: FindBlocks(cast<DeclContext>(D), WL);
325 :
2206: branch 4 taken
2016: branch 5 taken
326 4222: for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
2230: branch 2 taken
2206: branch 3 taken
327 4436: for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
328 : WI != WE; ++WI)
329 4246: (*I)(*this, *Mgr, *WI);
330 : }
331 :
332 : //===----------------------------------------------------------------------===//
333 : // Analyses
334 : //===----------------------------------------------------------------------===//
335 :
336 : static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
337 252: Decl *D) {
252: branch 1 taken
0: branch 2 not taken
338 252: if (LiveVariables *L = mgr.getLiveVariables(D)) {
339 252: C.DisplayFunction(D);
340 252: BugReporter BR(mgr);
341 252: CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
342 : }
343 252: }
344 :
345 : static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
346 12: Decl *D) {
12: branch 1 taken
0: branch 2 not taken
347 12: if (CFG* c = mgr.getCFG(D)) {
348 12: C.DisplayFunction(D);
349 12: CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
350 : }
351 12: }
352 :
353 :
354 : static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
355 : Decl *D,
356 2138: GRTransferFuncs* tf) {
357 :
358 2138: llvm::OwningPtr<GRTransferFuncs> TF(tf);
359 :
360 : // Display progress.
361 2138: C.DisplayFunction(D);
362 :
363 : // Construct the analysis engine. We first query for the LiveVariables
364 : // information to see if the CFG is valid.
365 : // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
0: branch 1 not taken
2138: branch 2 taken
366 2138: if (!mgr.getLiveVariables(D))
367 0: return;
368 :
369 2138: GRExprEngine Eng(mgr, TF.take());
370 :
1845: branch 0 taken
293: branch 1 taken
371 2138: if (C.Opts.EnableExperimentalInternalChecks)
372 1845: RegisterExperimentalInternalChecks(Eng);
373 :
374 2138: RegisterAppleChecks(Eng, *D);
375 :
10: branch 0 taken
2128: branch 1 taken
376 2138: if (C.Opts.EnableExperimentalChecks)
377 10: RegisterExperimentalChecks(Eng);
378 :
379 : // Set the graph auditor.
380 2138: llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
0: branch 1 not taken
2138: branch 2 taken
381 2138: if (mgr.shouldVisualizeUbigraph()) {
382 0: Auditor.reset(CreateUbiViz());
383 0: ExplodedNode::SetAuditor(Auditor.get());
384 : }
385 :
386 : // Execute the worklist algorithm.
387 2138: Eng.ExecuteWorkList(mgr.getStackFrame(D));
388 :
389 : // Release the auditor (if any) so that it doesn't monitor the graph
390 : // created BugReporter.
391 2138: ExplodedNode::SetAuditor(0);
392 :
393 : // Visualize the exploded graph.
0: branch 1 not taken
2138: branch 2 taken
394 2138: if (mgr.shouldVisualizeGraphviz())
395 0: Eng.ViewGraph(mgr.shouldTrimGraph());
396 :
397 : // Display warnings.
2138: branch 5 taken
0: branch 6 not taken
398 2138: Eng.getBugReporter().FlushReports();
399 : }
400 :
401 : static void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr,
402 2138: Decl *D, bool GCEnabled) {
403 :
404 : GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
405 : GCEnabled,
406 2138: mgr.getLangOptions());
407 :
408 2138: ActionGRExprEngine(C, mgr, D, TF);
409 2138: }
410 :
411 : static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,
412 1946: Decl *D) {
413 :
0: branch 2 not taken
1708: branch 3 taken
46: branch 4 taken
192: branch 5 taken
414 1946: switch (mgr.getLangOptions().getGCMode()) {
415 : default:
416 0: assert (false && "Invalid GC mode.");
417 : case LangOptions::NonGC:
418 1708: ActionObjCMemCheckerAux(C, mgr, D, false);
419 1708: break;
420 :
421 : case LangOptions::GCOnly:
422 46: ActionObjCMemCheckerAux(C, mgr, D, true);
423 46: break;
424 :
425 : case LangOptions::HybridGC:
426 192: ActionObjCMemCheckerAux(C, mgr, D, false);
427 192: ActionObjCMemCheckerAux(C, mgr, D, true);
428 : break;
429 : }
430 1946: }
431 :
432 : static void ActionDisplayLiveVariables(AnalysisConsumer &C,
433 0: AnalysisManager& mgr, Decl *D) {
0: branch 1 not taken
0: branch 2 not taken
434 0: if (LiveVariables* L = mgr.getLiveVariables(D)) {
435 0: C.DisplayFunction(D);
436 0: L->dumpBlockLiveness(mgr.getSourceManager());
437 : }
438 0: }
439 :
440 0: static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
0: branch 1 not taken
0: branch 2 not taken
441 0: if (CFG *cfg = mgr.getCFG(D)) {
442 0: C.DisplayFunction(D);
443 0: cfg->dump(mgr.getLangOptions());
444 : }
445 0: }
446 :
447 0: static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
0: branch 1 not taken
0: branch 2 not taken
448 0: if (CFG *cfg = mgr.getCFG(D)) {
449 0: C.DisplayFunction(D);
450 0: cfg->viewCFG(mgr.getLangOptions());
451 : }
452 0: }
453 :
454 : static void ActionSecuritySyntacticChecks(AnalysisConsumer &C,
455 7: AnalysisManager &mgr, Decl *D) {
456 7: C.DisplayFunction(D);
457 7: BugReporter BR(mgr);
458 7: CheckSecuritySyntaxOnly(D, BR);
459 7: }
460 :
461 : static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr,
462 6: Decl *D) {
0: branch 2 not taken
6: branch 3 taken
463 6: if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
464 0: return;
465 :
466 6: C.DisplayFunction(D);
467 6: BugReporter BR(mgr);
468 6: CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
469 : }
470 :
471 : static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr,
472 4: Decl *D) {
473 4: C.DisplayFunction(D);
474 4: BugReporter BR(mgr);
475 4: CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
476 4: }
477 :
478 : static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr,
479 2: Decl *D) {
480 2: C.DisplayFunction(D);
481 2: BugReporter BR(mgr);
482 2: CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);
483 2: }
484 :
485 : static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr,
486 1: Decl *D) {
487 1: C.DisplayFunction(D);
488 1: BugReporter BR(mgr);
489 1: CheckSizeofPointer(D, BR);
490 1: }
491 :
492 : static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr,
493 0: Decl *D) {
494 : // FIXME: This is largely copy of ActionGRExprEngine. Needs cleanup.
495 : // Display progress.
496 0: C.DisplayFunction(D);
497 :
498 : // FIXME: Make a fake transfer function. The GRTransferFunc interface
499 : // eventually will be removed.
500 0: GRExprEngine Eng(mgr, new GRTransferFuncs());
501 :
0: branch 0 not taken
0: branch 1 not taken
502 0: if (C.Opts.EnableExperimentalInternalChecks)
503 0: RegisterExperimentalInternalChecks(Eng);
504 :
505 0: RegisterAppleChecks(Eng, *D);
506 :
0: branch 0 not taken
0: branch 1 not taken
507 0: if (C.Opts.EnableExperimentalChecks)
508 0: RegisterExperimentalChecks(Eng);
509 :
510 : // Register call inliner as the last checker.
511 0: RegisterCallInliner(Eng);
512 :
513 : // Execute the worklist algorithm.
514 0: Eng.ExecuteWorkList(mgr.getStackFrame(D));
515 :
516 : // Visualize the exploded graph.
0: branch 1 not taken
0: branch 2 not taken
517 0: if (mgr.shouldVisualizeGraphviz())
518 0: Eng.ViewGraph(mgr.shouldTrimGraph());
519 :
520 : // Display warnings.
521 0: Eng.getBugReporter().FlushReports();
522 0: }
523 :
524 : //===----------------------------------------------------------------------===//
525 : // AnalysisConsumer creation.
526 : //===----------------------------------------------------------------------===//
527 :
528 : ASTConsumer* clang::CreateAnalysisConsumer(const Preprocessor& pp,
529 : const std::string& OutDir,
530 188: const AnalyzerOptions& Opts) {
531 188: llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts));
532 :
201: branch 1 taken
188: branch 2 taken
533 389: for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i)
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
2: branch 4 taken
17: branch 5 taken
2: branch 6 taken
1: branch 7 taken
2: branch 8 taken
1: branch 9 taken
175: branch 10 taken
1: branch 11 taken
0: branch 12 not taken
0: branch 13 not taken
534 201: switch (Opts.AnalysisList[i]) {
535 : #define ANALYSIS(NAME, CMD, DESC, SCOPE)\
536 : case NAME:\
537 : C->add ## SCOPE ## Action(&Action ## NAME);\
538 : break;
539 : #include "clang/Frontend/Analyses.def"
540 : default: break;
541 : }
542 :
543 : // Last, disable the effects of '-Werror' when using the AnalysisConsumer.
544 188: pp.getDiagnostics().setWarningsAsErrors(false);
545 :
546 188: return C.take();
547 : }
548 :
549 : //===----------------------------------------------------------------------===//
550 : // Ubigraph Visualization. FIXME: Move to separate file.
551 : //===----------------------------------------------------------------------===//
552 :
553 : namespace {
554 :
555 : class UbigraphViz : public ExplodedNode::Auditor {
556 : llvm::OwningPtr<llvm::raw_ostream> Out;
557 : llvm::sys::Path Dir, Filename;
558 : unsigned Cntr;
559 :
560 : typedef llvm::DenseMap<void*,unsigned> VMap;
561 : VMap M;
562 :
563 : public:
564 : UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
565 : llvm::sys::Path& filename);
566 :
567 : ~UbigraphViz();
568 :
569 : virtual void AddEdge(ExplodedNode* Src, ExplodedNode* Dst);
570 : };
571 :
572 : } // end anonymous namespace
573 :
574 0: static ExplodedNode::Auditor* CreateUbiViz() {
575 0: std::string ErrMsg;
576 :
577 0: llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
0: branch 1 not taken
0: branch 2 not taken
578 0: if (!ErrMsg.empty())
579 0: return 0;
580 :
581 0: llvm::sys::Path Filename = Dir;
582 0: Filename.appendComponent("llvm_ubi");
583 0: Filename.makeUnique(true,&ErrMsg);
584 :
0: branch 1 not taken
0: branch 2 not taken
585 0: if (!ErrMsg.empty())
586 0: return 0;
587 :
588 0: llvm::errs() << "Writing '" << Filename.str() << "'.\n";
589 :
590 0: llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
591 0: Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
592 :
0: branch 1 not taken
0: branch 2 not taken
593 0: if (!ErrMsg.empty())
594 0: return 0;
595 :
596 0: return new UbigraphViz(Stream.take(), Dir, Filename);
597 : }
598 :
599 0: void UbigraphViz::AddEdge(ExplodedNode* Src, ExplodedNode* Dst) {
600 :
0: branch 0 not taken
0: branch 1 not taken
601 0: assert (Src != Dst && "Self-edges are not allowed.");
602 :
603 : // Lookup the Src. If it is a new node, it's a root.
604 0: VMap::iterator SrcI= M.find(Src);
605 : unsigned SrcID;
606 :
0: branch 3 not taken
0: branch 4 not taken
607 0: if (SrcI == M.end()) {
608 0: M[Src] = SrcID = Cntr++;
609 0: *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
610 : }
611 : else
612 0: SrcID = SrcI->second;
613 :
614 : // Lookup the Dst.
615 0: VMap::iterator DstI= M.find(Dst);
616 : unsigned DstID;
617 :
0: branch 3 not taken
0: branch 4 not taken
618 0: if (DstI == M.end()) {
619 0: M[Dst] = DstID = Cntr++;
620 0: *Out << "('vertex', " << DstID << ")\n";
621 : }
622 : else {
623 : // We have hit DstID before. Change its style to reflect a cache hit.
624 0: DstID = DstI->second;
625 0: *Out << "('change_vertex_style', " << DstID << ", 1)\n";
626 : }
627 :
628 : // Add the edge.
629 : *Out << "('edge', " << SrcID << ", " << DstID
630 0: << ", ('arrow','true'), ('oriented', 'true'))\n";
631 0: }
632 :
633 : UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
634 0: llvm::sys::Path& filename)
635 0: : Out(out), Dir(dir), Filename(filename), Cntr(0) {
636 :
637 0: *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
638 : *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
639 0: " ('size', '1.5'))\n";
640 0: }
641 :
642 0: UbigraphViz::~UbigraphViz() {
643 0: Out.reset(0);
644 0: llvm::errs() << "Running 'ubiviz' program... ";
645 0: std::string ErrMsg;
646 0: llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
647 0: std::vector<const char*> args;
648 0: args.push_back(Ubiviz.c_str());
649 0: args.push_back(Filename.c_str());
650 0: args.push_back(0);
651 :
0: branch 2 not taken
0: branch 3 not taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 10 not taken
0: branch 11 not taken
652 0: if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
653 0: llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
654 : }
655 :
656 : // Delete the directory.
657 0: Dir.eraseFromDisk(true);
0: branch 5 not taken
0: branch 6 not taken
0: branch 13 not taken
0: branch 14 not taken
0: branch 21 not taken
0: branch 22 not taken
658 0: }
Generated: 2010-02-10 01:31 by zcov