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 #define DEBUG_TYPE "AnalysisConsumer"
15 
16 #include "AnalysisConsumer.h"
17 #include "clang/AST/ASTConsumer.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/DeclCXX.h"
20 #include "clang/AST/DeclObjC.h"
21 #include "clang/AST/ParentMap.h"
22 #include "clang/AST/RecursiveASTVisitor.h"
23 #include "clang/Analysis/CFG.h"
24 #include "clang/Analysis/CallGraph.h"
25 #include "clang/Analysis/Analyses/LiveVariables.h"
26 #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
27 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
28 #include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
29 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
30 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
31 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
32 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
33 #include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
34 
35 #include "clang/Basic/FileManager.h"
36 #include "clang/Basic/SourceManager.h"
37 #include "clang/Frontend/AnalyzerOptions.h"
38 #include "clang/Lex/Preprocessor.h"
39 #include "llvm/Support/raw_ostream.h"
40 #include "llvm/Support/Path.h"
41 #include "llvm/Support/Program.h"
42 #include "llvm/Support/Timer.h"
43 #include "llvm/ADT/DepthFirstIterator.h"
44 #include "llvm/ADT/OwningPtr.h"
45 #include "llvm/ADT/SmallPtrSet.h"
46 #include "llvm/ADT/Statistic.h"
47 
48 #include <queue>
49 
50 using namespace clang;
51 using namespace ento;
52 using llvm::SmallPtrSet;
53 
54 static ExplodedNode::Auditor* CreateUbiViz();
55 
56 STATISTIC(NumFunctionTopLevel, "The # of functions at top level.");
57 STATISTIC(NumFunctionsAnalyzed, "The # of functions analysed (as top level).");
58 STATISTIC(NumBlocksInAnalyzedFunctions,
59                      "The # of basic blocks in the analyzed functions.");
60 STATISTIC(PercentReachableBlocks, "The % of reachable basic blocks.");
61 STATISTIC(MaxCFGSize, "The maximum number of basic blocks in a function.");
62 
63 //===----------------------------------------------------------------------===//
64 // Special PathDiagnosticConsumers.
65 //===----------------------------------------------------------------------===//
66 
67 static void createPlistHTMLDiagnosticConsumer(PathDiagnosticConsumers &C,
68                                               const std::string &prefix,
69                                               const Preprocessor &PP) {
70   createHTMLDiagnosticConsumer(C, llvm::sys::path::parent_path(prefix), PP);
71   createPlistDiagnosticConsumer(C, prefix, PP);
72 }
73 
74 namespace {
75 class ClangDiagPathDiagConsumer : public PathDiagnosticConsumer {
76   DiagnosticsEngine &Diag;
77 public:
78   ClangDiagPathDiagConsumer(DiagnosticsEngine &Diag) : Diag(Diag) {}
79   virtual ~ClangDiagPathDiagConsumer() {}
80   virtual StringRef getName() const { return "ClangDiags"; }
81   virtual bool useVerboseDescription() const { return false; }
82   virtual PathGenerationScheme getGenerationScheme() const { return None; }
83 
84   void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
85                             FilesMade *filesMade) {
86     for (std::vector<const PathDiagnostic*>::iterator I = Diags.begin(),
87          E = Diags.end(); I != E; ++I) {
88       const PathDiagnostic *PD = *I;
89       StringRef desc = PD->getDescription();
90       SmallString<512> TmpStr;
91       llvm::raw_svector_ostream Out(TmpStr);
92       for (StringRef::iterator I=desc.begin(), E=desc.end(); I!=E; ++I) {
93         if (*I == '%')
94           Out << "%%";
95         else
96           Out << *I;
97       }
98       Out.flush();
99       unsigned ErrorDiag = Diag.getCustomDiagID(DiagnosticsEngine::Warning,
100                                                 TmpStr);
101       SourceLocation L = PD->getLocation().asLocation();
102       DiagnosticBuilder diagBuilder = Diag.Report(L, ErrorDiag);
103 
104       // Get the ranges from the last point in the path.
105       ArrayRef<SourceRange> Ranges = PD->path.back()->getRanges();
106 
107       for (ArrayRef<SourceRange>::iterator I = Ranges.begin(),
108                                            E = Ranges.end(); I != E; ++I) {
109         diagBuilder << *I;
110       }
111     }
112   }
113 };
114 } // end anonymous namespace
115 
116 //===----------------------------------------------------------------------===//
117 // AnalysisConsumer declaration.
118 //===----------------------------------------------------------------------===//
119 
120 namespace {
121 
122 class AnalysisConsumer : public ASTConsumer,
123                          public RecursiveASTVisitor<AnalysisConsumer> {
124   enum AnalysisMode {
125     ANALYSIS_SYNTAX,
126     ANALYSIS_PATH,
127     ANALYSIS_ALL
128   };
129 
130   /// Mode of the analyzes while recursively visiting Decls.
131   AnalysisMode RecVisitorMode;
132   /// Bug Reporter to use while recursively visiting Decls.
133   BugReporter *RecVisitorBR;
134 
135 public:
136   ASTContext *Ctx;
137   const Preprocessor &PP;
138   const std::string OutDir;
139   AnalyzerOptions Opts;
140   ArrayRef<std::string> Plugins;
141 
142   /// \brief Stores the declarations from the local translation unit.
143   /// Note, we pre-compute the local declarations at parse time as an
144   /// optimization to make sure we do not deserialize everything from disk.
145   /// The local declaration to all declarations ratio might be very small when
146   /// working with a PCH file.
147   SetOfDecls LocalTUDecls;
148 
149   // Set of PathDiagnosticConsumers.  Owned by AnalysisManager.
150   PathDiagnosticConsumers PathConsumers;
151 
152   StoreManagerCreator CreateStoreMgr;
153   ConstraintManagerCreator CreateConstraintMgr;
154 
155   OwningPtr<CheckerManager> checkerMgr;
156   OwningPtr<AnalysisManager> Mgr;
157 
158   /// Time the analyzes time of each translation unit.
159   static llvm::Timer* TUTotalTimer;
160 
161   /// The information about analyzed functions shared throughout the
162   /// translation unit.
163   FunctionSummariesTy FunctionSummaries;
164 
165   AnalysisConsumer(const Preprocessor& pp,
166                    const std::string& outdir,
167                    const AnalyzerOptions& opts,
168                    ArrayRef<std::string> plugins)
169     : RecVisitorMode(ANALYSIS_ALL), RecVisitorBR(0),
170       Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins) {
171     DigestAnalyzerOptions();
172     if (Opts.PrintStats) {
173       llvm::EnableStatistics();
174       TUTotalTimer = new llvm::Timer("Analyzer Total Time");
175     }
176   }
177 
178   ~AnalysisConsumer() {
179     if (Opts.PrintStats)
180       delete TUTotalTimer;
181   }
182 
183   void DigestAnalyzerOptions() {
184     // Create the PathDiagnosticConsumer.
185     PathConsumers.push_back(new ClangDiagPathDiagConsumer(PP.getDiagnostics()));
186 
187     if (!OutDir.empty()) {
188       switch (Opts.AnalysisDiagOpt) {
189       default:
190 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
191         case PD_##NAME: CREATEFN(PathConsumers, OutDir, PP); break;
192 #include "clang/Frontend/Analyses.def"
193       }
194     } else if (Opts.AnalysisDiagOpt == PD_TEXT) {
195       // Create the text client even without a specified output file since
196       // it just uses diagnostic notes.
197       createTextPathDiagnosticConsumer(PathConsumers, "", PP);
198     }
199 
200     // Create the analyzer component creators.
201     switch (Opts.AnalysisStoreOpt) {
202     default:
203       llvm_unreachable("Unknown store manager.");
204 #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN)           \
205       case NAME##Model: CreateStoreMgr = CREATEFN; break;
206 #include "clang/Frontend/Analyses.def"
207     }
208 
209     switch (Opts.AnalysisConstraintsOpt) {
210     default:
211       llvm_unreachable("Unknown store manager.");
212 #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN)     \
213       case NAME##Model: CreateConstraintMgr = CREATEFN; break;
214 #include "clang/Frontend/Analyses.def"
215     }
216   }
217 
218   void DisplayFunction(const Decl *D, AnalysisMode Mode) {
219     if (!Opts.AnalyzerDisplayProgress)
220       return;
221 
222     SourceManager &SM = Mgr->getASTContext().getSourceManager();
223     PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
224     if (Loc.isValid()) {
225       llvm::errs() << "ANALYZE";
226       switch (Mode) {
227         case ANALYSIS_SYNTAX: llvm::errs() << "(Syntax)"; break;
228         case ANALYSIS_PATH: llvm::errs() << "(Path Sensitive)"; break;
229         case ANALYSIS_ALL: break;
230       };
231       llvm::errs() << ": " << Loc.getFilename();
232       if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
233         const NamedDecl *ND = cast<NamedDecl>(D);
234         llvm::errs() << ' ' << *ND << '\n';
235       }
236       else if (isa<BlockDecl>(D)) {
237         llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
238                      << Loc.getColumn() << '\n';
239       }
240       else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
241         Selector S = MD->getSelector();
242         llvm::errs() << ' ' << S.getAsString();
243       }
244     }
245   }
246 
247   virtual void Initialize(ASTContext &Context) {
248     Ctx = &Context;
249     checkerMgr.reset(createCheckerManager(Opts, PP.getLangOpts(), Plugins,
250                                           PP.getDiagnostics()));
251     Mgr.reset(new AnalysisManager(*Ctx,
252                                   PP.getDiagnostics(),
253                                   PP.getLangOpts(),
254                                   PathConsumers,
255                                   CreateStoreMgr,
256                                   CreateConstraintMgr,
257                                   checkerMgr.get(),
258                                   Opts.MaxNodes, Opts.MaxLoop,
259                                   Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
260                                   Opts.AnalysisPurgeOpt, Opts.EagerlyAssume,
261                                   Opts.TrimGraph,
262                                   Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
263                                   Opts.EagerlyTrimEGraph,
264                                   Opts.IPAMode,
265                                   Opts.InlineMaxStackDepth,
266                                   Opts.InlineMaxFunctionSize,
267                                   Opts.InliningMode,
268                                   Opts.NoRetryExhausted));
269   }
270 
271   /// \brief Store the top level decls in the set to be processed later on.
272   /// (Doing this pre-processing avoids deserialization of data from PCH.)
273   virtual bool HandleTopLevelDecl(DeclGroupRef D);
274   virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D);
275 
276   virtual void HandleTranslationUnit(ASTContext &C);
277 
278   /// \brief Build the call graph for all the top level decls of this TU and
279   /// use it to define the order in which the functions should be visited.
280   void HandleDeclsGallGraph(const unsigned LocalTUDeclsSize);
281 
282   /// \brief Run analyzes(syntax or path sensitive) on the given function.
283   /// \param Mode - determines if we are requesting syntax only or path
284   /// sensitive only analysis.
285   /// \param VisitedCallees - The output parameter, which is populated with the
286   /// set of functions which should be considered analyzed after analyzing the
287   /// given root function.
288   void HandleCode(Decl *D, AnalysisMode Mode,
289                   SetOfConstDecls *VisitedCallees = 0);
290 
291   void RunPathSensitiveChecks(Decl *D, SetOfConstDecls *VisitedCallees);
292   void ActionExprEngine(Decl *D, bool ObjCGCEnabled,
293                         SetOfConstDecls *VisitedCallees);
294 
295   /// Visitors for the RecursiveASTVisitor.
296   bool shouldWalkTypesOfTypeLocs() const { return false; }
297 
298   /// Handle callbacks for arbitrary Decls.
299   bool VisitDecl(Decl *D) {
300     checkerMgr->runCheckersOnASTDecl(D, *Mgr, *RecVisitorBR);
301     return true;
302   }
303 
304   bool VisitFunctionDecl(FunctionDecl *FD) {
305     IdentifierInfo *II = FD->getIdentifier();
306     if (II && II->getName().startswith("__inline"))
307       return true;
308 
309     // We skip function template definitions, as their semantics is
310     // only determined when they are instantiated.
311     if (FD->isThisDeclarationADefinition() &&
312         !FD->isDependentContext()) {
313       HandleCode(FD, RecVisitorMode);
314     }
315     return true;
316   }
317 
318   bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
319     checkerMgr->runCheckersOnASTDecl(MD, *Mgr, *RecVisitorBR);
320     if (MD->isThisDeclarationADefinition())
321       HandleCode(MD, RecVisitorMode);
322     return true;
323   }
324 
325 private:
326   void storeTopLevelDecls(DeclGroupRef DG);
327 
328   /// \brief Check if we should skip (not analyze) the given function.
329   bool skipFunction(Decl *D);
330 
331 };
332 } // end anonymous namespace
333 
334 
335 //===----------------------------------------------------------------------===//
336 // AnalysisConsumer implementation.
337 //===----------------------------------------------------------------------===//
338 llvm::Timer* AnalysisConsumer::TUTotalTimer = 0;
339 
340 bool AnalysisConsumer::HandleTopLevelDecl(DeclGroupRef DG) {
341   storeTopLevelDecls(DG);
342   return true;
343 }
344 
345 void AnalysisConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
346   storeTopLevelDecls(DG);
347 }
348 
349 void AnalysisConsumer::storeTopLevelDecls(DeclGroupRef DG) {
350   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
351 
352     // Skip ObjCMethodDecl, wait for the objc container to avoid
353     // analyzing twice.
354     if (isa<ObjCMethodDecl>(*I))
355       continue;
356 
357     LocalTUDecls.push_back(*I);
358   }
359 }
360 
361 void AnalysisConsumer::HandleDeclsGallGraph(const unsigned LocalTUDeclsSize) {
362   // Otherwise, use the Callgraph to derive the order.
363   // Build the Call Graph.
364   CallGraph CG;
365 
366   // Add all the top level declarations to the graph.
367   // Note: CallGraph can trigger deserialization of more items from a pch
368   // (though HandleInterestingDecl); triggering additions to LocalTUDecls.
369   // We rely on random access to add the initially processed Decls to CG.
370   for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
371     CG.addToCallGraph(LocalTUDecls[i]);
372   }
373 
374   // Find the top level nodes - children of root + the unreachable (parentless)
375   // nodes.
376   llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions;
377   for (CallGraph::nodes_iterator TI = CG.parentless_begin(),
378                                  TE = CG.parentless_end(); TI != TE; ++TI) {
379     TopLevelFunctions.push_back(*TI);
380     NumFunctionTopLevel++;
381   }
382   CallGraphNode *Entry = CG.getRoot();
383   for (CallGraphNode::iterator I = Entry->begin(),
384                                E = Entry->end(); I != E; ++I) {
385     TopLevelFunctions.push_back(*I);
386     NumFunctionTopLevel++;
387   }
388 
389   // Make sure the nodes are sorted in order reverse of their definition in the
390   // translation unit. This step is very important for performance. It ensures
391   // that we analyze the root functions before the externally available
392   // subroutines.
393   std::deque<CallGraphNode*> BFSQueue;
394   for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator
395          TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend();
396          TI != TE; ++TI)
397     BFSQueue.push_back(*TI);
398 
399   // BFS over all of the functions, while skipping the ones inlined into
400   // the previously processed functions. Use external Visited set, which is
401   // also modified when we inline a function.
402   SmallPtrSet<CallGraphNode*,24> Visited;
403   while(!BFSQueue.empty()) {
404     CallGraphNode *N = BFSQueue.front();
405     BFSQueue.pop_front();
406 
407     // Push the children into the queue.
408     for (CallGraphNode::const_iterator CI = N->begin(),
409          CE = N->end(); CI != CE; ++CI) {
410       if (!Visited.count(*CI))
411         BFSQueue.push_back(*CI);
412     }
413 
414     // Skip the functions which have been processed already or previously
415     // inlined.
416     if (Visited.count(N))
417       continue;
418 
419     // Analyze the function.
420     SetOfConstDecls VisitedCallees;
421     Decl *D = N->getDecl();
422     assert(D);
423     HandleCode(D, ANALYSIS_PATH,
424                (Mgr->InliningMode == All ? 0 : &VisitedCallees));
425 
426     // Add the visited callees to the global visited set.
427     for (SetOfConstDecls::iterator I = VisitedCallees.begin(),
428                                    E = VisitedCallees.end(); I != E; ++I) {
429       CallGraphNode *VN = CG.getNode(*I);
430       if (VN)
431         Visited.insert(VN);
432     }
433     Visited.insert(N);
434   }
435 }
436 
437 void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
438   // Don't run the actions if an error has occurred with parsing the file.
439   DiagnosticsEngine &Diags = PP.getDiagnostics();
440   if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
441     return;
442 
443   {
444     if (TUTotalTimer) TUTotalTimer->startTimer();
445 
446     // Introduce a scope to destroy BR before Mgr.
447     BugReporter BR(*Mgr);
448     TranslationUnitDecl *TU = C.getTranslationUnitDecl();
449     checkerMgr->runCheckersOnASTDecl(TU, *Mgr, BR);
450 
451     // Run the AST-only checks using the order in which functions are defined.
452     // If inlining is not turned on, use the simplest function order for path
453     // sensitive analyzes as well.
454     RecVisitorMode = (Mgr->shouldInlineCall() ? ANALYSIS_SYNTAX : ANALYSIS_ALL);
455     RecVisitorBR = &BR;
456 
457     // Process all the top level declarations.
458     //
459     // Note: TraverseDecl may modify LocalTUDecls, but only by appending more
460     // entries.  Thus we don't use an iterator, but rely on LocalTUDecls
461     // random access.  By doing so, we automatically compensate for iterators
462     // possibly being invalidated, although this is a bit slower.
463     const unsigned LocalTUDeclsSize = LocalTUDecls.size();
464     for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
465       TraverseDecl(LocalTUDecls[i]);
466     }
467 
468     if (Mgr->shouldInlineCall())
469       HandleDeclsGallGraph(LocalTUDeclsSize);
470 
471     // After all decls handled, run checkers on the entire TranslationUnit.
472     checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
473 
474     RecVisitorBR = 0;
475   }
476 
477   // Explicitly destroy the PathDiagnosticConsumer.  This will flush its output.
478   // FIXME: This should be replaced with something that doesn't rely on
479   // side-effects in PathDiagnosticConsumer's destructor. This is required when
480   // used with option -disable-free.
481   Mgr.reset(NULL);
482 
483   if (TUTotalTimer) TUTotalTimer->stopTimer();
484 
485   // Count how many basic blocks we have not covered.
486   NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks();
487   if (NumBlocksInAnalyzedFunctions > 0)
488     PercentReachableBlocks =
489       (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) /
490         NumBlocksInAnalyzedFunctions;
491 
492 }
493 
494 static void FindBlocks(DeclContext *D, SmallVectorImpl<Decl*> &WL) {
495   if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
496     WL.push_back(BD);
497 
498   for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
499        I!=E; ++I)
500     if (DeclContext *DC = dyn_cast<DeclContext>(*I))
501       FindBlocks(DC, WL);
502 }
503 
504 static std::string getFunctionName(const Decl *D) {
505   if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) {
506     return ID->getSelector().getAsString();
507   }
508   if (const FunctionDecl *ND = dyn_cast<FunctionDecl>(D)) {
509     IdentifierInfo *II = ND->getIdentifier();
510     if (II)
511       return II->getName();
512   }
513   return "";
514 }
515 
516 bool AnalysisConsumer::skipFunction(Decl *D) {
517   if (!Opts.AnalyzeSpecificFunction.empty() &&
518       getFunctionName(D) != Opts.AnalyzeSpecificFunction)
519     return true;
520 
521   // Don't run the actions on declarations in header files unless
522   // otherwise specified.
523   SourceManager &SM = Ctx->getSourceManager();
524   SourceLocation SL = SM.getExpansionLoc(D->getLocation());
525   if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))
526     return true;
527 
528   return false;
529 }
530 
531 void AnalysisConsumer::HandleCode(Decl *D, AnalysisMode Mode,
532                                   SetOfConstDecls *VisitedCallees) {
533   if (skipFunction(D))
534     return;
535 
536   DisplayFunction(D, Mode);
537   CFG *DeclCFG = Mgr->getCFG(D);
538   if (DeclCFG) {
539     unsigned CFGSize = DeclCFG->size();
540     MaxCFGSize = MaxCFGSize < CFGSize ? CFGSize : MaxCFGSize;
541   }
542 
543 
544   // Clear the AnalysisManager of old AnalysisDeclContexts.
545   Mgr->ClearContexts();
546 
547   // Dispatch on the actions.
548   SmallVector<Decl*, 10> WL;
549   WL.push_back(D);
550 
551   if (D->hasBody() && Opts.AnalyzeNestedBlocks)
552     FindBlocks(cast<DeclContext>(D), WL);
553 
554   BugReporter BR(*Mgr);
555   for (SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
556        WI != WE; ++WI)
557     if ((*WI)->hasBody()) {
558       if (Mode != ANALYSIS_PATH)
559         checkerMgr->runCheckersOnASTBody(*WI, *Mgr, BR);
560       if (Mode != ANALYSIS_SYNTAX && checkerMgr->hasPathSensitiveCheckers()) {
561         RunPathSensitiveChecks(*WI, VisitedCallees);
562         NumFunctionsAnalyzed++;
563       }
564     }
565 }
566 
567 //===----------------------------------------------------------------------===//
568 // Path-sensitive checking.
569 //===----------------------------------------------------------------------===//
570 
571 void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
572                                         SetOfConstDecls *VisitedCallees) {
573   // Construct the analysis engine.  First check if the CFG is valid.
574   // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
575   if (!Mgr->getCFG(D))
576     return;
577 
578   // See if the LiveVariables analysis scales.
579   if (!Mgr->getAnalysisDeclContext(D)->getAnalysis<RelaxedLiveVariables>())
580     return;
581 
582   ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries);
583 
584   // Set the graph auditor.
585   OwningPtr<ExplodedNode::Auditor> Auditor;
586   if (Mgr->shouldVisualizeUbigraph()) {
587     Auditor.reset(CreateUbiViz());
588     ExplodedNode::SetAuditor(Auditor.get());
589   }
590 
591   // Execute the worklist algorithm.
592   Eng.ExecuteWorkList(Mgr->getAnalysisDeclContextManager().getStackFrame(D),
593                       Mgr->getMaxNodes());
594 
595   // Release the auditor (if any) so that it doesn't monitor the graph
596   // created BugReporter.
597   ExplodedNode::SetAuditor(0);
598 
599   // Visualize the exploded graph.
600   if (Mgr->shouldVisualizeGraphviz())
601     Eng.ViewGraph(Mgr->shouldTrimGraph());
602 
603   // Display warnings.
604   Eng.getBugReporter().FlushReports();
605 }
606 
607 void AnalysisConsumer::RunPathSensitiveChecks(Decl *D,
608                                               SetOfConstDecls *Visited) {
609 
610   switch (Mgr->getLangOpts().getGC()) {
611   case LangOptions::NonGC:
612     ActionExprEngine(D, false, Visited);
613     break;
614 
615   case LangOptions::GCOnly:
616     ActionExprEngine(D, true, Visited);
617     break;
618 
619   case LangOptions::HybridGC:
620     ActionExprEngine(D, false, Visited);
621     ActionExprEngine(D, true, Visited);
622     break;
623   }
624 }
625 
626 //===----------------------------------------------------------------------===//
627 // AnalysisConsumer creation.
628 //===----------------------------------------------------------------------===//
629 
630 ASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,
631                                           const std::string& outDir,
632                                           const AnalyzerOptions& opts,
633                                           ArrayRef<std::string> plugins) {
634   // Disable the effects of '-Werror' when using the AnalysisConsumer.
635   pp.getDiagnostics().setWarningsAsErrors(false);
636 
637   return new AnalysisConsumer(pp, outDir, opts, plugins);
638 }
639 
640 //===----------------------------------------------------------------------===//
641 // Ubigraph Visualization.  FIXME: Move to separate file.
642 //===----------------------------------------------------------------------===//
643 
644 namespace {
645 
646 class UbigraphViz : public ExplodedNode::Auditor {
647   OwningPtr<raw_ostream> Out;
648   llvm::sys::Path Dir, Filename;
649   unsigned Cntr;
650 
651   typedef llvm::DenseMap<void*,unsigned> VMap;
652   VMap M;
653 
654 public:
655   UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
656               llvm::sys::Path& filename);
657 
658   ~UbigraphViz();
659 
660   virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst);
661 };
662 
663 } // end anonymous namespace
664 
665 static ExplodedNode::Auditor* CreateUbiViz() {
666   std::string ErrMsg;
667 
668   llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
669   if (!ErrMsg.empty())
670     return 0;
671 
672   llvm::sys::Path Filename = Dir;
673   Filename.appendComponent("llvm_ubi");
674   Filename.makeUnique(true,&ErrMsg);
675 
676   if (!ErrMsg.empty())
677     return 0;
678 
679   llvm::errs() << "Writing '" << Filename.str() << "'.\n";
680 
681   OwningPtr<llvm::raw_fd_ostream> Stream;
682   Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
683 
684   if (!ErrMsg.empty())
685     return 0;
686 
687   return new UbigraphViz(Stream.take(), Dir, Filename);
688 }
689 
690 void UbigraphViz::AddEdge(ExplodedNode *Src, ExplodedNode *Dst) {
691 
692   assert (Src != Dst && "Self-edges are not allowed.");
693 
694   // Lookup the Src.  If it is a new node, it's a root.
695   VMap::iterator SrcI= M.find(Src);
696   unsigned SrcID;
697 
698   if (SrcI == M.end()) {
699     M[Src] = SrcID = Cntr++;
700     *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
701   }
702   else
703     SrcID = SrcI->second;
704 
705   // Lookup the Dst.
706   VMap::iterator DstI= M.find(Dst);
707   unsigned DstID;
708 
709   if (DstI == M.end()) {
710     M[Dst] = DstID = Cntr++;
711     *Out << "('vertex', " << DstID << ")\n";
712   }
713   else {
714     // We have hit DstID before.  Change its style to reflect a cache hit.
715     DstID = DstI->second;
716     *Out << "('change_vertex_style', " << DstID << ", 1)\n";
717   }
718 
719   // Add the edge.
720   *Out << "('edge', " << SrcID << ", " << DstID
721        << ", ('arrow','true'), ('oriented', 'true'))\n";
722 }
723 
724 UbigraphViz::UbigraphViz(raw_ostream *out, llvm::sys::Path& dir,
725                          llvm::sys::Path& filename)
726   : Out(out), Dir(dir), Filename(filename), Cntr(0) {
727 
728   *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
729   *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
730           " ('size', '1.5'))\n";
731 }
732 
733 UbigraphViz::~UbigraphViz() {
734   Out.reset(0);
735   llvm::errs() << "Running 'ubiviz' program... ";
736   std::string ErrMsg;
737   llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
738   std::vector<const char*> args;
739   args.push_back(Ubiviz.c_str());
740   args.push_back(Filename.c_str());
741   args.push_back(0);
742 
743   if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
744     llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
745   }
746 
747   // Delete the directory.
748   Dir.eraseFromDisk(true);
749 }
750