zcov: / lib/Basic/Diagnostic.cpp


Files: 1 Branches Taken: 71.3% 328 / 460
Generated: 2010-02-10 01:31 Branches Executed: 92.6% 426 / 460
Line Coverage: 88.2% 439 / 498


Programs: 2 Runs 3018


       1                 : //===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===//
       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 implements the Diagnostic-related interfaces.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "clang/Basic/Diagnostic.h"
      15                 : 
      16                 : #include "clang/Lex/LexDiagnostic.h"
      17                 : #include "clang/Parse/ParseDiagnostic.h"
      18                 : #include "clang/AST/ASTDiagnostic.h"
      19                 : #include "clang/Sema/SemaDiagnostic.h"
      20                 : #include "clang/Frontend/FrontendDiagnostic.h"
      21                 : #include "clang/Analysis/AnalysisDiagnostic.h"
      22                 : #include "clang/Driver/DriverDiagnostic.h"
      23                 : 
      24                 : #include "clang/Basic/FileManager.h"
      25                 : #include "clang/Basic/IdentifierTable.h"
      26                 : #include "clang/Basic/SourceLocation.h"
      27                 : #include "clang/Basic/SourceManager.h"
      28                 : #include "llvm/ADT/SmallVector.h"
      29                 : #include "llvm/ADT/StringExtras.h"
      30                 : #include "llvm/Support/raw_ostream.h"
      31                 : #include <vector>
      32                 : #include <map>
      33                 : #include <cstring>
      34                 : using namespace clang;
      35                 : 
      36                 : //===----------------------------------------------------------------------===//
      37                 : // Builtin Diagnostic information
      38                 : //===----------------------------------------------------------------------===//
      39                 : 
      40                 : // Diagnostic classes.
      41                 : enum {
      42                 :   CLASS_NOTE       = 0x01,
      43                 :   CLASS_WARNING    = 0x02,
      44                 :   CLASS_EXTENSION  = 0x03,
      45                 :   CLASS_ERROR      = 0x04
      46                 : };
      47                 : 
      48                 : struct StaticDiagInfoRec {
      49                 :   unsigned short DiagID;
      50                 :   unsigned Mapping : 3;
      51                 :   unsigned Class : 3;
      52                 :   bool SFINAE : 1;
      53                 :   const char *Description;
      54                 :   const char *OptionGroup;
      55                 : 
      56          5244417:   bool operator<(const StaticDiagInfoRec &RHS) const {
      57          5244417:     return DiagID < RHS.DiagID;
      58                 :   }
      59                 :   bool operator>(const StaticDiagInfoRec &RHS) const {
      60                 :     return DiagID > RHS.DiagID;
      61                 :   }
      62                 : };
      63                 : 
      64                 : static const StaticDiagInfoRec StaticDiagInfo[] = {
      65                 : #define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE)    \
      66                 :   { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, DESC, GROUP },
      67                 : #include "clang/Basic/DiagnosticCommonKinds.inc"
      68                 : #include "clang/Basic/DiagnosticDriverKinds.inc"
      69                 : #include "clang/Basic/DiagnosticFrontendKinds.inc"
      70                 : #include "clang/Basic/DiagnosticLexKinds.inc"
      71                 : #include "clang/Basic/DiagnosticParseKinds.inc"
      72                 : #include "clang/Basic/DiagnosticASTKinds.inc"
      73                 : #include "clang/Basic/DiagnosticSemaKinds.inc"
      74                 : #include "clang/Basic/DiagnosticAnalysisKinds.inc"
      75                 :   { 0, 0, 0, 0, 0, 0}
      76                 : };
      77                 : #undef DIAG
      78                 : 
      79                 : /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
      80                 : /// or null if the ID is invalid.
      81            96714: static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
      82            96714:   unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
      83                 : 
      84                 :   // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
      85                 : #ifndef NDEBUG
      86                 :   static bool IsFirst = true;
                     2570: branch 0 taken
                    94144: branch 1 taken
      87            96714:   if (IsFirst) {
                  4227650: branch 0 taken
                     2570: branch 1 taken
      88          8460440:     for (unsigned i = 1; i != NumDiagEntries; ++i) {
      89                 :       assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
      90                 :              "Diag ID conflict, the enums at the start of clang::diag (in "
                        0: branch 0 not taken
                  4227650: branch 1 taken
      91          4227650:              "Diagnostic.h) probably need to be increased");
      92                 : 
      93                 :       assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
                  4227650: branch 1 taken
                        0: branch 2 not taken
      94          4227650:              "Improperly sorted diag info");
      95                 :     }
      96             2570:     IsFirst = false;
      97                 :   }
      98                 : #endif
      99                 : 
     100                 :   // Search the diagnostic table with a binary search.
     101            96714:   StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0 };
     102                 : 
     103                 :   const StaticDiagInfoRec *Found =
     104            96714:     std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
                    95957: branch 0 taken
                      757: branch 1 taken
                        0: branch 2 not taken
                    95957: branch 3 taken
     105            96714:   if (Found == StaticDiagInfo + NumDiagEntries ||
     106                 :       Found->DiagID != DiagID)
     107              757:     return 0;
     108                 : 
     109            95957:   return Found;
     110                 : }
     111                 : 
     112            12965: static unsigned GetDefaultDiagMapping(unsigned DiagID) {
                    12965: branch 1 taken
                        0: branch 2 not taken
     113            12965:   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
     114            12965:     return Info->Mapping;
     115                0:   return diag::MAP_FATAL;
     116                 : }
     117                 : 
     118                 : /// getWarningOptionForDiag - Return the lowest-level warning option that
     119                 : /// enables the specified diagnostic.  If there is no -Wfoo flag that controls
     120                 : /// the diagnostic, this returns null.
     121               18: const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) {
                       18: branch 1 taken
                        0: branch 2 not taken
     122               18:   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
     123               18:     return Info->OptionGroup;
     124                0:   return 0;
     125                 : }
     126                 : 
     127               44: bool Diagnostic::isBuiltinSFINAEDiag(unsigned DiagID) {
                       44: branch 1 taken
                        0: branch 2 not taken
     128               44:   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
                       44: branch 0 taken
                        0: branch 1 not taken
                       24: branch 2 taken
                       20: branch 3 taken
     129               44:     return Info->SFINAE && Info->Class == CLASS_ERROR;
     130                0:   return false;
     131                 : }
     132                 : 
     133                 : /// getDiagClass - Return the class field of the diagnostic.
     134                 : ///
     135            75669: static unsigned getBuiltinDiagClass(unsigned DiagID) {
                    75669: branch 1 taken
                        0: branch 2 not taken
     136            75669:   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
     137            75669:     return Info->Class;
     138                0:   return ~0U;
     139                 : }
     140                 : 
     141                 : //===----------------------------------------------------------------------===//
     142                 : // Custom Diagnostic information
     143                 : //===----------------------------------------------------------------------===//
     144                 : 
     145                 : namespace clang {
     146                 :   namespace diag {
     147              356:     class CustomDiagInfo {
     148                 :       typedef std::pair<Diagnostic::Level, std::string> DiagDesc;
     149                 :       std::vector<DiagDesc> DiagInfo;
     150                 :       std::map<DiagDesc, unsigned> DiagIDs;
     151                 :     public:
     152                 : 
     153                 :       /// getDescription - Return the description of the specified custom
     154                 :       /// diagnostic.
     155              757:       const char *getDescription(unsigned DiagID) const {
     156                 :         assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
                      757: branch 0 taken
                        0: branch 1 not taken
                      757: branch 3 taken
                        0: branch 4 not taken
     157              757:                "Invalid diagnosic ID");
     158              757:         return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str();
     159                 :       }
     160                 : 
     161                 :       /// getLevel - Return the level of the specified custom diagnostic.
     162              757:       Diagnostic::Level getLevel(unsigned DiagID) const {
     163                 :         assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
                      757: branch 0 taken
                        0: branch 1 not taken
                      757: branch 3 taken
                        0: branch 4 not taken
     164              757:                "Invalid diagnosic ID");
     165              757:         return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
     166                 :       }
     167                 : 
     168                 :       unsigned getOrCreateDiagID(Diagnostic::Level L, llvm::StringRef Message,
     169              858:                                  Diagnostic &Diags) {
     170              858:         DiagDesc D(L, Message);
     171                 :         // Check to see if it already exists.
     172              858:         std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
                      536: branch 2 taken
                      322: branch 3 taken
                      164: branch 6 taken
                      372: branch 7 taken
                      164: branch 8 taken
                      694: branch 9 taken
     173              858:         if (I != DiagIDs.end() && I->first == D)
     174              164:           return I->second;
     175                 : 
     176                 :         // If not, assign a new ID.
     177              694:         unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
     178              694:         DiagIDs.insert(std::make_pair(D, ID));
     179              694:         DiagInfo.push_back(D);
     180              694:         return ID;
     181                 :       }
     182                 :     };
     183                 : 
     184                 :   } // end diag namespace
     185                 : } // end clang namespace
     186                 : 
     187                 : 
     188                 : //===----------------------------------------------------------------------===//
     189                 : // Common Diagnostic implementation
     190                 : //===----------------------------------------------------------------------===//
     191                 : 
     192                 : static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
     193                 :                                const char *Modifier, unsigned ML,
     194                 :                                const char *Argument, unsigned ArgLen,
     195                 :                                const Diagnostic::ArgumentValue *PrevArgs,
     196                 :                                unsigned NumPrevArgs,
     197                 :                                llvm::SmallVectorImpl<char> &Output,
     198                0:                                void *Cookie) {
     199                0:   const char *Str = "<can't format argument>";
     200                0:   Output.append(Str, Str+strlen(Str));
     201                0: }
     202                 : 
     203                 : 
                    53420: branch 3 taken
                     5342: branch 4 taken
                    53420: branch 6 taken
                     5342: branch 7 taken
                    16026: branch 9 taken
                     5342: branch 10 taken
                        0: branch 14 not taken
                        0: branch 15 not taken
                        0: branch 17 not taken
                        0: branch 18 not taken
                        0: branch 20 not taken
                        0: branch 21 not taken
     204             5342: Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
     205             5342:   AllExtensionsSilenced = 0;
     206             5342:   IgnoreAllWarnings = false;
     207             5342:   WarningsAsErrors = false;
     208             5342:   ErrorsAsFatal = false;
     209             5342:   SuppressSystemWarnings = false;
     210             5342:   SuppressAllDiagnostics = false;
     211             5342:   ExtBehavior = Ext_Ignore;
     212                 : 
     213             5342:   ErrorOccurred = false;
     214             5342:   FatalErrorOccurred = false;
     215             5342:   NumDiagnostics = 0;
     216                 :   
     217             5342:   NumErrors = 0;
     218             5342:   CustomDiagInfo = 0;
     219             5342:   CurDiagID = ~0U;
     220             5342:   LastDiagLevel = Ignored;
     221                 : 
     222             5342:   ArgToStringFn = DummyArgToStringFn;
     223             5342:   ArgToStringCookie = 0;
     224                 : 
     225                 :   // Set all mappings to 'unset'.
     226             5342:   DiagMappings BlankDiags(diag::DIAG_UPPER_LIMIT/2, 0);
     227             5342:   DiagMappingsStack.push_back(BlankDiags);
     228             5342: }
     229                 : 
     230             5342: Diagnostic::~Diagnostic() {
                      178: branch 0 taken
                     5164: branch 1 taken
                      178: branch 4 taken
                      178: branch 5 taken
     231             5342:   delete CustomDiagInfo;
                     5342: branch 0 taken
                        0: branch 1 not taken
                    16026: branch 2 taken
                     5342: branch 3 taken
                     5342: branch 5 taken
                        0: branch 6 not taken
                    53420: branch 7 taken
                     5342: branch 8 taken
                     5342: branch 11 taken
                     5342: branch 12 taken
                     5342: branch 13 taken
                     5342: branch 14 taken
                        0: branch 16 not taken
                        0: branch 17 not taken
                        0: branch 18 not taken
                        0: branch 19 not taken
     232             5342: }
     233                 : 
     234                 : 
     235                1: void Diagnostic::pushMappings() {
     236                 :   // Avoids undefined behavior when the stack has to resize.
     237                1:   DiagMappingsStack.reserve(DiagMappingsStack.size() + 1);
     238                1:   DiagMappingsStack.push_back(DiagMappingsStack.back());
     239                1: }
     240                 : 
     241                3: bool Diagnostic::popMappings() {
                        2: branch 1 taken
                        1: branch 2 taken
     242                3:   if (DiagMappingsStack.size() == 1)
     243                2:     return false;
     244                 : 
     245                1:   DiagMappingsStack.pop_back();
     246                1:   return true;
     247                 : }
     248                 : 
     249                 : /// getCustomDiagID - Return an ID for a diagnostic with the specified message
     250                 : /// and level.  If this is the first request for this diagnosic, it is
     251                 : /// registered and created, otherwise the existing ID is returned.
     252              858: unsigned Diagnostic::getCustomDiagID(Level L, llvm::StringRef Message) {
                      178: branch 0 taken
                      680: branch 1 taken
     253              858:   if (CustomDiagInfo == 0)
     254              178:     CustomDiagInfo = new diag::CustomDiagInfo();
     255              858:   return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
     256                 : }
     257                 : 
     258                 : 
     259                 : /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
     260                 : /// level of the specified diagnostic ID is a Warning or Extension.
     261                 : /// This only works on builtin diagnostics, not custom ones, and is not legal to
     262                 : /// call on NOTEs.
     263              698: bool Diagnostic::isBuiltinWarningOrExtension(unsigned DiagID) {
     264                 :   return DiagID < diag::DIAG_UPPER_LIMIT &&
                      698: branch 0 taken
                        0: branch 1 not taken
                      698: branch 3 taken
                        0: branch 4 not taken
     265              698:          getBuiltinDiagClass(DiagID) != CLASS_ERROR;
     266                 : }
     267                 : 
     268                 : /// \brief Determine whether the given built-in diagnostic ID is a
     269                 : /// Note.
     270             6225: bool Diagnostic::isBuiltinNote(unsigned DiagID) {
     271                 :   return DiagID < diag::DIAG_UPPER_LIMIT &&
                     6225: branch 0 taken
                        0: branch 1 not taken
                     1690: branch 3 taken
                     4535: branch 4 taken
     272             6225:     getBuiltinDiagClass(DiagID) == CLASS_NOTE;
     273                 : }
     274                 : 
     275                 : /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
     276                 : /// ID is for an extension of some sort.
     277                 : ///
     278            25265: bool Diagnostic::isBuiltinExtensionDiag(unsigned DiagID) {
     279                 :   return DiagID < diag::DIAG_UPPER_LIMIT &&
                    25265: branch 0 taken
                        0: branch 1 not taken
                     1615: branch 3 taken
                    23650: branch 4 taken
     280            25265:          getBuiltinDiagClass(DiagID) == CLASS_EXTENSION;
     281                 : }
     282                 : 
     283                 : 
     284                 : /// getDescription - Given a diagnostic ID, return a description of the
     285                 : /// issue.
     286             8018: const char *Diagnostic::getDescription(unsigned DiagID) const {
                     7261: branch 1 taken
                      757: branch 2 taken
     287             8018:   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
     288             7261:     return Info->Description;
     289              757:   return CustomDiagInfo->getDescription(DiagID);
     290                 : }
     291                 : 
     292                 : /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
     293                 : /// object, classify the specified diagnostic ID into a Level, consumable by
     294                 : /// the DiagnosticClient.
     295            25720: Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
     296                 :   // Handle custom diagnostics, which cannot be mapped.
                        0: branch 0 not taken
                    25720: branch 1 taken
     297            25720:   if (DiagID >= diag::DIAG_UPPER_LIMIT)
     298                0:     return CustomDiagInfo->getLevel(DiagID);
     299                 : 
     300            25720:   unsigned DiagClass = getBuiltinDiagClass(DiagID);
                        0: branch 0 not taken
                    25720: branch 1 taken
     301            25720:   assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
     302            25720:   return getDiagnosticLevel(DiagID, DiagClass);
     303                 : }
     304                 : 
     305                 : /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
     306                 : /// object, classify the specified diagnostic ID into a Level, consumable by
     307                 : /// the DiagnosticClient.
     308                 : Diagnostic::Level
     309            41421: Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
     310                 :   // Specific non-error diagnostics may be mapped to various levels from ignored
     311                 :   // to error.  Errors can only be mapped to fatal.
     312            41421:   Diagnostic::Level Result = Diagnostic::Fatal;
     313                 : 
     314                 :   // Get the mapping information, if unset, compute it lazily.
     315            41421:   unsigned MappingInfo = getDiagnosticMappingInfo((diag::kind)DiagID);
                    12965: branch 0 taken
                    28456: branch 1 taken
     316            41421:   if (MappingInfo == 0) {
     317            12965:     MappingInfo = GetDefaultDiagMapping(DiagID);
     318            12965:     setDiagnosticMappingInternal(DiagID, MappingInfo, false);
     319                 :   }
     320                 : 
                        0: branch 0 not taken
                    25237: branch 1 taken
                     3220: branch 2 taken
                        6: branch 3 taken
                    12957: branch 4 taken
                        1: branch 5 taken
                        0: branch 6 not taken
     321            41421:   switch (MappingInfo & 7) {
     322                0:   default: assert(0 && "Unknown mapping!");
     323                 :   case diag::MAP_IGNORE:
     324                 :     // Ignore this, unless this is an extension diagnostic and we're mapping
     325                 :     // them onto warnings or errors.
                     1596: branch 1 taken
                    23641: branch 2 taken
                      151: branch 3 taken
                     1445: branch 4 taken
                        4: branch 5 taken
                      147: branch 6 taken
                    25090: branch 7 taken
                      147: branch 8 taken
     326            25237:     if (!isBuiltinExtensionDiag(DiagID) ||  // Not an extension
     327                 :         ExtBehavior == Ext_Ignore ||        // Extensions ignored anyway
     328                 :         (MappingInfo & 8) != 0)             // User explicitly mapped it.
     329            25090:       return Diagnostic::Ignored;
     330              147:     Result = Diagnostic::Warning;
                       17: branch 0 taken
                      130: branch 1 taken
     331              147:     if (ExtBehavior == Ext_Error) Result = Diagnostic::Error;
                       17: branch 0 taken
                      130: branch 1 taken
                        0: branch 2 not taken
                       17: branch 3 taken
     332              147:     if (Result == Diagnostic::Error && ErrorsAsFatal)
     333                0:       Result = Diagnostic::Fatal;
     334              147:     break;
     335                 :   case diag::MAP_ERROR:
     336             3220:     Result = Diagnostic::Error;
                        0: branch 0 not taken
                     3220: branch 1 taken
     337             3220:     if (ErrorsAsFatal)
     338                0:       Result = Diagnostic::Fatal;
     339             3220:     break;
     340                 :   case diag::MAP_FATAL:
     341                6:     Result = Diagnostic::Fatal;
     342                6:     break;
     343                 :   case diag::MAP_WARNING:
     344                 :     // If warnings are globally mapped to ignore or error, do it.
                      125: branch 0 taken
                    12832: branch 1 taken
     345            12957:     if (IgnoreAllWarnings)
     346              125:       return Diagnostic::Ignored;
     347                 : 
     348            12832:     Result = Diagnostic::Warning;
     349                 : 
     350                 :     // If this is an extension diagnostic and we're in -pedantic-error mode, and
     351                 :     // if the user didn't explicitly map it, upgrade to an error.
                       11: branch 0 taken
                    12821: branch 1 taken
                       10: branch 2 taken
                        1: branch 3 taken
                        4: branch 5 taken
                        6: branch 6 taken
                        4: branch 7 taken
                    12828: branch 8 taken
     352            12832:     if (ExtBehavior == Ext_Error &&
     353                 :         (MappingInfo & 8) == 0 &&
     354                 :         isBuiltinExtensionDiag(DiagID))
     355                4:       Result = Diagnostic::Error;
     356                 : 
                       18: branch 0 taken
                    12814: branch 1 taken
     357            12832:     if (WarningsAsErrors)
     358               18:       Result = Diagnostic::Error;
                       22: branch 0 taken
                    12810: branch 1 taken
                        0: branch 2 not taken
                       22: branch 3 taken
     359            12832:     if (Result == Diagnostic::Error && ErrorsAsFatal)
     360                0:       Result = Diagnostic::Fatal;
     361            12832:     break;
     362                 : 
     363                 :   case diag::MAP_WARNING_NO_WERROR:
     364                 :     // Diagnostics specified with -Wno-error=foo should be set to warnings, but
     365                 :     // not be adjusted by -Werror or -pedantic-errors.
     366                1:     Result = Diagnostic::Warning;
     367                 : 
     368                 :     // If warnings are globally mapped to ignore or error, do it.
                        0: branch 0 not taken
                        1: branch 1 taken
     369                1:     if (IgnoreAllWarnings)
     370                0:       return Diagnostic::Ignored;
     371                 : 
     372                1:     break;
     373                 : 
     374                 :   case diag::MAP_ERROR_NO_WFATAL:
     375                 :     // Diagnostics specified as -Wno-fatal-error=foo should be errors, but
     376                 :     // unaffected by -Wfatal-errors.
     377                0:     Result = Diagnostic::Error;
     378                 :     break;
     379                 :   }
     380                 : 
     381                 :   // Okay, we're about to return this as a "diagnostic to emit" one last check:
     382                 :   // if this is any sort of extension warning, and if we're in an __extension__
     383                 :   // block, silence it.
                       18: branch 0 taken
                    16188: branch 1 taken
                       15: branch 3 taken
                        3: branch 4 taken
                       15: branch 5 taken
                    16191: branch 6 taken
     384            16206:   if (AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
     385               15:     return Diagnostic::Ignored;
     386                 : 
     387            16191:   return Result;
     388                 : }
     389                 : 
     390                 : static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
     391              493:                          unsigned &Value) {
                        0: branch 0 not taken
                      493: branch 1 taken
     392              493:   if (Memory + sizeof(unsigned) > MemoryEnd)
     393                0:     return true;
     394                 : 
     395              493:   memmove(&Value, Memory, sizeof(unsigned));
     396              493:   Memory += sizeof(unsigned);
     397              493:   return false;
     398                 : }
     399                 : 
     400                 : static bool ReadSourceLocation(FileManager &FM, SourceManager &SM,
     401                 :                                const char *&Memory, const char *MemoryEnd,
     402               85:                                SourceLocation &Location) {
     403                 :   // Read the filename.
     404               85:   unsigned FileNameLen = 0;
                       85: branch 1 taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                       85: branch 4 taken
                        0: branch 5 not taken
                       85: branch 6 taken
     405               85:   if (ReadUnsigned(Memory, MemoryEnd, FileNameLen) || 
     406                 :       Memory + FileNameLen > MemoryEnd)
     407                0:     return true;
     408                 : 
     409               85:   llvm::StringRef FileName(Memory, FileNameLen);
     410               85:   Memory += FileNameLen;
     411                 : 
     412                 :   // Read the line, column.
     413               85:   unsigned Line = 0, Column = 0;
                       85: branch 1 taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                       85: branch 5 taken
                        0: branch 6 not taken
                       85: branch 7 taken
     414               85:   if (ReadUnsigned(Memory, MemoryEnd, Line) ||
     415                 :       ReadUnsigned(Memory, MemoryEnd, Column))
     416                0:     return true;
     417                 : 
                        3: branch 1 taken
                       82: branch 2 taken
     418               85:   if (FileName.empty()) {
     419                3:     Location = SourceLocation();
     420                3:     return false;
     421                 :   }
     422                 : 
     423               82:   const FileEntry *File = FM.getFile(FileName);
                        0: branch 0 not taken
                       82: branch 1 taken
     424               82:   if (!File)
     425                0:     return true;
     426                 : 
     427                 :   // Make sure that this file has an entry in the source manager.
                       19: branch 1 taken
                       63: branch 2 taken
     428               82:   if (!SM.hasFileInfo(File))
     429               19:     SM.createFileID(File, SourceLocation(), SrcMgr::C_User);
     430                 : 
     431               82:   Location = SM.getLocation(File, Line, Column);
     432               82:   return false;
     433                 : }
     434                 : 
     435                 : DiagnosticBuilder Diagnostic::Deserialize(FileManager &FM, SourceManager &SM, 
     436                 :                                           const char *&Memory, 
     437               73:                                           const char *MemoryEnd) {
                        0: branch 0 not taken
                       73: branch 1 taken
     438               73:   if (Memory == MemoryEnd)
     439                0:     return DiagnosticBuilder(0);
     440                 : 
     441                 :   // Read the severity level.
     442               73:   unsigned Level = 0;
                       73: branch 1 taken
                        0: branch 2 not taken
                       19: branch 3 taken
                       54: branch 4 taken
                       19: branch 5 taken
                       54: branch 6 taken
     443               73:   if (ReadUnsigned(Memory, MemoryEnd, Level) || Level > Fatal)
     444               19:     return DiagnosticBuilder(0);
     445                 : 
     446                 :   // Read the source location.
     447               54:   SourceLocation Location;
                        0: branch 1 not taken
                       54: branch 2 taken
     448               54:   if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, Location))
     449                0:     return DiagnosticBuilder(0);
     450                 : 
     451                 :   // Read the diagnostic text.
                        0: branch 0 not taken
                       54: branch 1 taken
     452               54:   if (Memory == MemoryEnd)
     453                0:     return DiagnosticBuilder(0);
     454                 : 
     455               54:   unsigned MessageLen = 0;
                       54: branch 1 taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                       54: branch 4 taken
                        0: branch 5 not taken
                       54: branch 6 taken
     456               54:   if (ReadUnsigned(Memory, MemoryEnd, MessageLen) ||
     457                 :       Memory + MessageLen > MemoryEnd)
     458                0:     return DiagnosticBuilder(0);
     459                 :   
     460               54:   llvm::StringRef Message(Memory, MessageLen);
     461               54:   Memory += MessageLen;
     462                 : 
     463                 :   // At this point, we have enough information to form a diagnostic. Do so.
     464               54:   unsigned DiagID = getCustomDiagID((enum Level)Level, Message);
     465               54:   DiagnosticBuilder DB = Report(FullSourceLoc(Location, SM), DiagID);
                        0: branch 0 not taken
                       54: branch 1 taken
     466               54:   if (Memory == MemoryEnd)
     467                0:     return DB;
     468                 : 
     469                 :   // Read the source ranges.
     470               54:   unsigned NumSourceRanges = 0;
                        0: branch 1 not taken
                       54: branch 2 taken
     471               54:   if (ReadUnsigned(Memory, MemoryEnd, NumSourceRanges))
     472                0:     return DB;
                       11: branch 0 taken
                       54: branch 1 taken
     473               65:   for (unsigned I = 0; I != NumSourceRanges; ++I) {
     474               11:     SourceLocation Begin, End;
                       11: branch 1 taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                       11: branch 5 taken
                        0: branch 6 not taken
                       11: branch 7 taken
     475               11:     if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, Begin) ||
     476                 :         ReadSourceLocation(FM, SM, Memory, MemoryEnd, End))
     477                0:       return DB;
     478                 : 
     479               11:     DB << SourceRange(Begin, End);
     480                 :   }
     481                 : 
     482                 :   // Read the fix-it hints.
     483               54:   unsigned NumFixIts = 0;
                        0: branch 1 not taken
                       54: branch 2 taken
     484               54:   if (ReadUnsigned(Memory, MemoryEnd, NumFixIts))
     485                0:     return DB;
                        3: branch 1 taken
                       54: branch 2 taken
     486               57:   for (unsigned I = 0; I != NumFixIts; ++I) {
     487                3:     SourceLocation RemoveBegin, RemoveEnd, InsertionLoc;
     488                3:     unsigned InsertLen = 0;
                        3: branch 1 taken
                        0: branch 2 not taken
                        3: branch 4 taken
                        0: branch 5 not taken
                        3: branch 7 taken
                        0: branch 8 not taken
                        3: branch 10 taken
                        0: branch 11 not taken
                        0: branch 12 not taken
                        3: branch 13 taken
                        0: branch 14 not taken
                        3: branch 15 taken
     489                3:     if (ReadSourceLocation(FM, SM, Memory, MemoryEnd, RemoveBegin) ||
     490                 :         ReadSourceLocation(FM, SM, Memory, MemoryEnd, RemoveEnd) ||
     491                 :         ReadSourceLocation(FM, SM, Memory, MemoryEnd, InsertionLoc) ||
     492                 :         ReadUnsigned(Memory, MemoryEnd, InsertLen) ||
     493                 :         Memory + InsertLen > MemoryEnd)
     494                0:       return DB;
     495                 : 
     496                3:     CodeModificationHint Hint;
     497                3:     Hint.RemoveRange = SourceRange(RemoveBegin, RemoveEnd);
     498                3:     Hint.InsertionLoc = InsertionLoc;
     499                3:     Hint.CodeToInsert.assign(Memory, Memory + InsertLen);
     500                3:     Memory += InsertLen;
     501                3:     DB << Hint;
     502                 :   }
     503                 : 
     504               54:   return DB;
     505                 : }
     506                 : 
     507                 : struct WarningOption {
     508                 :   const char  *Name;
     509                 :   const short *Members;
     510                 :   const char  *SubGroups;
     511                 : };
     512                 : 
     513                 : #define GET_DIAG_ARRAYS
     514                 : #include "clang/Basic/DiagnosticGroups.inc"
     515                 : #undef GET_DIAG_ARRAYS
     516                 : 
     517                 : // Second the table of options, sorted by name for fast binary lookup.
     518                 : static const WarningOption OptionTable[] = {
     519                 : #define GET_DIAG_TABLE
     520                 : #include "clang/Basic/DiagnosticGroups.inc"
     521                 : #undef GET_DIAG_TABLE
     522                 : };
     523                 : static const size_t OptionTableSize =
     524                 : sizeof(OptionTable) / sizeof(OptionTable[0]);
     525                 : 
     526                 : static bool WarningOptionCompare(const WarningOption &LHS,
     527              836:                                  const WarningOption &RHS) {
     528              836:   return strcmp(LHS.Name, RHS.Name) < 0;
     529                 : }
     530                 : 
     531                 : static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
     532              360:                             Diagnostic &Diags) {
     533                 :   // Option exists, poke all the members of its diagnostic set.
                      314: branch 0 taken
                       46: branch 1 taken
     534              360:   if (const short *Member = Group->Members) {
                      698: branch 0 taken
                      314: branch 1 taken
     535             1012:     for (; *Member != -1; ++Member)
     536              698:       Diags.setDiagnosticMapping(*Member, Mapping);
     537                 :   }
     538                 : 
     539                 :   // Enable/disable all subgroups along with this one.
                       70: branch 0 taken
                      290: branch 1 taken
     540              360:   if (const char *SubGroups = Group->SubGroups) {
                      241: branch 0 taken
                       70: branch 1 taken
     541              311:     for (; *SubGroups != (char)-1; ++SubGroups)
     542              241:       MapGroupMembers(&OptionTable[(unsigned char)*SubGroups], Mapping, Diags);
     543                 :   }
     544              360: }
     545                 : 
     546                 : /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
     547                 : /// "unknown-pragmas" to have the specified mapping.  This returns true and
     548                 : /// ignores the request if "Group" was unknown, false otherwise.
     549                 : bool Diagnostic::setDiagnosticGroupMapping(const char *Group,
     550              120:                                            diag::Mapping Map) {
     551                 : 
     552              120:   WarningOption Key = { Group, 0, 0 };
     553                 :   const WarningOption *Found =
     554                 :   std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
     555              120:                    WarningOptionCompare);
                      120: branch 0 taken
                        0: branch 1 not taken
                        1: branch 3 taken
                      119: branch 4 taken
     556              120:   if (Found == OptionTable + OptionTableSize ||
     557                 :       strcmp(Found->Name, Group) != 0)
     558                1:     return true;  // Option not found.
     559                 : 
     560              119:   MapGroupMembers(Found, Map, *this);
     561              119:   return false;
     562                 : }
     563                 : 
     564                 : 
     565                 : /// ProcessDiag - This is the method used to report a diagnostic that is
     566                 : /// finally fully formed.
     567            18884: bool Diagnostic::ProcessDiag() {
     568            18884:   DiagnosticInfo Info(this);
     569                 : 
                      366: branch 0 taken
                    18518: branch 1 taken
     570            18884:   if (SuppressAllDiagnostics)
     571              366:     return false;
     572                 :   
     573                 :   // Figure out the diagnostic level of this message.
     574                 :   Diagnostic::Level DiagLevel;
     575            18518:   unsigned DiagID = Info.getID();
     576                 : 
     577                 :   // ShouldEmitInSystemHeader - True if this diagnostic should be produced even
     578                 :   // in a system header.
     579                 :   bool ShouldEmitInSystemHeader;
     580                 : 
                      757: branch 0 taken
                    17761: branch 1 taken
     581            18518:   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
     582                 :     // Handle custom diagnostics, which cannot be mapped.
     583              757:     DiagLevel = CustomDiagInfo->getLevel(DiagID);
     584                 : 
     585                 :     // Custom diagnostics always are emitted in system headers.
     586              757:     ShouldEmitInSystemHeader = true;
     587                 :   } else {
     588                 :     // Get the class of the diagnostic.  If this is a NOTE, map it onto whatever
     589                 :     // the diagnostic level was for the previous diagnostic so that it is
     590                 :     // filtered the same as the previous diagnostic.
     591            17761:     unsigned DiagClass = getBuiltinDiagClass(DiagID);
                     2060: branch 0 taken
                    15701: branch 1 taken
     592            17761:     if (DiagClass == CLASS_NOTE) {
     593             2060:       DiagLevel = Diagnostic::Note;
     594             2060:       ShouldEmitInSystemHeader = false;  // extra consideration is needed
     595                 :     } else {
     596                 :       // If this is not an error and we are in a system header, we ignore it.
     597                 :       // Check the original Diag ID here, because we also want to ignore
     598                 :       // extensions and warnings in -Werror and -pedantic-errors modes, which
     599                 :       // *map* warnings/extensions to errors.
     600            15701:       ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR;
     601                 : 
     602            15701:       DiagLevel = getDiagnosticLevel(DiagID, DiagClass);
     603                 :     }
     604                 :   }
     605                 : 
                    16455: branch 0 taken
                     2063: branch 1 taken
     606            18518:   if (DiagLevel != Diagnostic::Note) {
     607                 :     // Record that a fatal error occurred only when we see a second
     608                 :     // non-note diagnostic. This allows notes to be attached to the
     609                 :     // fatal error, but suppresses any diagnostics that follow those
     610                 :     // notes.
                        2: branch 0 taken
                    16453: branch 1 taken
     611            16455:     if (LastDiagLevel == Diagnostic::Fatal)
     612                2:       FatalErrorOccurred = true;
     613                 : 
     614            16455:     LastDiagLevel = DiagLevel;
     615                 :   }
     616                 : 
     617                 :   // If a fatal error has already been emitted, silence all subsequent
     618                 :   // diagnostics.
                        4: branch 0 taken
                    18514: branch 1 taken
     619            18518:   if (FatalErrorOccurred)
     620                4:     return false;
     621                 : 
     622                 :   // If the client doesn't care about this message, don't issue it.  If this is
     623                 :   // a note and the last real diagnostic was ignored, ignore it too.
                     8075: branch 0 taken
                    10439: branch 1 taken
                     2063: branch 2 taken
                     6012: branch 3 taken
                       53: branch 4 taken
                     2010: branch 5 taken
     624            18514:   if (DiagLevel == Diagnostic::Ignored ||
     625                 :       (DiagLevel == Diagnostic::Note && LastDiagLevel == Diagnostic::Ignored))
     626            10492:     return false;
     627                 : 
     628                 :   // If this diagnostic is in a system header and is not a clang error, suppress
     629                 :   // it.
                     7980: branch 0 taken
                       42: branch 1 taken
                     4020: branch 2 taken
                     3960: branch 3 taken
                     4015: branch 6 taken
                        5: branch 7 taken
                        4: branch 11 taken
                     4011: branch 12 taken
                        1: branch 13 taken
                        3: branch 14 taken
                        0: branch 15 not taken
                        1: branch 16 taken
                        3: branch 17 taken
                     8019: branch 18 taken
     630             8022:   if (SuppressSystemWarnings && !ShouldEmitInSystemHeader &&
     631                 :       Info.getLocation().isValid() &&
     632                 :       Info.getLocation().getSpellingLoc().isInSystemHeader() &&
     633                 :       (DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored)) {
     634                3:     LastDiagLevel = Diagnostic::Ignored;
     635                3:     return false;
     636                 :   }
     637                 : 
                     3248: branch 0 taken
                     4771: branch 1 taken
     638             8019:   if (DiagLevel >= Diagnostic::Error) {
     639             3248:     ErrorOccurred = true;
     640             3248:     ++NumErrors;
     641                 :   }
     642                 : 
     643                 :   // Finally, report it.
     644             8019:   Client->HandleDiagnostic(DiagLevel, Info);
                     8019: branch 1 taken
                        0: branch 2 not taken
     645             8019:   if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics;
     646                 : 
     647             8019:   CurDiagID = ~0U;
     648                 : 
     649             8019:   return true;
     650                 : }
     651                 : 
     652                 : 
                    11914: branch 0 taken
                    11914: branch 1 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 6 not taken
                    11914: branch 7 taken
     653            11914: DiagnosticClient::~DiagnosticClient() {}
     654                 : 
     655                 : 
     656                 : /// ModifierIs - Return true if the specified modifier matches specified string.
     657                 : template <std::size_t StrLen>
     658                 : static bool ModifierIs(const char *Modifier, unsigned ModifierLen,
     659             3228:                        const char (&Str)[StrLen]) {
                       71: branch 0 taken
                      353: branch 1 taken
                       71: branch 2 taken
                        0: branch 3 not taken
                       89: branch 4 taken
                      193: branch 5 taken
                       89: branch 7 taken
                        0: branch 8 not taken
                     1887: branch 9 taken
                      635: branch 10 taken
                     1816: branch 12 taken
                       71: branch 13 taken
     660             3228:   return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1);
     661                 : }
     662                 : 
     663                 : /// ScanForward - Scans forward, looking for the given character, skipping
     664                 : /// nested clauses and escaped characters.
     665             5741: static const char *ScanFormat(const char *I, const char *E, char Target) {
     666             5741:   unsigned Depth = 0;
     667                 : 
                   164031: branch 0 taken
                      428: branch 1 taken
     668           164459:   for ( ; I != E; ++I) {
                   164031: branch 0 taken
                        0: branch 1 not taken
                     5313: branch 2 taken
                   158718: branch 3 taken
     669           164031:     if (Depth == 0 && *I == Target) return I;
                        0: branch 0 not taken
                   158718: branch 1 taken
                   158718: branch 2 taken
                   158718: branch 3 taken
     670           158718:     if (Depth != 0 && *I == '}') Depth--;
     671                 : 
                      172: branch 0 taken
                   158546: branch 1 taken
     672           158718:     if (*I == '%') {
     673              172:       I++;
                      172: branch 0 taken
                        0: branch 1 not taken
     674              172:       if (I == E) break;
     675                 : 
     676                 :       // Escaped characters get implicitly skipped here.
     677                 : 
     678                 :       // Format specifier.
                      170: branch 0 taken
                        2: branch 1 taken
                      170: branch 3 taken
                        0: branch 4 not taken
     679              172:       if (!isdigit(*I) && !ispunct(*I)) {
                     1190: branch 0 taken
                        0: branch 1 not taken
                     1020: branch 2 taken
                      170: branch 3 taken
                     1020: branch 4 taken
                        0: branch 5 not taken
     680              170:         for (I++; I != E && !isdigit(*I) && *I != '{'; I++) ;
                      170: branch 0 taken
                        0: branch 1 not taken
     681              170:         if (I == E) break;
                        0: branch 0 not taken
                      170: branch 1 taken
     682              170:         if (*I == '{')
     683                0:           Depth++;
     684                 :       }
     685                 :     }
     686                 :   }
     687              428:   return E;
     688                 : }
     689                 : 
     690                 : /// HandleSelectModifier - Handle the integer 'select' modifier.  This is used
     691                 : /// like this:  %select{foo|bar|baz}2.  This means that the integer argument
     692                 : /// "%2" has a value from 0-2.  If the value is 0, the diagnostic prints 'foo'.
     693                 : /// If the value is 1, it prints 'bar'.  If it has the value 2, it prints 'baz'.
     694                 : /// This is very useful for certain classes of variant diagnostics.
     695                 : static void HandleSelectModifier(const DiagnosticInfo &DInfo, unsigned ValNo,
     696                 :                                  const char *Argument, unsigned ArgumentLen,
     697             1745:                                  llvm::SmallVectorImpl<char> &OutStr) {
     698             1745:   const char *ArgumentEnd = Argument+ArgumentLen;
     699                 : 
     700                 :   // Skip over 'ValNo' |'s.
                     2049: branch 0 taken
                     1745: branch 1 taken
     701             5539:   while (ValNo) {
     702             2049:     const char *NextVal = ScanFormat(Argument, ArgumentEnd, '|');
     703                 :     assert(NextVal != ArgumentEnd && "Value for integer select modifier was"
                        0: branch 0 not taken
                     2049: branch 1 taken
     704             2049:            " larger than the number of options in the diagnostic string!");
     705             2049:     Argument = NextVal+1;  // Skip this string.
     706             2049:     --ValNo;
     707                 :   }
     708                 : 
     709                 :   // Get the end of the value.  This is either the } or the |.
     710             1745:   const char *EndPtr = ScanFormat(Argument, ArgumentEnd, '|');
     711                 : 
     712                 :   // Recursively format the result of the select clause into the output string.
     713             1745:   DInfo.FormatDiagnostic(Argument, EndPtr, OutStr);
     714             1745: }
     715                 : 
     716                 : /// HandleIntegerSModifier - Handle the integer 's' modifier.  This adds the
     717                 : /// letter 's' to the string if the value is not 1.  This is used in cases like
     718                 : /// this:  "you idiot, you have %4 parameter%s4!".
     719                 : static void HandleIntegerSModifier(unsigned ValNo,
     720               71:                                    llvm::SmallVectorImpl<char> &OutStr) {
                       25: branch 0 taken
                       46: branch 1 taken
     721               71:   if (ValNo != 1)
     722               25:     OutStr.push_back('s');
     723               71: }
     724                 : 
     725                 : /// HandleOrdinalModifier - Handle the integer 'ord' modifier.  This
     726                 : /// prints the ordinal form of the given integer, with 1 corresponding
     727                 : /// to the first ordinal.  Currently this is hard-coded to use the
     728                 : /// English form.
     729                 : static void HandleOrdinalModifier(unsigned ValNo,
     730               89:                                   llvm::SmallVectorImpl<char> &OutStr) {
                        0: branch 0 not taken
                       89: branch 1 taken
     731               89:   assert(ValNo != 0 && "ValNo must be strictly positive!");
     732                 : 
     733               89:   llvm::raw_svector_ostream Out(OutStr);
     734                 : 
     735                 :   // We could use text forms for the first N ordinals, but the numeric
     736                 :   // forms are actually nicer in diagnostics because they stand out.
     737               89:   Out << ValNo;
     738                 : 
     739                 :   // It is critically important that we do this perfectly for
     740                 :   // user-written sequences with over 100 elements.
                        0: branch 0 not taken
                       89: branch 1 taken
     741               89:   switch (ValNo % 100) {
     742                 :   case 11:
     743                 :   case 12:
     744                 :   case 13:
     745                0:     Out << "th"; return;
     746                 :   default:
                       75: branch 0 taken
                       14: branch 1 taken
                        0: branch 2 not taken
                        0: branch 3 not taken
     747               89:     switch (ValNo % 10) {
     748               75:     case 1: Out << "st"; return;
     749               14:     case 2: Out << "nd"; return;
     750                0:     case 3: Out << "rd"; return;
     751                0:     default: Out << "th"; return;
     752                 :     }
     753               89:   }
     754                 : }
     755                 : 
     756                 : 
     757                 : /// PluralNumber - Parse an unsigned integer and advance Start.
     758               71: static unsigned PluralNumber(const char *&Start, const char *End) {
     759                 :   // Programming 101: Parse a decimal number :-)
     760               71:   unsigned Val = 0;
                       71: branch 0 taken
                       71: branch 1 taken
                       71: branch 2 taken
                        0: branch 3 not taken
                       71: branch 4 taken
                        0: branch 5 not taken
     761              213:   while (Start != End && *Start >= '0' && *Start <= '9') {
     762               71:     Val *= 10;
     763               71:     Val += *Start - '0';
     764               71:     ++Start;
     765                 :   }
     766               71:   return Val;
     767                 : }
     768                 : 
     769                 : /// TestPluralRange - Test if Val is in the parsed range. Modifies Start.
     770               71: static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) {
                       71: branch 0 taken
                        0: branch 1 not taken
     771               71:   if (*Start != '[') {
     772               71:     unsigned Ref = PluralNumber(Start, End);
     773               71:     return Ref == Val;
     774                 :   }
     775                 : 
     776                0:   ++Start;
     777                0:   unsigned Low = PluralNumber(Start, End);
                        0: branch 0 not taken
                        0: branch 1 not taken
     778                0:   assert(*Start == ',' && "Bad plural expression syntax: expected ,");
     779                0:   ++Start;
     780                0:   unsigned High = PluralNumber(Start, End);
                        0: branch 0 not taken
                        0: branch 1 not taken
     781                0:   assert(*Start == ']' && "Bad plural expression syntax: expected )");
     782                0:   ++Start;
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
     783                0:   return Low <= Val && Val <= High;
     784                 : }
     785                 : 
     786                 : /// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier.
     787              131: static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
     788                 :   // Empty condition?
                       60: branch 0 taken
                       71: branch 1 taken
     789              131:   if (*Start == ':')
     790               60:     return true;
     791                 : 
     792                0:   while (1) {
     793               71:     char C = *Start;
                        0: branch 0 not taken
                       71: branch 1 taken
     794               71:     if (C == '%') {
     795                 :       // Modulo expression
     796                0:       ++Start;
     797                0:       unsigned Arg = PluralNumber(Start, End);
                        0: branch 0 not taken
                        0: branch 1 not taken
     798                0:       assert(*Start == '=' && "Bad plural expression syntax: expected =");
     799                0:       ++Start;
     800                0:       unsigned ValMod = ValNo % Arg;
                        0: branch 1 not taken
                        0: branch 2 not taken
     801                0:       if (TestPluralRange(ValMod, Start, End))
     802                0:         return true;
     803                 :     } else {
     804                 :       assert((C == '[' || (C >= '0' && C <= '9')) &&
                       71: branch 0 taken
                        0: branch 1 not taken
                       71: branch 2 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                       71: branch 5 taken
     805               71:              "Bad plural expression syntax: unexpected character");
     806                 :       // Range expression
                       11: branch 1 taken
                       60: branch 2 taken
     807               71:       if (TestPluralRange(ValNo, Start, End))
     808               11:         return true;
     809                 :     }
     810                 : 
     811                 :     // Scan for next or-expr part.
     812               60:     Start = std::find(Start, End, ',');
                        0: branch 0 not taken
                       60: branch 1 taken
     813               60:     if (Start == End)
     814               60:       break;
     815                0:     ++Start;
     816                 :   }
     817               60:   return false;
     818                 : }
     819                 : 
     820                 : /// HandlePluralModifier - Handle the integer 'plural' modifier. This is used
     821                 : /// for complex plural forms, or in languages where all plurals are complex.
     822                 : /// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are
     823                 : /// conditions that are tested in order, the form corresponding to the first
     824                 : /// that applies being emitted. The empty condition is always true, making the
     825                 : /// last form a default case.
     826                 : /// Conditions are simple boolean expressions, where n is the number argument.
     827                 : /// Here are the rules.
     828                 : /// condition  := expression | empty
     829                 : /// empty      :=                             -> always true
     830                 : /// expression := numeric [',' expression]    -> logical or
     831                 : /// numeric    := range                       -> true if n in range
     832                 : ///             | '%' number '=' range        -> true if n % number in range
     833                 : /// range      := number
     834                 : ///             | '[' number ',' number ']'   -> ranges are inclusive both ends
     835                 : ///
     836                 : /// Here are some examples from the GNU gettext manual written in this form:
     837                 : /// English:
     838                 : /// {1:form0|:form1}
     839                 : /// Latvian:
     840                 : /// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0}
     841                 : /// Gaeilge:
     842                 : /// {1:form0|2:form1|:form2}
     843                 : /// Romanian:
     844                 : /// {1:form0|0,%100=[1,19]:form1|:form2}
     845                 : /// Lithuanian:
     846                 : /// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1}
     847                 : /// Russian (requires repeated form):
     848                 : /// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2}
     849                 : /// Slovak
     850                 : /// {1:form0|[2,4]:form1|:form2}
     851                 : /// Polish (requires repeated form):
     852                 : /// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
     853                 : static void HandlePluralModifier(unsigned ValNo,
     854                 :                                  const char *Argument, unsigned ArgumentLen,
     855               71:                                  llvm::SmallVectorImpl<char> &OutStr) {
     856               71:   const char *ArgumentEnd = Argument + ArgumentLen;
     857               60:   while (1) {
                        0: branch 0 not taken
                      131: branch 1 taken
     858              131:     assert(Argument < ArgumentEnd && "Plural expression didn't match.");
     859              131:     const char *ExprEnd = Argument;
                       71: branch 0 taken
                      131: branch 1 taken
     860              333:     while (*ExprEnd != ':') {
                        0: branch 0 not taken
                       71: branch 1 taken
     861               71:       assert(ExprEnd != ArgumentEnd && "Plural missing expression end");
     862               71:       ++ExprEnd;
     863                 :     }
                       71: branch 1 taken
                       60: branch 2 taken
     864              131:     if (EvalPluralExpr(ValNo, Argument, ExprEnd)) {
     865               71:       Argument = ExprEnd + 1;
     866               71:       ExprEnd = ScanFormat(Argument, ArgumentEnd, '|');
     867               71:       OutStr.append(Argument, ExprEnd);
     868                 :       return;
     869                 :     }
     870               60:     Argument = ScanFormat(Argument, ArgumentEnd - 1, '|') + 1;
     871                 :   }
     872                 : }
     873                 : 
     874                 : 
     875                 : /// FormatDiagnostic - Format this diagnostic into a string, substituting the
     876                 : /// formal arguments into the %0 slots.  The result is appended onto the Str
     877                 : /// array.
     878                 : void DiagnosticInfo::
     879             8018: FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
     880             8018:   const char *DiagStr = getDiags()->getDescription(getID());
     881             8018:   const char *DiagEnd = DiagStr+strlen(DiagStr);
     882                 : 
     883             8018:   FormatDiagnostic(DiagStr, DiagEnd, OutStr);
     884             8018: }
     885                 : 
     886                 : void DiagnosticInfo::
     887                 : FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
     888             9763:                  llvm::SmallVectorImpl<char> &OutStr) const {
     889                 : 
     890                 :   /// FormattedArgs - Keep track of all of the arguments formatted by
     891                 :   /// ConvertArgToString and pass them into subsequent calls to
     892                 :   /// ConvertArgToString, allowing the implementation to avoid redundancies in
     893                 :   /// obvious cases.
     894             9763:   llvm::SmallVector<Diagnostic::ArgumentValue, 8> FormattedArgs;
     895                 :   
                    23030: branch 0 taken
                     9763: branch 1 taken
     896            42556:   while (DiagStr != DiagEnd) {
                    14771: branch 0 taken
                     8259: branch 1 taken
     897            23030:     if (DiagStr[0] != '%') {
     898                 :       // Append non-%0 substrings to Str if we have one.
     899            14771:       const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
     900            14771:       OutStr.append(DiagStr, StrEnd);
     901            14771:       DiagStr = StrEnd;
     902            14771:       continue;
                       17: branch 1 taken
                     8242: branch 2 taken
     903             8259:     } else if (ispunct(DiagStr[1])) {
     904               17:       OutStr.push_back(DiagStr[1]);  // %% -> %.
     905               17:       DiagStr += 2;
     906               17:       continue;
     907                 :     }
     908                 : 
     909                 :     // Skip the %.
     910             8242:     ++DiagStr;
     911                 : 
     912                 :     // This must be a placeholder for a diagnostic argument.  The format for a
     913                 :     // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0".
     914                 :     // The digit is a number from 0-9 indicating which argument this comes from.
     915                 :     // The modifier is a string of digits from the set [-a-z]+, arguments is a
     916                 :     // brace enclosed string.
     917             8242:     const char *Modifier = 0, *Argument = 0;
     918             8242:     unsigned ModifierLen = 0, ArgumentLen = 0;
     919                 : 
     920                 :     // Check to see if we have a modifier.  If so eat it.
                     2235: branch 0 taken
                     6007: branch 1 taken
     921             8242:     if (!isdigit(DiagStr[0])) {
     922             2235:       Modifier = DiagStr;
                        0: branch 0 not taken
                    14980: branch 1 taken
                    14561: branch 2 taken
                      419: branch 3 taken
                    12745: branch 4 taken
                     1816: branch 5 taken
     923            17215:       while (DiagStr[0] == '-' ||
     924                 :              (DiagStr[0] >= 'a' && DiagStr[0] <= 'z'))
     925            12745:         ++DiagStr;
     926             2235:       ModifierLen = DiagStr-Modifier;
     927                 : 
     928                 :       // If we have an argument, get it next.
                     1816: branch 0 taken
                      419: branch 1 taken
     929             2235:       if (DiagStr[0] == '{') {
     930             1816:         ++DiagStr; // Skip {.
     931             1816:         Argument = DiagStr;
     932                 : 
     933             1816:         DiagStr = ScanFormat(DiagStr, DiagEnd, '}');
                        0: branch 0 not taken
                     1816: branch 1 taken
     934             1816:         assert(DiagStr != DiagEnd && "Mismatched {}'s in diagnostic string!");
     935             1816:         ArgumentLen = DiagStr-Argument;
     936             1816:         ++DiagStr;  // Skip }.
     937                 :       }
     938                 :     }
     939                 : 
                        0: branch 0 not taken
                     8242: branch 1 taken
     940             8242:     assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");
     941             8242:     unsigned ArgNo = *DiagStr++ - '0';
     942                 : 
     943             8242:     Diagnostic::ArgumentKind Kind = getArgKind(ArgNo);
     944                 :     
                      668: branch 0 taken
                      445: branch 1 taken
                     1176: branch 2 taken
                      993: branch 3 taken
                      383: branch 4 taken
                     4577: branch 5 taken
                        0: branch 6 not taken
     945             8242:     switch (Kind) {
     946                 :     // ---- STRINGS ----
     947                 :     case Diagnostic::ak_std_string: {
     948              668:       const std::string &S = getArgStdStr(ArgNo);
                        0: branch 0 not taken
                      668: branch 1 taken
     949              668:       assert(ModifierLen == 0 && "No modifiers for strings yet");
     950              668:       OutStr.append(S.begin(), S.end());
     951              668:       break;
     952                 :     }
     953                 :     case Diagnostic::ak_c_string: {
     954              445:       const char *S = getArgCStr(ArgNo);
                        0: branch 0 not taken
                      445: branch 1 taken
     955              445:       assert(ModifierLen == 0 && "No modifiers for strings yet");
     956                 : 
     957                 :       // Don't crash if get passed a null pointer by accident.
                        0: branch 0 not taken
                      445: branch 1 taken
     958              445:       if (!S)
     959                0:         S = "(null)";
     960                 : 
     961              445:       OutStr.append(S, S + strlen(S));
     962              445:       break;
     963                 :     }
     964                 :     // ---- INTEGERS ----
     965                 :     case Diagnostic::ak_sint: {
     966             1176:       int Val = getArgSInt(ArgNo);
     967                 : 
                     1149: branch 1 taken
                       27: branch 2 taken
     968             1176:       if (ModifierIs(Modifier, ModifierLen, "select")) {
     969             1149:         HandleSelectModifier(*this, (unsigned)Val, Argument, ArgumentLen, OutStr);
                        0: branch 1 not taken
                       27: branch 2 taken
     970               27:       } else if (ModifierIs(Modifier, ModifierLen, "s")) {
     971                0:         HandleIntegerSModifier(Val, OutStr);
                        0: branch 1 not taken
                       27: branch 2 taken
     972               27:       } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
     973                0:         HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
                        0: branch 1 not taken
                       27: branch 2 taken
     974               27:       } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
     975                0:         HandleOrdinalModifier((unsigned)Val, OutStr);
     976                 :       } else {
                        0: branch 0 not taken
                       27: branch 1 taken
     977               27:         assert(ModifierLen == 0 && "Unknown integer modifier");
     978               27:         llvm::raw_svector_ostream(OutStr) << Val;
     979                 :       }
     980             1176:       break;
     981                 :     }
     982                 :     case Diagnostic::ak_uint: {
     983              993:       unsigned Val = getArgUInt(ArgNo);
     984                 : 
                      596: branch 1 taken
                      397: branch 2 taken
     985              993:       if (ModifierIs(Modifier, ModifierLen, "select")) {
     986              596:         HandleSelectModifier(*this, Val, Argument, ArgumentLen, OutStr);
                       71: branch 1 taken
                      326: branch 2 taken
     987              397:       } else if (ModifierIs(Modifier, ModifierLen, "s")) {
     988               71:         HandleIntegerSModifier(Val, OutStr);
                       71: branch 1 taken
                      255: branch 2 taken
     989              326:       } else if (ModifierIs(Modifier, ModifierLen, "plural")) {
     990               71:         HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
                       89: branch 1 taken
                      166: branch 2 taken
     991              255:       } else if (ModifierIs(Modifier, ModifierLen, "ordinal")) {
     992               89:         HandleOrdinalModifier(Val, OutStr);
     993                 :       } else {
                        0: branch 0 not taken
                      166: branch 1 taken
     994              166:         assert(ModifierLen == 0 && "Unknown integer modifier");
     995              166:         llvm::raw_svector_ostream(OutStr) << Val;
     996                 :       }
     997              993:       break;
     998                 :     }
     999                 :     // ---- NAMES and TYPES ----
    1000                 :     case Diagnostic::ak_identifierinfo: {
    1001              383:       const IdentifierInfo *II = getArgIdentifier(ArgNo);
                        0: branch 0 not taken
                      383: branch 1 taken
    1002              383:       assert(ModifierLen == 0 && "No modifiers for strings yet");
    1003                 : 
    1004                 :       // Don't crash if get passed a null pointer by accident.
                        1: branch 0 taken
                      382: branch 1 taken
    1005              383:       if (!II) {
    1006                1:         const char *S = "(null)";
    1007                1:         OutStr.append(S, S + strlen(S));
    1008                1:         continue;
    1009                 :       }
    1010                 : 
    1011              382:       llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';
    1012              382:       break;
    1013                 :     }
    1014                 :     case Diagnostic::ak_qualtype:
    1015                 :     case Diagnostic::ak_declarationname:
    1016                 :     case Diagnostic::ak_nameddecl:
    1017                 :     case Diagnostic::ak_nestednamespec:
    1018                 :     case Diagnostic::ak_declcontext:
    1019                 :       getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
    1020                 :                                      Modifier, ModifierLen,
    1021                 :                                      Argument, ArgumentLen,
    1022                 :                                      FormattedArgs.data(), FormattedArgs.size(),
    1023             4577:                                      OutStr);
    1024                 :       break;
    1025                 :     }
    1026                 :     
    1027                 :     // Remember this argument info for subsequent formatting operations.  Turn
    1028                 :     // std::strings into a null terminated string to make it be the same case as
    1029                 :     // all the other ones.
                     7573: branch 0 taken
                      668: branch 1 taken
    1030             8241:     if (Kind != Diagnostic::ak_std_string)
    1031             7573:       FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));
    1032                 :     else
    1033                 :       FormattedArgs.push_back(std::make_pair(Diagnostic::ak_c_string,
    1034              668:                                         (intptr_t)getArgStdStr(ArgNo).c_str()));
    1035                 :     
    1036             9763:   }
    1037             9763: }
    1038                 : 
    1039              474: static void WriteUnsigned(llvm::raw_ostream &OS, unsigned Value) {
    1040              474:   OS.write((const char *)&Value, sizeof(unsigned));
    1041              474: }
    1042                 : 
    1043              139: static void WriteString(llvm::raw_ostream &OS, llvm::StringRef String) {
    1044              139:   WriteUnsigned(OS, String.size());
    1045              139:   OS.write(String.data(), String.size());
    1046              139: }
    1047                 : 
    1048                 : static void WriteSourceLocation(llvm::raw_ostream &OS, 
    1049                 :                                 SourceManager *SM,
    1050               85:                                 SourceLocation Location) {
                       85: branch 0 taken
                        0: branch 1 not taken
                        3: branch 3 taken
                       82: branch 4 taken
                        3: branch 5 taken
                       82: branch 6 taken
    1051               85:   if (!SM || Location.isInvalid()) {
    1052                 :     // If we don't have a source manager or this location is invalid,
    1053                 :     // just write an invalid location.
    1054                3:     WriteUnsigned(OS, 0);
    1055                3:     WriteUnsigned(OS, 0);
    1056                3:     WriteUnsigned(OS, 0);
    1057                3:     return;
    1058                 :   }
    1059                 : 
    1060               82:   Location = SM->getInstantiationLoc(Location);
    1061               82:   std::pair<FileID, unsigned> Decomposed = SM->getDecomposedLoc(Location);
    1062                 :   
    1063               82:   WriteString(OS, SM->getFileEntryForID(Decomposed.first)->getName());
    1064               82:   WriteUnsigned(OS, SM->getLineNumber(Decomposed.first, Decomposed.second));
    1065               82:   WriteUnsigned(OS, SM->getColumnNumber(Decomposed.first, Decomposed.second));
    1066                 : }
    1067                 : 
    1068                 : void DiagnosticInfo::Serialize(Diagnostic::Level DiagLevel, 
    1069               54:                                llvm::raw_ostream &OS) const {
    1070               54:   SourceManager *SM = 0;
                       54: branch 2 taken
                        0: branch 3 not taken
    1071               54:   if (getLocation().isValid())
    1072               54:     SM = &const_cast<SourceManager &>(getLocation().getManager());
    1073                 : 
    1074                 :   // Write the diagnostic level and location.
    1075               54:   WriteUnsigned(OS, (unsigned)DiagLevel);
    1076               54:   WriteSourceLocation(OS, SM, getLocation());
    1077                 : 
    1078                 :   // Write the diagnostic message.
    1079               54:   llvm::SmallString<64> Message;
    1080               54:   FormatDiagnostic(Message);
    1081               54:   WriteString(OS, Message);
    1082                 :   
    1083                 :   // Count the number of ranges that don't point into macros, since
    1084                 :   // only simple file ranges serialize well.
    1085               54:   unsigned NumNonMacroRanges = 0;
                       11: branch 1 taken
                       54: branch 2 taken
    1086               65:   for (unsigned I = 0, N = getNumRanges(); I != N; ++I) {
    1087               11:     SourceRange R = getRange(I);
                       11: branch 2 taken
                        0: branch 3 not taken
                        0: branch 6 not taken
                       11: branch 7 taken
                        0: branch 8 not taken
                       11: branch 9 taken
    1088               11:     if (R.getBegin().isMacroID() || R.getEnd().isMacroID())
    1089                0:       continue;
    1090                 : 
    1091               11:     ++NumNonMacroRanges;
    1092                 :   }
    1093                 : 
    1094                 :   // Write the ranges.
    1095               54:   WriteUnsigned(OS, NumNonMacroRanges);
                       10: branch 0 taken
                       44: branch 1 taken
    1096               54:   if (NumNonMacroRanges) {
                       11: branch 1 taken
                       10: branch 2 taken
    1097               21:     for (unsigned I = 0, N = getNumRanges(); I != N; ++I) {
    1098               11:       SourceRange R = getRange(I);
                       11: branch 2 taken
                        0: branch 3 not taken
                        0: branch 6 not taken
                       11: branch 7 taken
                        0: branch 8 not taken
                       11: branch 9 taken
    1099               11:       if (R.getBegin().isMacroID() || R.getEnd().isMacroID())
    1100                0:         continue;
    1101                 :       
    1102               11:       WriteSourceLocation(OS, SM, R.getBegin());
    1103               11:       WriteSourceLocation(OS, SM, R.getEnd());
    1104                 :     }
    1105                 :   }
    1106                 : 
    1107                 :   // Determine if all of the fix-its involve rewrites with simple file
    1108                 :   // locations (not in macro instantiations). If so, we can write
    1109                 :   // fix-it information.
    1110               54:   unsigned NumFixIts = getNumCodeModificationHints();
                        3: branch 0 taken
                       54: branch 1 taken
    1111               57:   for (unsigned I = 0; I != NumFixIts; ++I) {
    1112                3:     const CodeModificationHint &Hint = getCodeModificationHint(I);
                        2: branch 1 taken
                        1: branch 2 taken
                        2: branch 5 taken
                        0: branch 6 not taken
                        0: branch 9 not taken
                        2: branch 10 taken
                        0: branch 11 not taken
                        3: branch 12 taken
    1113                3:     if (Hint.RemoveRange.isValid() &&
    1114                 :         (Hint.RemoveRange.getBegin().isMacroID() ||
    1115                 :          Hint.RemoveRange.getEnd().isMacroID())) {
    1116                0:       NumFixIts = 0;
    1117                0:       break;
    1118                 :     }
    1119                 : 
                        2: branch 1 taken
                        1: branch 2 taken
                        0: branch 4 not taken
                        2: branch 5 taken
                        0: branch 6 not taken
                        3: branch 7 taken
    1120                3:     if (Hint.InsertionLoc.isValid() && Hint.InsertionLoc.isMacroID()) {
    1121                0:       NumFixIts = 0;
    1122                0:       break;
    1123                 :     }
    1124                 :   }
    1125                 : 
    1126                 :   // Write the fix-its.
    1127               54:   WriteUnsigned(OS, NumFixIts);
                        3: branch 0 taken
                       54: branch 1 taken
    1128               57:   for (unsigned I = 0; I != NumFixIts; ++I) {
    1129                3:     const CodeModificationHint &Hint = getCodeModificationHint(I);
    1130                3:     WriteSourceLocation(OS, SM, Hint.RemoveRange.getBegin());
    1131                3:     WriteSourceLocation(OS, SM, Hint.RemoveRange.getEnd());
    1132                3:     WriteSourceLocation(OS, SM, Hint.InsertionLoc);
    1133                3:     WriteString(OS, Hint.CodeToInsert);
    1134               54:   }
    1135               54: }
    1136                 : 
    1137                 : /// IncludeInDiagnosticCounts - This method (whose default implementation
    1138                 : ///  returns true) indicates whether the diagnostics handled by this
    1139                 : ///  DiagnosticClient should be included in the number of diagnostics
    1140                 : ///  reported by Diagnostic.
    1141             8019: bool DiagnosticClient::IncludeInDiagnosticCounts() const { return true; }

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