zcov: / lib/Frontend/PlistDiagnostics.cpp


Files: 1 Branches Taken: 51.6% 49 / 95
Generated: 2010-02-10 01:31 Branches Executed: 77.9% 74 / 95
Line Coverage: 77.5% 172 / 222


Programs: 1 Runs 2897


       1                 : //===--- PlistDiagnostics.cpp - Plist Diagnostics for Paths -----*- 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 PlistDiagnostics object.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "clang/Frontend/PathDiagnosticClients.h"
      15                 : #include "clang/Checker/BugReporter/PathDiagnostic.h"
      16                 : #include "clang/Basic/SourceManager.h"
      17                 : #include "clang/Basic/FileManager.h"
      18                 : #include "clang/Lex/Preprocessor.h"
      19                 : #include "llvm/Support/raw_ostream.h"
      20                 : #include "llvm/Support/Casting.h"
      21                 : #include "llvm/ADT/DenseMap.h"
      22                 : #include "llvm/ADT/SmallVector.h"
      23                 : using namespace clang;
      24                 : using llvm::cast;
      25                 : 
      26                 : typedef llvm::DenseMap<FileID, unsigned> FIDMap;
      27                 : 
      28                 : namespace clang {
      29                 :   class Preprocessor;
      30                 : }
      31                 : 
      32                 : namespace {
      33                 : struct CompareDiagnostics {
      34                 :   // Compare if 'X' is "<" than 'Y'.
      35               10:   bool operator()(const PathDiagnostic *X, const PathDiagnostic *Y) const {
      36                 :     // First compare by location
      37               10:     const FullSourceLoc &XLoc = X->getLocation().asLocation();
      38               10:     const FullSourceLoc &YLoc = Y->getLocation().asLocation();
                        0: branch 1 not taken
                       10: branch 2 taken
      39               10:     if (XLoc < YLoc)
      40                0:       return true;
                       10: branch 1 taken
                        0: branch 2 not taken
      41               10:     if (XLoc != YLoc)
      42               10:       return false;
      43                 :     
      44                 :     // Next, compare by bug type.
      45                0:     llvm::StringRef XBugType = X->getBugType();
      46                0:     llvm::StringRef YBugType = Y->getBugType();
                        0: branch 1 not taken
                        0: branch 2 not taken
      47                0:     if (XBugType < YBugType)
      48                0:       return true;
                        0: branch 1 not taken
                        0: branch 2 not taken
      49                0:     if (XBugType != YBugType)
      50                0:       return false;
      51                 :     
      52                 :     // Next, compare by bug description.
      53                0:     llvm::StringRef XDesc = X->getDescription();
      54                0:     llvm::StringRef YDesc = Y->getDescription();
                        0: branch 1 not taken
                        0: branch 2 not taken
      55                0:     if (XDesc < YDesc)
      56                0:       return true;
                        0: branch 1 not taken
                        0: branch 2 not taken
      57                0:     if (XDesc != YDesc)
      58                0:       return false;
      59                 :     
      60                 :     // FIXME: Further refine by comparing PathDiagnosticPieces?
      61                0:     return false;    
      62                 :   }  
      63                 : };  
      64                 : }
      65                 : 
      66                 : namespace {
      67                 :   class PlistDiagnostics : public PathDiagnosticClient {
      68                 :     std::vector<const PathDiagnostic*> BatchedDiags;
      69                 :     const std::string OutputFile;
      70                 :     const LangOptions &LangOpts;
      71                 :     llvm::OwningPtr<PathDiagnosticClient> SubPD;
      72                 :     bool flushed;
      73                 :   public:
      74                 :     PlistDiagnostics(const std::string& prefix, const LangOptions &LangOpts,
      75                 :                      PathDiagnosticClient *subPD);
      76                 : 
                        1: branch 5 taken
                        0: branch 6 not taken
                        0: branch 13 not taken
                        0: branch 14 not taken
      77                1:     ~PlistDiagnostics() { FlushDiagnostics(NULL); }
      78                 : 
      79                 :     void FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade);
      80                 :     
      81                 :     void HandlePathDiagnostic(const PathDiagnostic* D);
      82                 :     
      83                0:     virtual llvm::StringRef getName() const {
      84                0:       return "PlistDiagnostics";
      85                 :     }
      86                 : 
      87                 :     PathGenerationScheme getGenerationScheme() const;
      88                0:     bool supportsLogicalOpControlFlow() const { return true; }
      89                0:     bool supportsAllBlockEdges() const { return true; }
      90                6:     virtual bool useVerboseDescription() const { return false; }
      91                 :   };
      92                 : } // end anonymous namespace
      93                 : 
      94                 : PlistDiagnostics::PlistDiagnostics(const std::string& output,
      95                 :                                    const LangOptions &LO,
      96                1:                                    PathDiagnosticClient *subPD)
      97                1:   : OutputFile(output), LangOpts(LO), SubPD(subPD), flushed(false) {}
      98                 : 
      99                 : PathDiagnosticClient*
     100                 : clang::CreatePlistDiagnosticClient(const std::string& s, const Preprocessor &PP,
     101                1:                                    PathDiagnosticClient *subPD) {
     102                1:   return new PlistDiagnostics(s, PP.getLangOptions(), subPD);
     103                 : }
     104                 : 
     105                 : PathDiagnosticClient::PathGenerationScheme
     106                6: PlistDiagnostics::getGenerationScheme() const {
                        0: branch 1 not taken
                        6: branch 2 taken
     107                6:   if (const PathDiagnosticClient *PD = SubPD.get())
     108                0:     return PD->getGenerationScheme();
     109                 : 
     110                6:   return Extensive;
     111                 : }
     112                 : 
     113                 : static void AddFID(FIDMap &FIDs, llvm::SmallVectorImpl<FileID> &V,
     114               45:                    const SourceManager* SM, SourceLocation L) {
     115                 : 
     116               45:   FileID FID = SM->getFileID(SM->getInstantiationLoc(L));
     117               45:   FIDMap::iterator I = FIDs.find(FID);
                        1: branch 3 taken
                       44: branch 4 taken
     118               45:   if (I != FIDs.end()) return;
     119                1:   FIDs[FID] = V.size();
     120                1:   V.push_back(FID);
     121                 : }
     122                 : 
     123                 : static unsigned GetFID(const FIDMap& FIDs, const SourceManager &SM,
     124               87:                        SourceLocation L) {
     125               87:   FileID FID = SM.getFileID(SM.getInstantiationLoc(L));
     126               87:   FIDMap::const_iterator I = FIDs.find(FID);
                        0: branch 2 not taken
                       87: branch 3 taken
     127               87:   assert(I != FIDs.end());
     128               87:   return I->second;
     129                 : }
     130                 : 
     131              735: static llvm::raw_ostream& Indent(llvm::raw_ostream& o, const unsigned indent) {
                     5449: branch 1 taken
                      735: branch 2 taken
     132              735:   for (unsigned i = 0; i < indent; ++i) o << ' ';
     133              735:   return o;
     134                 : }
     135                 : 
     136                 : static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
     137                 :                          const LangOptions &LangOpts,
     138                 :                          SourceLocation L, const FIDMap &FM,
     139               87:                          unsigned indent, bool extend = false) {
     140                 : 
     141               87:   FullSourceLoc Loc(SM.getInstantiationLoc(L), const_cast<SourceManager&>(SM));
     142                 : 
     143                 :   // Add in the length of the token, so that we cover multi-char tokens.
     144                 :   unsigned offset =
                       27: branch 0 taken
                       60: branch 1 taken
     145               87:     extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0;
     146                 : 
     147               87:   Indent(o, indent) << "<dict>\n";
     148                 :   Indent(o, indent) << " <key>line</key><integer>"
     149               87:                     << Loc.getInstantiationLineNumber() << "</integer>\n";
     150                 :   Indent(o, indent) << " <key>col</key><integer>"
     151               87:                     << Loc.getInstantiationColumnNumber() + offset << "</integer>\n";
     152                 :   Indent(o, indent) << " <key>file</key><integer>"
     153               87:                     << GetFID(FM, SM, Loc) << "</integer>\n";
     154               87:   Indent(o, indent) << "</dict>\n";
     155               87: }
     156                 : 
     157                 : static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
     158                 :                          const LangOptions &LangOpts,
     159                 :                          const PathDiagnosticLocation &L, const FIDMap& FM,
     160                6:                          unsigned indent, bool extend = false) {
     161                6:   EmitLocation(o, SM, LangOpts, L.asLocation(), FM, indent, extend);
     162                6: }
     163                 : 
     164                 : static void EmitRange(llvm::raw_ostream& o, const SourceManager &SM,
     165                 :                       const LangOptions &LangOpts,
     166                 :                       PathDiagnosticRange R, const FIDMap &FM,
     167               35:                       unsigned indent) {
     168               35:   Indent(o, indent) << "<array>\n";
     169               35:   EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1);
     170               35:   EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, !R.isPoint);
     171               35:   Indent(o, indent) << "</array>\n";
     172               35: }
     173                 : 
     174                 : static llvm::raw_ostream& EmitString(llvm::raw_ostream& o,
     175               41:                                      const std::string& s) {
     176               41:   o << "<string>";
                     1531: branch 4 taken
                       41: branch 5 taken
     177             1572:   for (std::string::const_iterator I=s.begin(), E=s.end(); I!=E; ++I) {
     178             1531:     char c = *I;
                     1489: branch 0 taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                       42: branch 4 taken
                        0: branch 5 not taken
     179             1531:     switch (c) {
     180             1489:     default:   o << c; break;
     181                0:     case '&':  o << "&amp;"; break;
     182                0:     case '<':  o << "&lt;"; break;
     183                0:     case '>':  o << "&gt;"; break;
     184               42:     case '\'': o << "&apos;"; break;
     185                0:     case '\"': o << "&quot;"; break;
     186                 :     }
     187                 :   }
     188               41:   o << "</string>";
     189               41:   return o;
     190                 : }
     191                 : 
     192                 : static void ReportControlFlow(llvm::raw_ostream& o,
     193                 :                               const PathDiagnosticControlFlowPiece& P,
     194                 :                               const FIDMap& FM,
     195                 :                               const SourceManager &SM,
     196                 :                               const LangOptions &LangOpts,
     197               12:                               unsigned indent) {
     198                 : 
     199               12:   Indent(o, indent) << "<dict>\n";
     200               12:   ++indent;
     201                 : 
     202               12:   Indent(o, indent) << "<key>kind</key><string>control</string>\n";
     203                 : 
     204                 :   // Emit edges.
     205               12:   Indent(o, indent) << "<key>edges</key>\n";
     206               12:   ++indent;
     207               12:   Indent(o, indent) << "<array>\n";
     208               12:   ++indent;
                       12: branch 4 taken
                       12: branch 5 taken
     209               24:   for (PathDiagnosticControlFlowPiece::const_iterator I=P.begin(), E=P.end();
     210                 :        I!=E; ++I) {
     211               12:     Indent(o, indent) << "<dict>\n";
     212               12:     ++indent;
     213               12:     Indent(o, indent) << "<key>start</key>\n";
     214               12:     EmitRange(o, SM, LangOpts, I->getStart().asRange(), FM, indent+1);
     215               12:     Indent(o, indent) << "<key>end</key>\n";
     216               12:     EmitRange(o, SM, LangOpts, I->getEnd().asRange(), FM, indent+1);
     217               12:     --indent;
     218               12:     Indent(o, indent) << "</dict>\n";
     219                 :   }
     220               12:   --indent;
     221               12:   Indent(o, indent) << "</array>\n";
     222               12:   --indent;
     223                 : 
     224                 :   // Output any helper text.
     225               12:   const std::string& s = P.getString();
                        0: branch 1 not taken
                       12: branch 2 taken
     226               12:   if (!s.empty()) {
     227                0:     Indent(o, indent) << "<key>alternate</key>";
     228                0:     EmitString(o, s) << '\n';
     229                 :   }
     230                 : 
     231               12:   --indent;
     232               12:   Indent(o, indent) << "</dict>\n";
     233               12: }
     234                 : 
     235                 : static void ReportEvent(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
     236                 :                         const FIDMap& FM,
     237                 :                         const SourceManager &SM,
     238                 :                         const LangOptions &LangOpts,
     239               11:                         unsigned indent) {
     240                 : 
     241               11:   Indent(o, indent) << "<dict>\n";
     242               11:   ++indent;
     243                 : 
     244               11:   Indent(o, indent) << "<key>kind</key><string>event</string>\n";
     245                 : 
     246                 :   // Output the location.
     247               11:   FullSourceLoc L = P.getLocation().asLocation();
     248                 : 
     249               11:   Indent(o, indent) << "<key>location</key>\n";
     250               11:   EmitLocation(o, SM, LangOpts, L, FM, indent);
     251                 : 
     252                 :   // Output the ranges (if any).
     253               11:   PathDiagnosticPiece::range_iterator RI = P.ranges_begin(),
     254               11:   RE = P.ranges_end();
     255                 : 
                       11: branch 0 taken
                        0: branch 1 not taken
     256               11:   if (RI != RE) {
     257               11:     Indent(o, indent) << "<key>ranges</key>\n";
     258               11:     Indent(o, indent) << "<array>\n";
     259               11:     ++indent;
                       11: branch 0 taken
                       11: branch 1 taken
     260               22:     for (; RI != RE; ++RI)
     261               11:       EmitRange(o, SM, LangOpts, *RI, FM, indent+1);
     262               11:     --indent;
     263               11:     Indent(o, indent) << "</array>\n";
     264                 :   }
     265                 : 
     266                 :   // Output the text.
                        0: branch 2 not taken
                       11: branch 3 taken
     267               11:   assert(!P.getString().empty());
     268               11:   Indent(o, indent) << "<key>extended_message</key>\n";
     269               11:   Indent(o, indent);
     270               11:   EmitString(o, P.getString()) << '\n';
     271                 : 
     272                 :   // Output the short text.
     273                 :   // FIXME: Really use a short string.
     274               11:   Indent(o, indent) << "<key>message</key>\n";
     275               11:   EmitString(o, P.getString()) << '\n';
     276                 : 
     277                 :   // Finish up.
     278               11:   --indent;
     279               11:   Indent(o, indent); o << "</dict>\n";
     280               11: }
     281                 : 
     282                 : static void ReportMacro(llvm::raw_ostream& o,
     283                 :                         const PathDiagnosticMacroPiece& P,
     284                 :                         const FIDMap& FM, const SourceManager &SM,
     285                 :                         const LangOptions &LangOpts,
     286                0:                         unsigned indent) {
     287                 : 
                        0: branch 4 not taken
                        0: branch 5 not taken
     288                0:   for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end();
     289                 :        I!=E; ++I) {
     290                 : 
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
     291                0:     switch ((*I)->getKind()) {
     292                 :     default:
     293                0:       break;
     294                 :     case PathDiagnosticPiece::Event:
     295                 :       ReportEvent(o, cast<PathDiagnosticEventPiece>(**I), FM, SM, LangOpts,
     296                0:                   indent);
     297                0:       break;
     298                 :     case PathDiagnosticPiece::Macro:
     299                 :       ReportMacro(o, cast<PathDiagnosticMacroPiece>(**I), FM, SM, LangOpts,
     300                0:                   indent);
     301                 :       break;
     302                 :     }
     303                 :   }
     304                0: }
     305                 : 
     306                 : static void ReportDiag(llvm::raw_ostream& o, const PathDiagnosticPiece& P,
     307                 :                        const FIDMap& FM, const SourceManager &SM,
     308               23:                        const LangOptions &LangOpts) {
     309                 : 
     310               23:   unsigned indent = 4;
     311                 : 
                       12: branch 1 taken
                       11: branch 2 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
     312               23:   switch (P.getKind()) {
     313                 :   case PathDiagnosticPiece::ControlFlow:
     314                 :     ReportControlFlow(o, cast<PathDiagnosticControlFlowPiece>(P), FM, SM,
     315               12:                       LangOpts, indent);
     316               12:     break;
     317                 :   case PathDiagnosticPiece::Event:
     318                 :     ReportEvent(o, cast<PathDiagnosticEventPiece>(P), FM, SM, LangOpts,
     319               11:                 indent);
     320               11:     break;
     321                 :   case PathDiagnosticPiece::Macro:
     322                 :     ReportMacro(o, cast<PathDiagnosticMacroPiece>(P), FM, SM, LangOpts,
     323                0:                 indent);
     324                 :     break;
     325                 :   }
     326               23: }
     327                 : 
     328                6: void PlistDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
                        0: branch 0 not taken
                        6: branch 1 taken
     329                6:   if (!D)
     330                0:     return;
     331                 : 
                        0: branch 1 not taken
                        6: branch 2 taken
     332                6:   if (D->empty()) {
                        0: branch 0 not taken
                        0: branch 1 not taken
     333                0:     delete D;
     334                0:     return;
     335                 :   }
     336                 : 
     337                 :   // We need to flatten the locations (convert Stmt* to locations) because
     338                 :   // the referenced statements may be freed by the time the diagnostics
     339                 :   // are emitted.
     340                6:   const_cast<PathDiagnostic*>(D)->flattenLocations();
     341                6:   BatchedDiags.push_back(D);
     342                 : }
     343                 : 
     344                 : void PlistDiagnostics::FlushDiagnostics(llvm::SmallVectorImpl<std::string>
     345                2:                                         *FilesMade) {
     346                 :   
                        1: branch 0 taken
                        1: branch 1 taken
     347                2:   if (flushed)
     348                1:     return;
     349                 :   
     350                1:   flushed = true;
     351                 :   
     352                 :   // Sort the diagnostics so that they are always emitted in a deterministic
     353                 :   // order.
                        1: branch 1 taken
                        0: branch 2 not taken
     354                1:   if (!BatchedDiags.empty())
     355                1:     std::sort(BatchedDiags.begin(), BatchedDiags.end(), CompareDiagnostics()); 
     356                 : 
     357                 :   // Build up a set of FIDs that we use by scanning the locations and
     358                 :   // ranges of the diagnostics.
     359                1:   FIDMap FM;
     360                1:   llvm::SmallVector<FileID, 10> Fids;
     361                1:   const SourceManager* SM = 0;
     362                 : 
                        1: branch 1 taken
                        0: branch 2 not taken
     363                1:   if (!BatchedDiags.empty())
     364                1:     SM = &(*BatchedDiags.begin())->begin()->getLocation().getManager();
     365                 : 
                        6: branch 3 taken
                        1: branch 4 taken
     366                8:   for (std::vector<const PathDiagnostic*>::iterator DI = BatchedDiags.begin(),
     367                1:        DE = BatchedDiags.end(); DI != DE; ++DI) {
     368                 : 
     369                6:     const PathDiagnostic *D = *DI;
     370                 : 
                       23: branch 4 taken
                        6: branch 5 taken
     371               29:     for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I!=E; ++I) {
     372               23:       AddFID(FM, Fids, SM, I->getLocation().asLocation());
     373                 : 
                       11: branch 2 taken
                       23: branch 3 taken
     374               57:       for (PathDiagnosticPiece::range_iterator RI=I->ranges_begin(),
     375               23:            RE=I->ranges_end(); RI!=RE; ++RI) {
     376               11:         AddFID(FM, Fids, SM, RI->getBegin());
     377               11:         AddFID(FM, Fids, SM, RI->getEnd());
     378                 :       }
     379                 :     }
     380                 :   }
     381                 : 
     382                 :   // Open the file.
     383                1:   std::string ErrMsg;
     384                1:   llvm::raw_fd_ostream o(OutputFile.c_str(), ErrMsg);
                        0: branch 1 not taken
                        1: branch 2 taken
     385                1:   if (!ErrMsg.empty()) {
     386                0:     llvm::errs() << "warning: could not creat file: " << OutputFile << '\n';
     387                0:     return;
     388                 :   }
     389                 : 
     390                 :   // Write the plist header.
     391                 :   o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
     392                 :   "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
     393                 :   "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
     394                1:   "<plist version=\"1.0\">\n";
     395                 : 
     396                 :   // Write the root object: a <dict> containing...
     397                 :   //  - "files", an <array> mapping from FIDs to file names
     398                 :   //  - "diagnostics", an <array> containing the path diagnostics
     399                 :   o << "<dict>\n"
     400                 :        " <key>files</key>\n"
     401                1:        " <array>\n";
     402                 : 
                        1: branch 2 taken
                        1: branch 3 taken
     403                2:   for (llvm::SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end();
     404                 :        I!=E; ++I) {
     405                1:     o << "  ";
     406                1:     EmitString(o, SM->getFileEntryForID(*I)->getName()) << '\n';
     407                 :   }
     408                 : 
     409                 :   o << " </array>\n"
     410                 :        " <key>diagnostics</key>\n"
     411                1:        " <array>\n";
     412                 : 
                        6: branch 4 taken
                        1: branch 5 taken
     413                8:   for (std::vector<const PathDiagnostic*>::iterator DI=BatchedDiags.begin(),
     414                1:        DE = BatchedDiags.end(); DI!=DE; ++DI) {
     415                 : 
     416                 :     o << "  <dict>\n"
     417                6:          "   <key>path</key>\n";
     418                 : 
     419                6:     const PathDiagnostic *D = *DI;
     420                 :     // Create an owning smart pointer for 'D' just so that we auto-free it
     421                 :     // when we exit this method.
     422                6:     llvm::OwningPtr<PathDiagnostic> OwnedD(const_cast<PathDiagnostic*>(D));
     423                 : 
     424                6:     o << "   <array>\n";
     425                 : 
                       23: branch 4 taken
                        6: branch 5 taken
     426               29:     for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I != E; ++I)
     427               23:       ReportDiag(o, *I, FM, *SM, LangOpts);
     428                 : 
     429                6:     o << "   </array>\n";
     430                 : 
     431                 :     // Output the bug type and bug category.
     432                6:     o << "   <key>description</key>";
     433                6:     EmitString(o, D->getDescription()) << '\n';
     434                6:     o << "   <key>category</key>";
     435                6:     EmitString(o, D->getCategory()) << '\n';
     436                6:     o << "   <key>type</key>";
     437                6:     EmitString(o, D->getBugType()) << '\n';
     438                 : 
     439                 :     // Output the location of the bug.
     440                6:     o << "  <key>location</key>\n";
     441                6:     EmitLocation(o, *SM, LangOpts, D->getLocation(), FM, 2);
     442                 : 
     443                 :     // Output the diagnostic to the sub-diagnostic client, if any.
                        0: branch 1 not taken
                        6: branch 2 taken
     444                6:     if (SubPD) {
     445                0:       SubPD->HandlePathDiagnostic(OwnedD.take());
     446                0:       llvm::SmallVector<std::string, 1> SubFilesMade;
     447                0:       SubPD->FlushDiagnostics(SubFilesMade);
     448                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
     449                0:       if (!SubFilesMade.empty()) {
     450                0:         o << "  <key>" << SubPD->getName() << "_files</key>\n";
     451                0:         o << "  <array>\n";
                        0: branch 1 not taken
                        0: branch 2 not taken
     452                0:         for (size_t i = 0, n = SubFilesMade.size(); i < n ; ++i)
     453                0:           o << "   <string>" << SubFilesMade[i] << "</string>\n";
     454                0:         o << "  </array>\n";
     455                0:       }
     456                 :     }
     457                 : 
     458                 :     // Close up the entry.
     459                6:     o << "  </dict>\n";
     460                 :   }
     461                 : 
     462                1:   o << " </array>\n";
     463                 : 
     464                 :   // Finish.
     465                1:   o << "</dict>\n</plist>";
     466                 :   
                        0: branch 0 not taken
                        1: branch 1 taken
     467                1:   if (FilesMade)
     468                0:     FilesMade->push_back(OutputFile);
     469                 :   
                        1: branch 2 taken
                        0: branch 3 not taken
                        1: branch 5 taken
                        0: branch 6 not taken
                        1: branch 8 taken
                        0: branch 9 not taken
                        1: branch 11 taken
                        0: branch 12 not taken
     470                1:   BatchedDiags.clear();
     471                 : }

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