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