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/Basic/DiagnosticIDs.h"
     15 #include "clang/Basic/AllDiagnostics.h"
     16 #include "clang/Basic/DiagnosticCategories.h"
     17 #include "clang/Basic/SourceManager.h"
     18 #include "llvm/ADT/SmallVector.h"
     19 #include "llvm/Support/ErrorHandling.h"
     20 #include <map>
     21 using namespace clang;
     22 
     23 //===----------------------------------------------------------------------===//
     24 // Builtin Diagnostic information
     25 //===----------------------------------------------------------------------===//
     26 
     27 namespace {
     28 
     29 // Diagnostic classes.
     30 enum {
     31   CLASS_NOTE       = 0x01,
     32   CLASS_WARNING    = 0x02,
     33   CLASS_EXTENSION  = 0x03,
     34   CLASS_ERROR      = 0x04
     35 };
     36 
     37 struct StaticDiagInfoRec {
     38   unsigned short DiagID;
     39   unsigned Mapping : 3;
     40   unsigned Class : 3;
     41   unsigned SFINAE : 1;
     42   unsigned AccessControl : 1;
     43   unsigned WarnNoWerror : 1;
     44   unsigned WarnShowInSystemHeader : 1;
     45   unsigned Category : 5;
     46 
     47   uint16_t OptionGroupIndex;
     48 
     49   uint16_t DescriptionLen;
     50   const char *DescriptionStr;
     51 
     52   unsigned getOptionGroupIndex() const {
     53     return OptionGroupIndex;
     54   }
     55 
     56   StringRef getDescription() const {
     57     return StringRef(DescriptionStr, DescriptionLen);
     58   }
     59 
     60   bool operator<(const StaticDiagInfoRec &RHS) const {
     61     return DiagID < RHS.DiagID;
     62   }
     63 };
     64 
     65 } // namespace anonymous
     66 
     67 static const StaticDiagInfoRec StaticDiagInfo[] = {
     68 #define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,               \
     69              SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,              \
     70              CATEGORY)                                            \
     71   { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS,           \
     72     NOWERROR, SHOWINSYSHEADER, CATEGORY, GROUP,                   \
     73     STR_SIZE(DESC, uint16_t), DESC },
     74 #include "clang/Basic/DiagnosticCommonKinds.inc"
     75 #include "clang/Basic/DiagnosticDriverKinds.inc"
     76 #include "clang/Basic/DiagnosticFrontendKinds.inc"
     77 #include "clang/Basic/DiagnosticSerializationKinds.inc"
     78 #include "clang/Basic/DiagnosticLexKinds.inc"
     79 #include "clang/Basic/DiagnosticParseKinds.inc"
     80 #include "clang/Basic/DiagnosticASTKinds.inc"
     81 #include "clang/Basic/DiagnosticCommentKinds.inc"
     82 #include "clang/Basic/DiagnosticSemaKinds.inc"
     83 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
     84 #undef DIAG
     85   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
     86 };
     87 
     88 static const unsigned StaticDiagInfoSize =
     89   sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
     90 
     91 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
     92 /// or null if the ID is invalid.
     93 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
     94   // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
     95 #ifndef NDEBUG
     96   static bool IsFirst = true;
     97   if (IsFirst) {
     98     for (unsigned i = 1; i != StaticDiagInfoSize; ++i) {
     99       assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
    100              "Diag ID conflict, the enums at the start of clang::diag (in "
    101              "DiagnosticIDs.h) probably need to be increased");
    102 
    103       assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
    104              "Improperly sorted diag info");
    105     }
    106     IsFirst = false;
    107   }
    108 #endif
    109 
    110   // Out of bounds diag. Can't be in the table.
    111   using namespace diag;
    112   if (DiagID >= DIAG_UPPER_LIMIT)
    113     return 0;
    114 
    115   // Compute the index of the requested diagnostic in the static table.
    116   // 1. Add the number of diagnostics in each category preceeding the
    117   //    diagnostic and of the category the diagnostic is in. This gives us
    118   //    the offset of the category in the table.
    119   // 2. Subtract the number of IDs in each category from our ID. This gives us
    120   //    the offset of the diagnostic in the category.
    121   // This is cheaper than a binary search on the table as it doesn't touch
    122   // memory at all.
    123   unsigned Offset = 0;
    124   unsigned ID = DiagID;
    125 #define DIAG_START_COMMON 0 // Sentinel value.
    126 #define CATEGORY(NAME, PREV) \
    127   if (DiagID > DIAG_START_##NAME) { \
    128     Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
    129     ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
    130   }
    131 CATEGORY(DRIVER, COMMON)
    132 CATEGORY(FRONTEND, DRIVER)
    133 CATEGORY(SERIALIZATION, FRONTEND)
    134 CATEGORY(LEX, SERIALIZATION)
    135 CATEGORY(PARSE, LEX)
    136 CATEGORY(AST, PARSE)
    137 CATEGORY(COMMENT, AST)
    138 CATEGORY(SEMA, COMMENT)
    139 CATEGORY(ANALYSIS, SEMA)
    140 #undef CATEGORY
    141 #undef DIAG_START_COMMON
    142 
    143   // Avoid out of bounds reads.
    144   if (ID + Offset >= StaticDiagInfoSize)
    145     return 0;
    146 
    147   assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize);
    148 
    149   const StaticDiagInfoRec *Found = &StaticDiagInfo[ID + Offset];
    150   // If the diag id doesn't match we found a different diag, abort. This can
    151   // happen when this function is called with an ID that points into a hole in
    152   // the diagID space.
    153   if (Found->DiagID != DiagID)
    154     return 0;
    155   return Found;
    156 }
    157 
    158 static DiagnosticMappingInfo GetDefaultDiagMappingInfo(unsigned DiagID) {
    159   DiagnosticMappingInfo Info = DiagnosticMappingInfo::Make(
    160     diag::MAP_FATAL, /*IsUser=*/false, /*IsPragma=*/false);
    161 
    162   if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) {
    163     Info.setMapping((diag::Mapping) StaticInfo->Mapping);
    164 
    165     if (StaticInfo->WarnNoWerror) {
    166       assert(Info.getMapping() == diag::MAP_WARNING &&
    167              "Unexpected mapping with no-Werror bit!");
    168       Info.setNoWarningAsError(true);
    169     }
    170 
    171     if (StaticInfo->WarnShowInSystemHeader) {
    172       assert(Info.getMapping() == diag::MAP_WARNING &&
    173              "Unexpected mapping with show-in-system-header bit!");
    174       Info.setShowInSystemHeader(true);
    175     }
    176   }
    177 
    178   return Info;
    179 }
    180 
    181 /// getCategoryNumberForDiag - Return the category number that a specified
    182 /// DiagID belongs to, or 0 if no category.
    183 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
    184   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    185     return Info->Category;
    186   return 0;
    187 }
    188 
    189 namespace {
    190   // The diagnostic category names.
    191   struct StaticDiagCategoryRec {
    192     const char *NameStr;
    193     uint8_t NameLen;
    194 
    195     StringRef getName() const {
    196       return StringRef(NameStr, NameLen);
    197     }
    198   };
    199 }
    200 
    201 // Unfortunately, the split between DiagnosticIDs and Diagnostic is not
    202 // particularly clean, but for now we just implement this method here so we can
    203 // access GetDefaultDiagMapping.
    204 DiagnosticMappingInfo &DiagnosticsEngine::DiagState::getOrAddMappingInfo(
    205   diag::kind Diag)
    206 {
    207   std::pair<iterator, bool> Result = DiagMap.insert(
    208     std::make_pair(Diag, DiagnosticMappingInfo()));
    209 
    210   // Initialize the entry if we added it.
    211   if (Result.second)
    212     Result.first->second = GetDefaultDiagMappingInfo(Diag);
    213 
    214   return Result.first->second;
    215 }
    216 
    217 static const StaticDiagCategoryRec CategoryNameTable[] = {
    218 #define GET_CATEGORY_TABLE
    219 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
    220 #include "clang/Basic/DiagnosticGroups.inc"
    221 #undef GET_CATEGORY_TABLE
    222   { 0, 0 }
    223 };
    224 
    225 /// getNumberOfCategories - Return the number of categories
    226 unsigned DiagnosticIDs::getNumberOfCategories() {
    227   return sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
    228 }
    229 
    230 /// getCategoryNameFromID - Given a category ID, return the name of the
    231 /// category, an empty string if CategoryID is zero, or null if CategoryID is
    232 /// invalid.
    233 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
    234   if (CategoryID >= getNumberOfCategories())
    235    return StringRef();
    236   return CategoryNameTable[CategoryID].getName();
    237 }
    238 
    239 
    240 
    241 DiagnosticIDs::SFINAEResponse
    242 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
    243   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
    244     if (Info->AccessControl)
    245       return SFINAE_AccessControl;
    246 
    247     if (!Info->SFINAE)
    248       return SFINAE_Report;
    249 
    250     if (Info->Class == CLASS_ERROR)
    251       return SFINAE_SubstitutionFailure;
    252 
    253     // Suppress notes, warnings, and extensions;
    254     return SFINAE_Suppress;
    255   }
    256 
    257   return SFINAE_Report;
    258 }
    259 
    260 /// getBuiltinDiagClass - Return the class field of the diagnostic.
    261 ///
    262 static unsigned getBuiltinDiagClass(unsigned DiagID) {
    263   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    264     return Info->Class;
    265   return ~0U;
    266 }
    267 
    268 //===----------------------------------------------------------------------===//
    269 // Custom Diagnostic information
    270 //===----------------------------------------------------------------------===//
    271 
    272 namespace clang {
    273   namespace diag {
    274     class CustomDiagInfo {
    275       typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
    276       std::vector<DiagDesc> DiagInfo;
    277       std::map<DiagDesc, unsigned> DiagIDs;
    278     public:
    279 
    280       /// getDescription - Return the description of the specified custom
    281       /// diagnostic.
    282       StringRef getDescription(unsigned DiagID) const {
    283         assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
    284                "Invalid diagnostic ID");
    285         return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
    286       }
    287 
    288       /// getLevel - Return the level of the specified custom diagnostic.
    289       DiagnosticIDs::Level getLevel(unsigned DiagID) const {
    290         assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
    291                "Invalid diagnostic ID");
    292         return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
    293       }
    294 
    295       unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
    296                                  DiagnosticIDs &Diags) {
    297         DiagDesc D(L, Message);
    298         // Check to see if it already exists.
    299         std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
    300         if (I != DiagIDs.end() && I->first == D)
    301           return I->second;
    302 
    303         // If not, assign a new ID.
    304         unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
    305         DiagIDs.insert(std::make_pair(D, ID));
    306         DiagInfo.push_back(D);
    307         return ID;
    308       }
    309     };
    310 
    311   } // end diag namespace
    312 } // end clang namespace
    313 
    314 
    315 //===----------------------------------------------------------------------===//
    316 // Common Diagnostic implementation
    317 //===----------------------------------------------------------------------===//
    318 
    319 DiagnosticIDs::DiagnosticIDs() {
    320   CustomDiagInfo = 0;
    321 }
    322 
    323 DiagnosticIDs::~DiagnosticIDs() {
    324   delete CustomDiagInfo;
    325 }
    326 
    327 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
    328 /// and level.  If this is the first request for this diagnostic, it is
    329 /// registered and created, otherwise the existing ID is returned.
    330 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef Message) {
    331   if (CustomDiagInfo == 0)
    332     CustomDiagInfo = new diag::CustomDiagInfo();
    333   return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
    334 }
    335 
    336 
    337 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
    338 /// level of the specified diagnostic ID is a Warning or Extension.
    339 /// This only works on builtin diagnostics, not custom ones, and is not legal to
    340 /// call on NOTEs.
    341 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
    342   return DiagID < diag::DIAG_UPPER_LIMIT &&
    343          getBuiltinDiagClass(DiagID) != CLASS_ERROR;
    344 }
    345 
    346 /// \brief Determine whether the given built-in diagnostic ID is a
    347 /// Note.
    348 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
    349   return DiagID < diag::DIAG_UPPER_LIMIT &&
    350     getBuiltinDiagClass(DiagID) == CLASS_NOTE;
    351 }
    352 
    353 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
    354 /// ID is for an extension of some sort.  This also returns EnabledByDefault,
    355 /// which is set to indicate whether the diagnostic is ignored by default (in
    356 /// which case -pedantic enables it) or treated as a warning/error by default.
    357 ///
    358 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
    359                                         bool &EnabledByDefault) {
    360   if (DiagID >= diag::DIAG_UPPER_LIMIT ||
    361       getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
    362     return false;
    363 
    364   EnabledByDefault =
    365     GetDefaultDiagMappingInfo(DiagID).getMapping() != diag::MAP_IGNORE;
    366   return true;
    367 }
    368 
    369 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
    370   if (DiagID >= diag::DIAG_UPPER_LIMIT)
    371     return false;
    372 
    373   return GetDefaultDiagMappingInfo(DiagID).getMapping() == diag::MAP_ERROR;
    374 }
    375 
    376 /// getDescription - Given a diagnostic ID, return a description of the
    377 /// issue.
    378 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
    379   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    380     return Info->getDescription();
    381   return CustomDiagInfo->getDescription(DiagID);
    382 }
    383 
    384 /// getDiagnosticLevel - Based on the way the client configured the
    385 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level,
    386 /// by consumable the DiagnosticClient.
    387 DiagnosticIDs::Level
    388 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
    389                                   const DiagnosticsEngine &Diag) const {
    390   // Handle custom diagnostics, which cannot be mapped.
    391   if (DiagID >= diag::DIAG_UPPER_LIMIT)
    392     return CustomDiagInfo->getLevel(DiagID);
    393 
    394   unsigned DiagClass = getBuiltinDiagClass(DiagID);
    395   if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note;
    396   return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag);
    397 }
    398 
    399 /// \brief Based on the way the client configured the Diagnostic
    400 /// object, classify the specified diagnostic ID into a Level, consumable by
    401 /// the DiagnosticClient.
    402 ///
    403 /// \param Loc The source location we are interested in finding out the
    404 /// diagnostic state. Can be null in order to query the latest state.
    405 DiagnosticIDs::Level
    406 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
    407                                   SourceLocation Loc,
    408                                   const DiagnosticsEngine &Diag) const {
    409   // Specific non-error diagnostics may be mapped to various levels from ignored
    410   // to error.  Errors can only be mapped to fatal.
    411   DiagnosticIDs::Level Result = DiagnosticIDs::Fatal;
    412 
    413   DiagnosticsEngine::DiagStatePointsTy::iterator
    414     Pos = Diag.GetDiagStatePointForLoc(Loc);
    415   DiagnosticsEngine::DiagState *State = Pos->State;
    416 
    417   // Get the mapping information, or compute it lazily.
    418   DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo(
    419     (diag::kind)DiagID);
    420 
    421   switch (MappingInfo.getMapping()) {
    422   case diag::MAP_IGNORE:
    423     Result = DiagnosticIDs::Ignored;
    424     break;
    425   case diag::MAP_WARNING:
    426     Result = DiagnosticIDs::Warning;
    427     break;
    428   case diag::MAP_ERROR:
    429     Result = DiagnosticIDs::Error;
    430     break;
    431   case diag::MAP_FATAL:
    432     Result = DiagnosticIDs::Fatal;
    433     break;
    434   }
    435 
    436   // Upgrade ignored diagnostics if -Weverything is enabled.
    437   if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored &&
    438       !MappingInfo.isUser())
    439     Result = DiagnosticIDs::Warning;
    440 
    441   // Ignore -pedantic diagnostics inside __extension__ blocks.
    442   // (The diagnostics controlled by -pedantic are the extension diagnostics
    443   // that are not enabled by default.)
    444   bool EnabledByDefault = false;
    445   bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
    446   if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
    447     return DiagnosticIDs::Ignored;
    448 
    449   // For extension diagnostics that haven't been explicitly mapped, check if we
    450   // should upgrade the diagnostic.
    451   if (IsExtensionDiag && !MappingInfo.isUser()) {
    452     switch (Diag.ExtBehavior) {
    453     case DiagnosticsEngine::Ext_Ignore:
    454       break;
    455     case DiagnosticsEngine::Ext_Warn:
    456       // Upgrade ignored diagnostics to warnings.
    457       if (Result == DiagnosticIDs::Ignored)
    458         Result = DiagnosticIDs::Warning;
    459       break;
    460     case DiagnosticsEngine::Ext_Error:
    461       // Upgrade ignored or warning diagnostics to errors.
    462       if (Result == DiagnosticIDs::Ignored || Result == DiagnosticIDs::Warning)
    463         Result = DiagnosticIDs::Error;
    464       break;
    465     }
    466   }
    467 
    468   // At this point, ignored errors can no longer be upgraded.
    469   if (Result == DiagnosticIDs::Ignored)
    470     return Result;
    471 
    472   // Honor -w, which is lower in priority than pedantic-errors, but higher than
    473   // -Werror.
    474   if (Result == DiagnosticIDs::Warning && Diag.IgnoreAllWarnings)
    475     return DiagnosticIDs::Ignored;
    476 
    477   // If -Werror is enabled, map warnings to errors unless explicitly disabled.
    478   if (Result == DiagnosticIDs::Warning) {
    479     if (Diag.WarningsAsErrors && !MappingInfo.hasNoWarningAsError())
    480       Result = DiagnosticIDs::Error;
    481   }
    482 
    483   // If -Wfatal-errors is enabled, map errors to fatal unless explicity
    484   // disabled.
    485   if (Result == DiagnosticIDs::Error) {
    486     if (Diag.ErrorsAsFatal && !MappingInfo.hasNoErrorAsFatal())
    487       Result = DiagnosticIDs::Fatal;
    488   }
    489 
    490   // If we are in a system header, we ignore it. We look at the diagnostic class
    491   // because we also want to ignore extensions and warnings in -Werror and
    492   // -pedantic-errors modes, which *map* warnings/extensions to errors.
    493   if (Result >= DiagnosticIDs::Warning &&
    494       DiagClass != CLASS_ERROR &&
    495       // Custom diagnostics always are emitted in system headers.
    496       DiagID < diag::DIAG_UPPER_LIMIT &&
    497       !MappingInfo.hasShowInSystemHeader() &&
    498       Diag.SuppressSystemWarnings &&
    499       Loc.isValid() &&
    500       Diag.getSourceManager().isInSystemHeader(
    501           Diag.getSourceManager().getExpansionLoc(Loc)))
    502     return DiagnosticIDs::Ignored;
    503 
    504   return Result;
    505 }
    506 
    507 struct clang::WarningOption {
    508   // Be safe with the size of 'NameLen' because we don't statically check if
    509   // the size will fit in the field; the struct size won't decrease with a
    510   // shorter type anyway.
    511   size_t NameLen;
    512   const char *NameStr;
    513   const short *Members;
    514   const short *SubGroups;
    515 
    516   StringRef getName() const {
    517     return StringRef(NameStr, NameLen);
    518   }
    519 };
    520 
    521 #define GET_DIAG_ARRAYS
    522 #include "clang/Basic/DiagnosticGroups.inc"
    523 #undef GET_DIAG_ARRAYS
    524 
    525 // Second the table of options, sorted by name for fast binary lookup.
    526 static const WarningOption OptionTable[] = {
    527 #define GET_DIAG_TABLE
    528 #include "clang/Basic/DiagnosticGroups.inc"
    529 #undef GET_DIAG_TABLE
    530 };
    531 static const size_t OptionTableSize =
    532 sizeof(OptionTable) / sizeof(OptionTable[0]);
    533 
    534 static bool WarningOptionCompare(const WarningOption &LHS,
    535                                  const WarningOption &RHS) {
    536   return LHS.getName() < RHS.getName();
    537 }
    538 
    539 /// getWarningOptionForDiag - Return the lowest-level warning option that
    540 /// enables the specified diagnostic.  If there is no -Wfoo flag that controls
    541 /// the diagnostic, this returns null.
    542 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
    543   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
    544     return OptionTable[Info->getOptionGroupIndex()].getName();
    545   return StringRef();
    546 }
    547 
    548 void DiagnosticIDs::getDiagnosticsInGroup(
    549     const WarningOption *Group,
    550     SmallVectorImpl<diag::kind> &Diags) const {
    551   // Add the members of the option diagnostic set.
    552   if (const short *Member = Group->Members) {
    553     for (; *Member != -1; ++Member)
    554       Diags.push_back(*Member);
    555   }
    556 
    557   // Add the members of the subgroups.
    558   if (const short *SubGroups = Group->SubGroups) {
    559     for (; *SubGroups != (short)-1; ++SubGroups)
    560       getDiagnosticsInGroup(&OptionTable[(short)*SubGroups], Diags);
    561   }
    562 }
    563 
    564 bool DiagnosticIDs::getDiagnosticsInGroup(
    565     StringRef Group,
    566     SmallVectorImpl<diag::kind> &Diags) const {
    567   WarningOption Key = { Group.size(), Group.data(), 0, 0 };
    568   const WarningOption *Found =
    569   std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
    570                    WarningOptionCompare);
    571   if (Found == OptionTable + OptionTableSize ||
    572       Found->getName() != Group)
    573     return true; // Option not found.
    574 
    575   getDiagnosticsInGroup(Found, Diags);
    576   return false;
    577 }
    578 
    579 void DiagnosticIDs::getAllDiagnostics(
    580                                SmallVectorImpl<diag::kind> &Diags) const {
    581   for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
    582     Diags.push_back(StaticDiagInfo[i].DiagID);
    583 }
    584 
    585 StringRef DiagnosticIDs::getNearestWarningOption(StringRef Group) {
    586   StringRef Best;
    587   unsigned BestDistance = Group.size() + 1; // Sanity threshold.
    588   for (const WarningOption *i = OptionTable, *e = OptionTable + OptionTableSize;
    589        i != e; ++i) {
    590     // Don't suggest ignored warning flags.
    591     if (!i->Members && !i->SubGroups)
    592       continue;
    593 
    594     unsigned Distance = i->getName().edit_distance(Group, true, BestDistance);
    595     if (Distance == BestDistance) {
    596       // Two matches with the same distance, don't prefer one over the other.
    597       Best = "";
    598     } else if (Distance < BestDistance) {
    599       // This is a better match.
    600       Best = i->getName();
    601       BestDistance = Distance;
    602     }
    603   }
    604 
    605   return Best;
    606 }
    607 
    608 /// ProcessDiag - This is the method used to report a diagnostic that is
    609 /// finally fully formed.
    610 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
    611   Diagnostic Info(&Diag);
    612 
    613   if (Diag.SuppressAllDiagnostics)
    614     return false;
    615 
    616   assert(Diag.getClient() && "DiagnosticClient not set!");
    617 
    618   // Figure out the diagnostic level of this message.
    619   unsigned DiagID = Info.getID();
    620   DiagnosticIDs::Level DiagLevel
    621     = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
    622 
    623   if (DiagLevel != DiagnosticIDs::Note) {
    624     // Record that a fatal error occurred only when we see a second
    625     // non-note diagnostic. This allows notes to be attached to the
    626     // fatal error, but suppresses any diagnostics that follow those
    627     // notes.
    628     if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
    629       Diag.FatalErrorOccurred = true;
    630 
    631     Diag.LastDiagLevel = DiagLevel;
    632   }
    633 
    634   // Update counts for DiagnosticErrorTrap even if a fatal error occurred.
    635   if (DiagLevel >= DiagnosticIDs::Error) {
    636     ++Diag.TrapNumErrorsOccurred;
    637     if (isUnrecoverable(DiagID))
    638       ++Diag.TrapNumUnrecoverableErrorsOccurred;
    639   }
    640 
    641   // If a fatal error has already been emitted, silence all subsequent
    642   // diagnostics.
    643   if (Diag.FatalErrorOccurred) {
    644     if (DiagLevel >= DiagnosticIDs::Error &&
    645         Diag.Client->IncludeInDiagnosticCounts()) {
    646       ++Diag.NumErrors;
    647       ++Diag.NumErrorsSuppressed;
    648     }
    649 
    650     return false;
    651   }
    652 
    653   // If the client doesn't care about this message, don't issue it.  If this is
    654   // a note and the last real diagnostic was ignored, ignore it too.
    655   if (DiagLevel == DiagnosticIDs::Ignored ||
    656       (DiagLevel == DiagnosticIDs::Note &&
    657        Diag.LastDiagLevel == DiagnosticIDs::Ignored))
    658     return false;
    659 
    660   if (DiagLevel >= DiagnosticIDs::Error) {
    661     if (isUnrecoverable(DiagID))
    662       Diag.UnrecoverableErrorOccurred = true;
    663 
    664     // Warnings which have been upgraded to errors do not prevent compilation.
    665     if (isDefaultMappingAsError(DiagID))
    666       Diag.UncompilableErrorOccurred = true;
    667 
    668     Diag.ErrorOccurred = true;
    669     if (Diag.Client->IncludeInDiagnosticCounts()) {
    670       ++Diag.NumErrors;
    671     }
    672 
    673     // If we've emitted a lot of errors, emit a fatal error instead of it to
    674     // stop a flood of bogus errors.
    675     if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
    676         DiagLevel == DiagnosticIDs::Error) {
    677       Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
    678       return false;
    679     }
    680   }
    681 
    682   // Finally, report it.
    683   EmitDiag(Diag, DiagLevel);
    684   return true;
    685 }
    686 
    687 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
    688   Diagnostic Info(&Diag);
    689   assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
    690 
    691   Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
    692   if (Diag.Client->IncludeInDiagnosticCounts()) {
    693     if (DiagLevel == DiagnosticIDs::Warning)
    694       ++Diag.NumWarnings;
    695   }
    696 
    697   Diag.CurDiagID = ~0U;
    698 }
    699 
    700 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
    701   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
    702     // Custom diagnostics.
    703     return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
    704   }
    705 
    706   // Only errors may be unrecoverable.
    707   if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
    708     return false;
    709 
    710   if (DiagID == diag::err_unavailable ||
    711       DiagID == diag::err_unavailable_message)
    712     return false;
    713 
    714   // Currently we consider all ARC errors as recoverable.
    715   if (isARCDiagnostic(DiagID))
    716     return false;
    717 
    718   return true;
    719 }
    720 
    721 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
    722   unsigned cat = getCategoryNumberForDiag(DiagID);
    723   return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
    724 }
    725