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