zcov: / lib/Checker/PathDiagnostic.cpp


Files: 1 Branches Taken: 30.2% 35 / 116
Generated: 2010-02-10 01:31 Branches Executed: 44.0% 51 / 116
Line Coverage: 60.8% 87 / 143


Programs: 1 Runs 2897


       1                 : //===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- C++ -*-===//
       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                 : //  This file defines the PathDiagnostic-related interfaces.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "clang/Checker/BugReporter/PathDiagnostic.h"
      15                 : #include "clang/AST/Expr.h"
      16                 : #include "clang/AST/Decl.h"
      17                 : #include "clang/AST/DeclObjC.h"
      18                 : #include "clang/AST/StmtCXX.h"
      19                 : #include "llvm/ADT/SmallString.h"
      20                 : #include "llvm/Support/Casting.h"
      21                 : 
      22                 : using namespace clang;
      23                 : using llvm::dyn_cast;
      24                 : using llvm::isa;
      25                 : 
      26                0: bool PathDiagnosticMacroPiece::containsEvent() const {
                        0: branch 4 not taken
                        0: branch 5 not taken
      27                0:   for (const_iterator I = begin(), E = end(); I!=E; ++I) {
                        0: branch 2 not taken
                        0: branch 3 not taken
      28                0:     if (isa<PathDiagnosticEventPiece>(*I))
      29                0:       return true;
      30                 : 
                        0: branch 2 not taken
                        0: branch 3 not taken
      31                0:     if (PathDiagnosticMacroPiece *MP = dyn_cast<PathDiagnosticMacroPiece>(*I))
                        0: branch 1 not taken
                        0: branch 2 not taken
      32                0:       if (MP->containsEvent())
      33                0:         return true;
      34                 :   }
      35                 : 
      36                0:   return false;
      37                 : }
      38                 : 
      39             3424: static llvm::StringRef StripTrailingDots(llvm::StringRef s) {
                     3993: branch 1 taken
                        1: branch 2 taken
      40             3994:   for (llvm::StringRef::size_type i = s.size(); i != 0; --i)
                     3423: branch 1 taken
                      570: branch 2 taken
      41             3993:     if (s[i - 1] != '.')
      42             3423:       return s.substr(0, i);
      43                1:   return "";
      44                 : }
      45                 : 
      46                 : PathDiagnosticPiece::PathDiagnosticPiece(llvm::StringRef s,
      47             1246:                                          Kind k, DisplayHint hint)
      48             1246:   : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
      49                 : 
      50             1479: PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
      51             1479:   : kind(k), Hint(hint) {}
      52                 : 
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 9 not taken
                        0: branch 10 not taken
                        0: branch 15 not taken
                     2725: branch 16 taken
      53             2725: PathDiagnosticPiece::~PathDiagnosticPiece() {}
                     1244: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        0: branch 9 not taken
                        0: branch 10 not taken
      54             1244: PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {}
                     1481: branch 2 taken
                        0: branch 3 not taken
                        0: branch 7 not taken
                        0: branch 8 not taken
                        0: branch 12 not taken
                        0: branch 13 not taken
      55             1481: PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {}
      56                 : 
      57                0: PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 8 not taken
                        0: branch 9 not taken
                        0: branch 13 not taken
                        0: branch 14 not taken
                        0: branch 18 not taken
                        0: branch 19 not taken
                        0: branch 23 not taken
                        0: branch 24 not taken
                        0: branch 28 not taken
                        0: branch 29 not taken
      58                0:   for (iterator I = begin(), E = end(); I != E; ++I) delete *I;
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 7 not taken
                        0: branch 8 not taken
                        0: branch 12 not taken
                        0: branch 13 not taken
      59                0: }
      60                 : 
      61                0: PathDiagnostic::PathDiagnostic() : Size(0) {}
      62                 : 
      63              726: PathDiagnostic::~PathDiagnostic() {
                     2725: branch 3 taken
                        0: branch 4 not taken
                     2725: branch 8 taken
                      726: branch 9 taken
                        0: branch 13 not taken
                        0: branch 14 not taken
                        0: branch 18 not taken
                        0: branch 19 not taken
      64              726:   for (iterator I = begin(), E = end(); I != E; ++I) delete &*I;
      65              726: }
      66                 : 
      67                1: void PathDiagnostic::resetPath(bool deletePieces) {
      68                1:   Size = 0;
      69                 : 
                        0: branch 0 not taken
                        1: branch 1 taken
      70                1:   if (deletePieces)
                        0: branch 4 not taken
                        0: branch 5 not taken
      71                0:     for (iterator I=begin(), E=end(); I!=E; ++I)
                        0: branch 1 not taken
                        0: branch 2 not taken
      72                0:       delete &*I;
      73                 : 
      74                1:   path.clear();
      75                1: }
      76                 : 
      77                 : 
      78                 : PathDiagnostic::PathDiagnostic(llvm::StringRef bugtype, llvm::StringRef desc,
      79              726:                                llvm::StringRef category)
      80                 :   : Size(0),
      81                 :     BugType(StripTrailingDots(bugtype)),
      82                 :     Desc(StripTrailingDots(desc)),
      83              726:     Category(StripTrailingDots(category)) {}
      84                 : 
      85                 : void PathDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
      86                0:                                             const DiagnosticInfo &Info) {
      87                 : 
      88                 :   // Create a PathDiagnostic with a single piece.
      89                 : 
      90                0:   PathDiagnostic* D = new PathDiagnostic();
      91                 : 
      92                 :   const char *LevelStr;
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
      93                0:   switch (DiagLevel) {
      94                 :   default:
      95                0:   case Diagnostic::Ignored: assert(0 && "Invalid diagnostic type");
      96                0:   case Diagnostic::Note:    LevelStr = "note: "; break;
      97                0:   case Diagnostic::Warning: LevelStr = "warning: "; break;
      98                0:   case Diagnostic::Error:   LevelStr = "error: "; break;
      99                0:   case Diagnostic::Fatal:   LevelStr = "fatal error: "; break;
     100                 :   }
     101                 : 
     102                0:   llvm::SmallString<100> StrC;
     103                0:   StrC += LevelStr;
     104                0:   Info.FormatDiagnostic(StrC);
     105                 : 
     106                 :   PathDiagnosticPiece *P =
     107                0:     new PathDiagnosticEventPiece(Info.getLocation(), StrC.str());
     108                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
     109                0:   for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
     110                0:     P->addRange(Info.getRange(i));
                        0: branch 1 not taken
                        0: branch 2 not taken
     111                0:   for (unsigned i = 0, e = Info.getNumCodeModificationHints(); i != e; ++i)
     112                0:     P->addCodeModificationHint(Info.getCodeModificationHint(i));
     113                0:   D->push_front(P);
     114                 : 
     115                0:   HandlePathDiagnostic(D);
     116                0: }
     117                 : 
     118                 : //===----------------------------------------------------------------------===//
     119                 : // PathDiagnosticLocation methods.
     120                 : //===----------------------------------------------------------------------===//
     121                 : 
     122            12611: FullSourceLoc PathDiagnosticLocation::asLocation() const {
                        0: branch 1 not taken
                    12611: branch 2 taken
     123            12611:   assert(isValid());
     124                 :   // Note that we want a 'switch' here so that the compiler can warn us in
     125                 :   // case we add more cases.
                     4912: branch 0 taken
                     7699: branch 1 taken
                        0: branch 2 not taken
                        0: branch 3 not taken
     126            12611:   switch (K) {
     127                 :     case SingleLocK:
     128                 :     case RangeK:
     129             4912:       break;
     130                 :     case StmtK:
     131             7699:       return FullSourceLoc(S->getLocStart(), const_cast<SourceManager&>(*SM));
     132                 :     case DeclK:
     133                0:       return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
     134                 :   }
     135                 : 
     136             4912:   return FullSourceLoc(R.getBegin(), const_cast<SourceManager&>(*SM));
     137                 : }
     138                 : 
     139             1004: PathDiagnosticRange PathDiagnosticLocation::asRange() const {
                        0: branch 1 not taken
                     1004: branch 2 taken
     140             1004:   assert(isValid());
     141                 :   // Note that we want a 'switch' here so that the compiler can warn us in
     142                 :   // case we add more cases.
                        8: branch 0 taken
                      198: branch 1 taken
                      798: branch 2 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
     143             1004:   switch (K) {
     144                 :     case SingleLocK:
     145                8:       return PathDiagnosticRange(R, true);
     146                 :     case RangeK:
     147              198:       break;
     148                 :     case StmtK: {
     149              798:       const Stmt *S = asStmt();
                      631: branch 1 taken
                      166: branch 2 taken
                        1: branch 3 taken
     150              798:       switch (S->getStmtClass()) {
     151                 :         default:
     152              631:           break;
     153                 :         case Stmt::DeclStmtClass: {
     154              166:           const DeclStmt *DS = cast<DeclStmt>(S);
                      166: branch 1 taken
                        0: branch 2 not taken
     155              166:           if (DS->isSingleDecl()) {
     156                 :             // Should always be the case, but we'll be defensive.
     157                 :             return SourceRange(DS->getLocStart(),
     158              166:                                DS->getSingleDecl()->getLocation());
     159                 :           }
     160                0:           break;
     161                 :         }
     162                 :           // FIXME: Provide better range information for different
     163                 :           //  terminators.
     164                 :         case Stmt::IfStmtClass:
     165                 :         case Stmt::WhileStmtClass:
     166                 :         case Stmt::DoStmtClass:
     167                 :         case Stmt::ForStmtClass:
     168                 :         case Stmt::ChooseExprClass:
     169                 :         case Stmt::IndirectGotoStmtClass:
     170                 :         case Stmt::SwitchStmtClass:
     171                 :         case Stmt::ConditionalOperatorClass:
     172                 :         case Stmt::ObjCForCollectionStmtClass: {
     173                1:           SourceLocation L = S->getLocStart();
     174                1:           return SourceRange(L, L);
     175                 :         }
     176                 :       }
     177                 : 
     178              631:       return S->getSourceRange();
     179                 :     }
     180                 :     case DeclK:
                        0: branch 1 not taken
                        0: branch 2 not taken
     181                0:       if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
     182                0:         return MD->getSourceRange();
                        0: branch 1 not taken
                        0: branch 2 not taken
     183                0:       if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     184                 :         // FIXME: We would like to always get the function body, even
     185                 :         // when it needs to be de-serialized, but getting the
     186                 :         // ASTContext here requires significant changes.
                        0: branch 1 not taken
                        0: branch 2 not taken
     187                0:         if (Stmt *Body = FD->getBody()) {
                        0: branch 1 not taken
                        0: branch 2 not taken
     188                0:           if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
     189                0:             return CS->getSourceRange();
     190                 :           else
     191                0:             return cast<CXXTryStmt>(Body)->getSourceRange();
     192                 :         }
     193                 :       }
     194                 :       else {
     195                0:         SourceLocation L = D->getLocation();
     196                0:         return PathDiagnosticRange(SourceRange(L, L), true);
     197                 :       }
     198                 :   }
     199                 : 
     200              198:   return R;
     201                 : }
     202                 : 
     203               41: void PathDiagnosticLocation::flatten() {
                       30: branch 0 taken
                       11: branch 1 taken
     204               41:   if (K == StmtK) {
     205               30:     R = asRange();
     206               30:     K = RangeK;
     207               30:     S = 0;
     208               30:     D = 0;
     209                 :   }
                        0: branch 0 not taken
                       11: branch 1 taken
     210               11:   else if (K == DeclK) {
     211                0:     SourceLocation L = D->getLocation();
     212                0:     R = SourceRange(L, L);
     213                0:     K = SingleLocK;
     214                0:     S = 0;
     215                0:     D = 0;
     216                 :   }
     217               41: }
     218                 : 
     219                 : //===----------------------------------------------------------------------===//
     220                 : // FoldingSet profiling methods.
     221                 : //===----------------------------------------------------------------------===//
     222                 : 
     223             4206: void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
     224             4206:   ID.AddInteger((unsigned) K);
                      393: branch 0 taken
                     1304: branch 1 taken
                     2509: branch 2 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
     225             4206:   switch (K) {
     226                 :     case RangeK:
     227              393:       ID.AddInteger(R.getBegin().getRawEncoding());
     228              393:       ID.AddInteger(R.getEnd().getRawEncoding());
     229              393:       break;      
     230                 :     case SingleLocK:
     231             1304:       ID.AddInteger(R.getBegin().getRawEncoding());
     232             1304:       break;
     233                 :     case StmtK:
     234             2509:       ID.Add(S);
     235             2509:       break;
     236                 :     case DeclK:
     237                0:       ID.Add(D);
     238                 :       break;
     239                 :   }
     240                 :   return;
     241                 : }
     242                 : 
     243             2725: void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
     244             2725:   ID.AddInteger((unsigned) getKind());
     245             2725:   ID.AddString(str);
     246                 :   // FIXME: Add profiling support for code hints.
     247             2725:   ID.AddInteger((unsigned) getDisplayHint());
                     1479: branch 2 taken
                     2725: branch 3 taken
     248             4204:   for (range_iterator I = ranges_begin(), E = ranges_end(); I != E; ++I) {
     249             1479:     ID.AddInteger(I->getBegin().getRawEncoding());
     250             1479:     ID.AddInteger(I->getEnd().getRawEncoding());
     251                 :   }  
     252             2725: }
     253                 : 
     254             1244: void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
     255             1244:   PathDiagnosticPiece::Profile(ID);
     256             1244:   ID.Add(Pos);
     257             1244: }
     258                 : 
     259             1481: void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
     260             1481:   PathDiagnosticPiece::Profile(ID);
                     1481: branch 4 taken
                     1481: branch 5 taken
     261             2962:   for (const_iterator I = begin(), E = end(); I != E; ++I)
     262             1481:     ID.Add(*I);
     263             1481: }
     264                 : 
     265                0: void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
     266                0:   PathDiagnosticSpotPiece::Profile(ID);
                        0: branch 4 not taken
                        0: branch 5 not taken
     267                0:   for (const_iterator I = begin(), E = end(); I != E; ++I)
     268                0:     ID.Add(**I);
     269                0: }
     270                 : 
     271              726: void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
     272              726:   ID.AddInteger(Size);
     273              726:   ID.AddString(BugType);
     274              726:   ID.AddString(Desc);
     275              726:   ID.AddString(Category);
                     2725: branch 4 taken
                      726: branch 5 taken
     276             3451:   for (const_iterator I = begin(), E = end(); I != E; ++I)
     277             2725:     ID.Add(*I);
     278                 :   
                        0: branch 4 not taken
                      726: branch 5 taken
     279              726:   for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
     280                0:     ID.AddString(*I);
     281              726: }

Generated: 2010-02-10 01:31 by zcov