Home | History | Annotate | Download | only in Basic
      1 //===--- DiagnosticIDs.cpp - Diagnostic IDs 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 IDs-related interfaces.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "clang/AST/ASTDiagnostic.h"
     15 #include "clang/Analysis/AnalysisDiagnostic.h"
     16 #include "clang/Basic/DiagnosticIDs.h"
     17 #include "clang/Basic/DiagnosticCategories.h"
     18 #include "clang/Basic/SourceManager.h"
     19 #include "clang/Driver/DriverDiagnostic.h"
     20 #include "clang/Frontend/FrontendDiagnostic.h"
     21 #include "clang/Lex/LexDiagnostic.h"
     22 #include "clang/Parse/ParseDiagnostic.h"
     23 #include "clang/Sema/SemaDiagnostic.h"
     24 
     25 #include <map>
     26 using namespace clang;
     27 
     28 //===----------------------------------------------------------------------===//
     29 // Builtin Diagnostic information
     30 //===----------------------------------------------------------------------===//
     31 
     32 namespace {
     33 
     34 // Diagnostic classes.
     35 enum {
     36   CLASS_NOTE       = 0x01,
     37   CLASS_WARNING    = 0x02,
     38   CLASS_EXTENSION  = 0x03,
     39   CLASS_ERROR      = 0x04
     40 };
     41 
     42 struct StaticDiagInfoRec {
     43   unsigned short DiagID;
     44   unsigned Mapping : 3;
     45   unsigned Class : 3;
     46   unsigned SFINAE : 1;
     47   unsigned AccessControl : 1;
     48   unsigned Category : 5;
     49 
     50   uint8_t  NameLen;
     51   uint8_t  OptionGroupLen;
     52 
     53   uint16_t DescriptionLen;
     54   uint16_t BriefExplanationLen;
     55   uint16_t FullExplanationLen;
     56 
     57   const char *NameStr;
     58   const char *OptionGroupStr;
     59 
     60   const char *DescriptionStr;
     61   const char *BriefExplanationStr;
     62   const char *FullExplanationStr;
     63 
     64   llvm::StringRef getName() const {
     65     return llvm::StringRef(NameStr, NameLen);
     66   }
     67   llvm::StringRef getOptionGroup() const {
     68     return llvm::StringRef(OptionGroupStr, OptionGroupLen);
     69   }
     70 
     71   llvm::StringRef getDescription() const {
     72     return llvm::StringRef(DescriptionStr, DescriptionLen);
     73   }
     74   llvm::StringRef getBriefExplanation() const {
     75     return llvm::StringRef(BriefExplanationStr, BriefExplanationLen);
     76   }
     77   llvm::StringRef getFullExplanation() const {
     78     return llvm::StringRef(FullExplanationStr, FullExplanationLen);
     79   }
     80 
     81   bool operator<(const StaticDiagInfoRec &RHS) const {
     82     return DiagID < RHS.DiagID;
     83   }
     84 };
     85 
     86 struct StaticDiagNameIndexRec {
     87   const char *NameStr;
     88   unsigned short DiagID;
     89   uint8_t NameLen;
     90 
     91   llvm::StringRef getName() const {
     92     return llvm::StringRef(NameStr, NameLen);
     93   }
     94 
     95   bool operator<(const StaticDiagNameIndexRec &RHS) const {
     96     return getName() < RHS.getName();
     97   }
     98 
     99   bool operator==(const StaticDiagNameIndexRec &RHS) const {
    100     return getName() == RHS.getName();
    101   }
    102 };
    103 
    104 template <size_t SizeOfStr, typename FieldType>
    105 class StringSizerHelper {
    106   char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1];
    107 public:
    108   enum { Size = SizeOfStr };
    109 };
    110 
    111 } // namespace anonymous
    112 
    113 #define STR_SIZE(str, fieldTy) StringSizerHelper<sizeof(str)-1, fieldTy>::Size
    114 
    115 static const StaticDiagInfoRec StaticDiagInfo[] = {
    116 #define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,               \
    117              SFINAE,ACCESS,CATEGORY,BRIEF,FULL)                   \
    118   { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS, CATEGORY, \
    119     STR_SIZE(#ENUM, uint8_t), STR_SIZE(GROUP, uint8_t),           \
    120     STR_SIZE(DESC, uint16_t), STR_SIZE(BRIEF, uint16_t),          \
    121     STR_SIZE(FULL, uint16_t),                                     \
    122     #ENUM, GROUP, DESC, BRIEF, FULL },
    123 #include "clang/Basic/DiagnosticCommonKinds.inc"
    124 #include "clang/Basic/DiagnosticDriverKinds.inc"
    125 #include "clang/Basic/DiagnosticFrontendKinds.inc"
    126 #include "clang/Basic/DiagnosticLexKinds.inc"
    127 #include "clang/Basic/DiagnosticParseKinds.inc"
    128 #include "clang/Basic/DiagnosticASTKinds.inc"
    129 #include "clang/Basic/DiagnosticSemaKinds.inc"
    130 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
    131 #undef DIAG
    132   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    133 };
    134 
    135 static const unsigned StaticDiagInfoSize =
    136   sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
    137 
    138 /// To be sorted before first use (since it's splitted among multiple files)
    139 static const StaticDiagNameIndexRec StaticDiagNameIndex[] = {
    140 #define DIAG_NAME_INDEX(ENUM) { #ENUM, diag::ENUM, STR_SIZE(#ENUM, uint8_t) },
    141 #include "clang/Basic/DiagnosticIndexName.inc"
    142 #undef DIAG_NAME_INDEX
    143   { 0, 0, 0 }
    144 };
    145 
    146 static const unsigned StaticDiagNameIndexSize =
    147   sizeof(StaticDiagNameIndex)/sizeof(StaticDiagNameIndex[0])-1;
    148 
    149 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
    150 /// or null if the ID is invalid.
    151 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
    152   // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
    153 #ifndef NDEBUG
    154   static bool IsFirst = true;
    155   if (IsFirst) {
    156     for (unsigned i = 1; i != StaticDiagInfoSize; ++i) {
    157       assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
    158              "Diag ID conflict, the enums at the start of clang::diag (in "
    159              "DiagnosticIDs.h) probably need to be increased");
    160 
    161       assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
    162              "Improperly sorted diag info");
    163     }
    164     IsFirst = false;
    165   }
    166 #endif
    167 
    168   // Search the diagnostic table with a binary search.
    169   StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0 };
    170 
    171   const StaticDiagInfoRec *Found =
    172     std::lower_bound(StaticDiagInfo, StaticDiagInfo + StaticDiagInfoSize, Find);
    173   if (Found == StaticDiagInfo + StaticDiagInfoSize ||
    174       Found->DiagID != DiagID)
    175     return 0;
    176 
    177   return Found;
    178 }
    179 
    180 static unsigned GetDefaultDiagMapping(unsigned DiagID) {
    181   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    182     return Info->Mapping;
    183   return diag::MAP_FATAL;
    184 }
    185 
    186 /// getWarningOptionForDiag - Return the lowest-level warning option that
    187 /// enables the specified diagnostic.  If there is no -Wfoo flag that controls
    188 /// the diagnostic, this returns null.
    189 llvm::StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
    190   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    191     return Info->getOptionGroup();
    192   return llvm::StringRef();
    193 }
    194 
    195 /// getCategoryNumberForDiag - Return the category number that a specified
    196 /// DiagID belongs to, or 0 if no category.
    197 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
    198   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    199     return Info->Category;
    200   return 0;
    201 }
    202 
    203 namespace {
    204   // The diagnostic category names.
    205   struct StaticDiagCategoryRec {
    206     const char *NameStr;
    207     uint8_t NameLen;
    208 
    209     llvm::StringRef getName() const {
    210       return llvm::StringRef(NameStr, NameLen);
    211     }
    212   };
    213 }
    214 
    215 static const StaticDiagCategoryRec CategoryNameTable[] = {
    216 #define GET_CATEGORY_TABLE
    217 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
    218 #include "clang/Basic/DiagnosticGroups.inc"
    219 #undef GET_CATEGORY_TABLE
    220   { 0, 0 }
    221 };
    222 
    223 /// getNumberOfCategories - Return the number of categories
    224 unsigned DiagnosticIDs::getNumberOfCategories() {
    225   return sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
    226 }
    227 
    228 /// getCategoryNameFromID - Given a category ID, return the name of the
    229 /// category, an empty string if CategoryID is zero, or null if CategoryID is
    230 /// invalid.
    231 llvm::StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
    232   if (CategoryID >= getNumberOfCategories())
    233    return llvm::StringRef();
    234   return CategoryNameTable[CategoryID].getName();
    235 }
    236 
    237 
    238 
    239 DiagnosticIDs::SFINAEResponse
    240 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
    241   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
    242     if (Info->AccessControl)
    243       return SFINAE_AccessControl;
    244 
    245     if (!Info->SFINAE)
    246       return SFINAE_Report;
    247 
    248     if (Info->Class == CLASS_ERROR)
    249       return SFINAE_SubstitutionFailure;
    250 
    251     // Suppress notes, warnings, and extensions;
    252     return SFINAE_Suppress;
    253   }
    254 
    255   return SFINAE_Report;
    256 }
    257 
    258 /// getName - Given a diagnostic ID, return its name
    259 llvm::StringRef DiagnosticIDs::getName(unsigned DiagID) {
    260   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    261     return Info->getName();
    262   return llvm::StringRef();
    263 }
    264 
    265 /// getIdFromName - Given a diagnostic name, return its ID, or 0
    266 unsigned DiagnosticIDs::getIdFromName(llvm::StringRef Name) {
    267   const StaticDiagNameIndexRec *StaticDiagNameIndexEnd =
    268     StaticDiagNameIndex + StaticDiagNameIndexSize;
    269 
    270   if (Name.empty()) { return diag::DIAG_UPPER_LIMIT; }
    271 
    272   StaticDiagNameIndexRec Find = { Name.data(), 0, Name.size() };
    273 
    274   const StaticDiagNameIndexRec *Found =
    275     std::lower_bound( StaticDiagNameIndex, StaticDiagNameIndexEnd, Find);
    276   if (Found == StaticDiagNameIndexEnd ||
    277       Found->getName() != Name)
    278     return diag::DIAG_UPPER_LIMIT;
    279 
    280   return Found->DiagID;
    281 }
    282 
    283 /// getBriefExplanation - Given a diagnostic ID, return a brief explanation
    284 /// of the issue
    285 llvm::StringRef DiagnosticIDs::getBriefExplanation(unsigned DiagID) {
    286   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    287     return Info->getBriefExplanation();
    288   return llvm::StringRef();
    289 }
    290 
    291 /// getFullExplanation - Given a diagnostic ID, return a full explanation
    292 /// of the issue
    293 llvm::StringRef DiagnosticIDs::getFullExplanation(unsigned DiagID) {
    294   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    295     return Info->getFullExplanation();
    296   return llvm::StringRef();
    297 }
    298 
    299 /// getBuiltinDiagClass - Return the class field of the diagnostic.
    300 ///
    301 static unsigned getBuiltinDiagClass(unsigned DiagID) {
    302   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    303     return Info->Class;
    304   return ~0U;
    305 }
    306 
    307 //===----------------------------------------------------------------------===//
    308 // Custom Diagnostic information
    309 //===----------------------------------------------------------------------===//
    310 
    311 namespace clang {
    312   namespace diag {
    313     class CustomDiagInfo {
    314       typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
    315       std::vector<DiagDesc> DiagInfo;
    316       std::map<DiagDesc, unsigned> DiagIDs;
    317     public:
    318 
    319       /// getDescription - Return the description of the specified custom
    320       /// diagnostic.
    321       llvm::StringRef getDescription(unsigned DiagID) const {
    322         assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
    323                "Invalid diagnosic ID");
    324         return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
    325       }
    326 
    327       /// getLevel - Return the level of the specified custom diagnostic.
    328       DiagnosticIDs::Level getLevel(unsigned DiagID) const {
    329         assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
    330                "Invalid diagnosic ID");
    331         return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
    332       }
    333 
    334       unsigned getOrCreateDiagID(DiagnosticIDs::Level L, llvm::StringRef Message,
    335                                  DiagnosticIDs &Diags) {
    336         DiagDesc D(L, Message);
    337         // Check to see if it already exists.
    338         std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
    339         if (I != DiagIDs.end() && I->first == D)
    340           return I->second;
    341 
    342         // If not, assign a new ID.
    343         unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
    344         DiagIDs.insert(std::make_pair(D, ID));
    345         DiagInfo.push_back(D);
    346         return ID;
    347       }
    348     };
    349 
    350   } // end diag namespace
    351 } // end clang namespace
    352 
    353 
    354 //===----------------------------------------------------------------------===//
    355 // Common Diagnostic implementation
    356 //===----------------------------------------------------------------------===//
    357 
    358 DiagnosticIDs::DiagnosticIDs() {
    359   CustomDiagInfo = 0;
    360 }
    361 
    362 DiagnosticIDs::~DiagnosticIDs() {
    363   delete CustomDiagInfo;
    364 }
    365 
    366 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
    367 /// and level.  If this is the first request for this diagnosic, it is
    368 /// registered and created, otherwise the existing ID is returned.
    369 unsigned DiagnosticIDs::getCustomDiagID(Level L, llvm::StringRef Message) {
    370   if (CustomDiagInfo == 0)
    371     CustomDiagInfo = new diag::CustomDiagInfo();
    372   return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
    373 }
    374 
    375 
    376 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
    377 /// level of the specified diagnostic ID is a Warning or Extension.
    378 /// This only works on builtin diagnostics, not custom ones, and is not legal to
    379 /// call on NOTEs.
    380 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
    381   return DiagID < diag::DIAG_UPPER_LIMIT &&
    382          getBuiltinDiagClass(DiagID) != CLASS_ERROR;
    383 }
    384 
    385 /// \brief Determine whether the given built-in diagnostic ID is a
    386 /// Note.
    387 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
    388   return DiagID < diag::DIAG_UPPER_LIMIT &&
    389     getBuiltinDiagClass(DiagID) == CLASS_NOTE;
    390 }
    391 
    392 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
    393 /// ID is for an extension of some sort.  This also returns EnabledByDefault,
    394 /// which is set to indicate whether the diagnostic is ignored by default (in
    395 /// which case -pedantic enables it) or treated as a warning/error by default.
    396 ///
    397 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
    398                                         bool &EnabledByDefault) {
    399   if (DiagID >= diag::DIAG_UPPER_LIMIT ||
    400       getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
    401     return false;
    402 
    403   EnabledByDefault = GetDefaultDiagMapping(DiagID) != diag::MAP_IGNORE;
    404   return true;
    405 }
    406 
    407 /// getDescription - Given a diagnostic ID, return a description of the
    408 /// issue.
    409 llvm::StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
    410   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    411     return Info->getDescription();
    412   return CustomDiagInfo->getDescription(DiagID);
    413 }
    414 
    415 /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
    416 /// object, classify the specified diagnostic ID into a Level, consumable by
    417 /// the DiagnosticClient.
    418 DiagnosticIDs::Level
    419 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
    420                                   const Diagnostic &Diag,
    421                                   diag::Mapping *mapping) const {
    422   // Handle custom diagnostics, which cannot be mapped.
    423   if (DiagID >= diag::DIAG_UPPER_LIMIT)
    424     return CustomDiagInfo->getLevel(DiagID);
    425 
    426   unsigned DiagClass = getBuiltinDiagClass(DiagID);
    427   assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
    428   return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag, mapping);
    429 }
    430 
    431 /// \brief Based on the way the client configured the Diagnostic
    432 /// object, classify the specified diagnostic ID into a Level, consumable by
    433 /// the DiagnosticClient.
    434 ///
    435 /// \param Loc The source location we are interested in finding out the
    436 /// diagnostic state. Can be null in order to query the latest state.
    437 DiagnosticIDs::Level
    438 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
    439                                   SourceLocation Loc,
    440                                   const Diagnostic &Diag,
    441                                   diag::Mapping *mapping) const {
    442   // Specific non-error diagnostics may be mapped to various levels from ignored
    443   // to error.  Errors can only be mapped to fatal.
    444   DiagnosticIDs::Level Result = DiagnosticIDs::Fatal;
    445 
    446   Diagnostic::DiagStatePointsTy::iterator
    447     Pos = Diag.GetDiagStatePointForLoc(Loc);
    448   Diagnostic::DiagState *State = Pos->State;
    449 
    450   // Get the mapping information, if unset, compute it lazily.
    451   unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID,
    452                                                        State);
    453   if (MappingInfo == 0) {
    454     MappingInfo = GetDefaultDiagMapping(DiagID);
    455     Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, State, false, false);
    456   }
    457 
    458   if (mapping)
    459     *mapping = (diag::Mapping) (MappingInfo & 7);
    460 
    461   bool ShouldEmitInSystemHeader = false;
    462 
    463   switch (MappingInfo & 7) {
    464   default: assert(0 && "Unknown mapping!");
    465   case diag::MAP_IGNORE:
    466     // Ignore this, unless this is an extension diagnostic and we're mapping
    467     // them onto warnings or errors.
    468     if (!isBuiltinExtensionDiag(DiagID) ||  // Not an extension
    469         Diag.ExtBehavior == Diagnostic::Ext_Ignore || // Ext ignored
    470         (MappingInfo & 8) != 0)             // User explicitly mapped it.
    471       return DiagnosticIDs::Ignored;
    472     Result = DiagnosticIDs::Warning;
    473     if (Diag.ExtBehavior == Diagnostic::Ext_Error) Result = DiagnosticIDs::Error;
    474     if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
    475       Result = DiagnosticIDs::Fatal;
    476     break;
    477   case diag::MAP_ERROR:
    478     Result = DiagnosticIDs::Error;
    479     if (Diag.ErrorsAsFatal)
    480       Result = DiagnosticIDs::Fatal;
    481     break;
    482   case diag::MAP_FATAL:
    483     Result = DiagnosticIDs::Fatal;
    484     break;
    485   case diag::MAP_WARNING_SHOW_IN_SYSTEM_HEADER:
    486     ShouldEmitInSystemHeader = true;
    487     // continue as MAP_WARNING.
    488   case diag::MAP_WARNING:
    489     // If warnings are globally mapped to ignore or error, do it.
    490     if (Diag.IgnoreAllWarnings)
    491       return DiagnosticIDs::Ignored;
    492 
    493     Result = DiagnosticIDs::Warning;
    494 
    495     // If this is an extension diagnostic and we're in -pedantic-error mode, and
    496     // if the user didn't explicitly map it, upgrade to an error.
    497     if (Diag.ExtBehavior == Diagnostic::Ext_Error &&
    498         (MappingInfo & 8) == 0 &&
    499         isBuiltinExtensionDiag(DiagID))
    500       Result = DiagnosticIDs::Error;
    501 
    502     if (Diag.WarningsAsErrors)
    503       Result = DiagnosticIDs::Error;
    504     if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
    505       Result = DiagnosticIDs::Fatal;
    506     break;
    507 
    508   case diag::MAP_WARNING_NO_WERROR:
    509     // Diagnostics specified with -Wno-error=foo should be set to warnings, but
    510     // not be adjusted by -Werror or -pedantic-errors.
    511     Result = DiagnosticIDs::Warning;
    512 
    513     // If warnings are globally mapped to ignore or error, do it.
    514     if (Diag.IgnoreAllWarnings)
    515       return DiagnosticIDs::Ignored;
    516 
    517     break;
    518 
    519   case diag::MAP_ERROR_NO_WFATAL:
    520     // Diagnostics specified as -Wno-fatal-error=foo should be errors, but
    521     // unaffected by -Wfatal-errors.
    522     Result = DiagnosticIDs::Error;
    523     break;
    524   }
    525 
    526   // Okay, we're about to return this as a "diagnostic to emit" one last check:
    527   // if this is any sort of extension warning, and if we're in an __extension__
    528   // block, silence it.
    529   if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
    530     return DiagnosticIDs::Ignored;
    531 
    532   // If we are in a system header, we ignore it.
    533   // We also want to ignore extensions and warnings in -Werror and
    534   // -pedantic-errors modes, which *map* warnings/extensions to errors.
    535   if (Result >= DiagnosticIDs::Warning &&
    536       DiagClass != CLASS_ERROR &&
    537       // Custom diagnostics always are emitted in system headers.
    538       DiagID < diag::DIAG_UPPER_LIMIT &&
    539       !ShouldEmitInSystemHeader &&
    540       Diag.SuppressSystemWarnings &&
    541       Loc.isValid() &&
    542       Diag.getSourceManager().isInSystemHeader(
    543           Diag.getSourceManager().getInstantiationLoc(Loc)))
    544     return DiagnosticIDs::Ignored;
    545 
    546   return Result;
    547 }
    548 
    549 namespace {
    550   struct WarningOption {
    551     // Be safe with the size of 'NameLen' because we don't statically check if
    552     // the size will fit in the field; the struct size won't decrease with a
    553     // shorter type anyway.
    554     size_t NameLen;
    555     const char *NameStr;
    556     const short *Members;
    557     const short *SubGroups;
    558 
    559     llvm::StringRef getName() const {
    560       return llvm::StringRef(NameStr, NameLen);
    561     }
    562   };
    563 }
    564 
    565 #define GET_DIAG_ARRAYS
    566 #include "clang/Basic/DiagnosticGroups.inc"
    567 #undef GET_DIAG_ARRAYS
    568 
    569 // Second the table of options, sorted by name for fast binary lookup.
    570 static const WarningOption OptionTable[] = {
    571 #define GET_DIAG_TABLE
    572 #include "clang/Basic/DiagnosticGroups.inc"
    573 #undef GET_DIAG_TABLE
    574 };
    575 static const size_t OptionTableSize =
    576 sizeof(OptionTable) / sizeof(OptionTable[0]);
    577 
    578 static bool WarningOptionCompare(const WarningOption &LHS,
    579                                  const WarningOption &RHS) {
    580   return LHS.getName() < RHS.getName();
    581 }
    582 
    583 static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
    584                             SourceLocation Loc, Diagnostic &Diag) {
    585   // Option exists, poke all the members of its diagnostic set.
    586   if (const short *Member = Group->Members) {
    587     for (; *Member != -1; ++Member)
    588       Diag.setDiagnosticMapping(*Member, Mapping, Loc);
    589   }
    590 
    591   // Enable/disable all subgroups along with this one.
    592   if (const short *SubGroups = Group->SubGroups) {
    593     for (; *SubGroups != (short)-1; ++SubGroups)
    594       MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Loc, Diag);
    595   }
    596 }
    597 
    598 /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
    599 /// "unknown-pragmas" to have the specified mapping.  This returns true and
    600 /// ignores the request if "Group" was unknown, false otherwise.
    601 bool DiagnosticIDs::setDiagnosticGroupMapping(llvm::StringRef Group,
    602                                               diag::Mapping Map,
    603                                               SourceLocation Loc,
    604                                               Diagnostic &Diag) const {
    605   assert((Loc.isValid() ||
    606           Diag.DiagStatePoints.empty() ||
    607           Diag.DiagStatePoints.back().Loc.isInvalid()) &&
    608          "Loc should be invalid only when the mapping comes from command-line");
    609   assert((Loc.isInvalid() || Diag.DiagStatePoints.empty() ||
    610           Diag.DiagStatePoints.back().Loc.isInvalid() ||
    611           !Diag.SourceMgr->isBeforeInTranslationUnit(Loc,
    612                                             Diag.DiagStatePoints.back().Loc)) &&
    613          "Source location of new mapping is before the previous one!");
    614 
    615   WarningOption Key = { Group.size(), Group.data(), 0, 0 };
    616   const WarningOption *Found =
    617   std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
    618                    WarningOptionCompare);
    619   if (Found == OptionTable + OptionTableSize ||
    620       Found->getName() != Group)
    621     return true;  // Option not found.
    622 
    623   MapGroupMembers(Found, Map, Loc, Diag);
    624   return false;
    625 }
    626 
    627 /// ProcessDiag - This is the method used to report a diagnostic that is
    628 /// finally fully formed.
    629 bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const {
    630   DiagnosticInfo Info(&Diag);
    631 
    632   if (Diag.SuppressAllDiagnostics)
    633     return false;
    634 
    635   assert(Diag.getClient() && "DiagnosticClient not set!");
    636 
    637   // Figure out the diagnostic level of this message.
    638   DiagnosticIDs::Level DiagLevel;
    639   unsigned DiagID = Info.getID();
    640 
    641   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
    642     // Handle custom diagnostics, which cannot be mapped.
    643     DiagLevel = CustomDiagInfo->getLevel(DiagID);
    644   } else {
    645     // Get the class of the diagnostic.  If this is a NOTE, map it onto whatever
    646     // the diagnostic level was for the previous diagnostic so that it is
    647     // filtered the same as the previous diagnostic.
    648     unsigned DiagClass = getBuiltinDiagClass(DiagID);
    649     if (DiagClass == CLASS_NOTE) {
    650       DiagLevel = DiagnosticIDs::Note;
    651     } else {
    652       DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(),
    653                                      Diag);
    654     }
    655   }
    656 
    657   if (DiagLevel != DiagnosticIDs::Note) {
    658     // Record that a fatal error occurred only when we see a second
    659     // non-note diagnostic. This allows notes to be attached to the
    660     // fatal error, but suppresses any diagnostics that follow those
    661     // notes.
    662     if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
    663       Diag.FatalErrorOccurred = true;
    664 
    665     Diag.LastDiagLevel = DiagLevel;
    666   }
    667 
    668   // If a fatal error has already been emitted, silence all subsequent
    669   // diagnostics.
    670   if (Diag.FatalErrorOccurred) {
    671     if (DiagLevel >= DiagnosticIDs::Error &&
    672         Diag.Client->IncludeInDiagnosticCounts()) {
    673       ++Diag.NumErrors;
    674       ++Diag.NumErrorsSuppressed;
    675     }
    676 
    677     return false;
    678   }
    679 
    680   // If the client doesn't care about this message, don't issue it.  If this is
    681   // a note and the last real diagnostic was ignored, ignore it too.
    682   if (DiagLevel == DiagnosticIDs::Ignored ||
    683       (DiagLevel == DiagnosticIDs::Note &&
    684        Diag.LastDiagLevel == DiagnosticIDs::Ignored))
    685     return false;
    686 
    687   if (DiagLevel >= DiagnosticIDs::Error) {
    688     Diag.TrapErrorOccurred = true;
    689     if (isUnrecoverable(DiagID)) {
    690       Diag.TrapUnrecoverableErrorOccurred = true;
    691       Diag.UnrecoverableErrorOccurred = true;
    692     }
    693 
    694     if (Diag.Client->IncludeInDiagnosticCounts()) {
    695       Diag.ErrorOccurred = true;
    696       ++Diag.NumErrors;
    697     }
    698 
    699     // If we've emitted a lot of errors, emit a fatal error after it to stop a
    700     // flood of bogus errors.
    701     if (Diag.ErrorLimit && Diag.NumErrors >= Diag.ErrorLimit &&
    702         DiagLevel == DiagnosticIDs::Error)
    703       Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
    704   }
    705 
    706   // If we have any Fix-Its, make sure that all of the Fix-Its point into
    707   // source locations that aren't macro instantiations. If any point into
    708   // macro instantiations, remove all of the Fix-Its.
    709   for (unsigned I = 0, N = Diag.NumFixItHints; I != N; ++I) {
    710     const FixItHint &FixIt = Diag.FixItHints[I];
    711     if (FixIt.RemoveRange.isInvalid() ||
    712         FixIt.RemoveRange.getBegin().isMacroID() ||
    713         FixIt.RemoveRange.getEnd().isMacroID()) {
    714       Diag.NumFixItHints = 0;
    715       break;
    716     }
    717   }
    718 
    719   // Finally, report it.
    720   Diag.Client->HandleDiagnostic((Diagnostic::Level)DiagLevel, Info);
    721   if (Diag.Client->IncludeInDiagnosticCounts()) {
    722     if (DiagLevel == DiagnosticIDs::Warning)
    723       ++Diag.NumWarnings;
    724   }
    725 
    726   Diag.CurDiagID = ~0U;
    727 
    728   return true;
    729 }
    730 
    731 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
    732   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
    733     // Custom diagnostics.
    734     return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
    735   }
    736 
    737   // Only errors may be unrecoverable.
    738   if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
    739     return false;
    740 
    741   if (DiagID == diag::err_unavailable ||
    742       DiagID == diag::err_unavailable_message)
    743     return false;
    744 
    745   // Currently we consider all ARC errors as recoverable.
    746   if (getCategoryNumberForDiag(DiagID) ==
    747         diag::DiagCat_Automatic_Reference_Counting_Issue)
    748     return false;
    749 
    750   return true;
    751 }
    752