zcov: / lib/Frontend/AnalysisConsumer.cpp


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


Programs: 1 Runs 2897


       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