clang API Documentation

DiagnosticIDs.cpp
Go to the documentation of this file.
00001 //===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file implements the Diagnostic IDs-related interfaces.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/Basic/DiagnosticIDs.h"
00015 #include "clang/Basic/AllDiagnostics.h"
00016 #include "clang/Basic/DiagnosticCategories.h"
00017 #include "clang/Basic/SourceManager.h"
00018 #include "llvm/ADT/STLExtras.h"
00019 #include "llvm/ADT/SmallVector.h"
00020 #include "llvm/Support/ErrorHandling.h"
00021 #include <map>
00022 using namespace clang;
00023 
00024 //===----------------------------------------------------------------------===//
00025 // Builtin Diagnostic information
00026 //===----------------------------------------------------------------------===//
00027 
00028 namespace {
00029 
00030 // Diagnostic classes.
00031 enum {
00032   CLASS_NOTE       = 0x01,
00033   CLASS_REMARK     = 0x02,
00034   CLASS_WARNING    = 0x03,
00035   CLASS_EXTENSION  = 0x04,
00036   CLASS_ERROR      = 0x05
00037 };
00038 
00039 struct StaticDiagInfoRec {
00040   uint16_t DiagID;
00041   unsigned DefaultSeverity : 3;
00042   unsigned Class : 3;
00043   unsigned SFINAE : 2;
00044   unsigned WarnNoWerror : 1;
00045   unsigned WarnShowInSystemHeader : 1;
00046   unsigned Category : 5;
00047 
00048   uint16_t OptionGroupIndex;
00049 
00050   uint16_t DescriptionLen;
00051   const char *DescriptionStr;
00052 
00053   unsigned getOptionGroupIndex() const {
00054     return OptionGroupIndex;
00055   }
00056 
00057   StringRef getDescription() const {
00058     return StringRef(DescriptionStr, DescriptionLen);
00059   }
00060 
00061   diag::Flavor getFlavor() const {
00062     return Class == CLASS_REMARK ? diag::Flavor::Remark
00063                                  : diag::Flavor::WarningOrError;
00064   }
00065 
00066   bool operator<(const StaticDiagInfoRec &RHS) const {
00067     return DiagID < RHS.DiagID;
00068   }
00069 };
00070 
00071 } // namespace anonymous
00072 
00073 static const StaticDiagInfoRec StaticDiagInfo[] = {
00074 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR,     \
00075              SHOWINSYSHEADER, CATEGORY)                                        \
00076   {                                                                            \
00077     diag::ENUM, DEFAULT_SEVERITY, CLASS, DiagnosticIDs::SFINAE, NOWERROR,      \
00078         SHOWINSYSHEADER, CATEGORY, GROUP, STR_SIZE(DESC, uint16_t), DESC       \
00079   }                                                                            \
00080   ,
00081 #include "clang/Basic/DiagnosticCommonKinds.inc"
00082 #include "clang/Basic/DiagnosticDriverKinds.inc"
00083 #include "clang/Basic/DiagnosticFrontendKinds.inc"
00084 #include "clang/Basic/DiagnosticSerializationKinds.inc"
00085 #include "clang/Basic/DiagnosticLexKinds.inc"
00086 #include "clang/Basic/DiagnosticParseKinds.inc"
00087 #include "clang/Basic/DiagnosticASTKinds.inc"
00088 #include "clang/Basic/DiagnosticCommentKinds.inc"
00089 #include "clang/Basic/DiagnosticSemaKinds.inc"
00090 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
00091 #undef DIAG
00092 };
00093 
00094 static const unsigned StaticDiagInfoSize = llvm::array_lengthof(StaticDiagInfo);
00095 
00096 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
00097 /// or null if the ID is invalid.
00098 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
00099   // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
00100 #ifndef NDEBUG
00101   static bool IsFirst = true; // So the check is only performed on first call.
00102   if (IsFirst) {
00103     for (unsigned i = 1; i != StaticDiagInfoSize; ++i) {
00104       assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
00105              "Diag ID conflict, the enums at the start of clang::diag (in "
00106              "DiagnosticIDs.h) probably need to be increased");
00107 
00108       assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
00109              "Improperly sorted diag info");
00110     }
00111     IsFirst = false;
00112   }
00113 #endif
00114 
00115   // Out of bounds diag. Can't be in the table.
00116   using namespace diag;
00117   if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
00118     return nullptr;
00119 
00120   // Compute the index of the requested diagnostic in the static table.
00121   // 1. Add the number of diagnostics in each category preceding the
00122   //    diagnostic and of the category the diagnostic is in. This gives us
00123   //    the offset of the category in the table.
00124   // 2. Subtract the number of IDs in each category from our ID. This gives us
00125   //    the offset of the diagnostic in the category.
00126   // This is cheaper than a binary search on the table as it doesn't touch
00127   // memory at all.
00128   unsigned Offset = 0;
00129   unsigned ID = DiagID - DIAG_START_COMMON - 1;
00130 #define CATEGORY(NAME, PREV) \
00131   if (DiagID > DIAG_START_##NAME) { \
00132     Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
00133     ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
00134   }
00135 CATEGORY(DRIVER, COMMON)
00136 CATEGORY(FRONTEND, DRIVER)
00137 CATEGORY(SERIALIZATION, FRONTEND)
00138 CATEGORY(LEX, SERIALIZATION)
00139 CATEGORY(PARSE, LEX)
00140 CATEGORY(AST, PARSE)
00141 CATEGORY(COMMENT, AST)
00142 CATEGORY(SEMA, COMMENT)
00143 CATEGORY(ANALYSIS, SEMA)
00144 #undef CATEGORY
00145 
00146   // Avoid out of bounds reads.
00147   if (ID + Offset >= StaticDiagInfoSize)
00148     return nullptr;
00149 
00150   assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize);
00151 
00152   const StaticDiagInfoRec *Found = &StaticDiagInfo[ID + Offset];
00153   // If the diag id doesn't match we found a different diag, abort. This can
00154   // happen when this function is called with an ID that points into a hole in
00155   // the diagID space.
00156   if (Found->DiagID != DiagID)
00157     return nullptr;
00158   return Found;
00159 }
00160 
00161 static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID) {
00162   DiagnosticMapping Info = DiagnosticMapping::Make(
00163       diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false);
00164 
00165   if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) {
00166     Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity);
00167 
00168     if (StaticInfo->WarnNoWerror) {
00169       assert(Info.getSeverity() == diag::Severity::Warning &&
00170              "Unexpected mapping with no-Werror bit!");
00171       Info.setNoWarningAsError(true);
00172     }
00173   }
00174 
00175   return Info;
00176 }
00177 
00178 /// getCategoryNumberForDiag - Return the category number that a specified
00179 /// DiagID belongs to, or 0 if no category.
00180 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
00181   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
00182     return Info->Category;
00183   return 0;
00184 }
00185 
00186 namespace {
00187   // The diagnostic category names.
00188   struct StaticDiagCategoryRec {
00189     const char *NameStr;
00190     uint8_t NameLen;
00191 
00192     StringRef getName() const {
00193       return StringRef(NameStr, NameLen);
00194     }
00195   };
00196 }
00197 
00198 // Unfortunately, the split between DiagnosticIDs and Diagnostic is not
00199 // particularly clean, but for now we just implement this method here so we can
00200 // access GetDefaultDiagMapping.
00201 DiagnosticMapping &
00202 DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) {
00203   std::pair<iterator, bool> Result =
00204       DiagMap.insert(std::make_pair(Diag, DiagnosticMapping()));
00205 
00206   // Initialize the entry if we added it.
00207   if (Result.second)
00208     Result.first->second = GetDefaultDiagMapping(Diag);
00209 
00210   return Result.first->second;
00211 }
00212 
00213 static const StaticDiagCategoryRec CategoryNameTable[] = {
00214 #define GET_CATEGORY_TABLE
00215 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
00216 #include "clang/Basic/DiagnosticGroups.inc"
00217 #undef GET_CATEGORY_TABLE
00218   { nullptr, 0 }
00219 };
00220 
00221 /// getNumberOfCategories - Return the number of categories
00222 unsigned DiagnosticIDs::getNumberOfCategories() {
00223   return llvm::array_lengthof(CategoryNameTable) - 1;
00224 }
00225 
00226 /// getCategoryNameFromID - Given a category ID, return the name of the
00227 /// category, an empty string if CategoryID is zero, or null if CategoryID is
00228 /// invalid.
00229 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
00230   if (CategoryID >= getNumberOfCategories())
00231    return StringRef();
00232   return CategoryNameTable[CategoryID].getName();
00233 }
00234 
00235 
00236 
00237 DiagnosticIDs::SFINAEResponse
00238 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
00239   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
00240     return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE);
00241   return SFINAE_Report;
00242 }
00243 
00244 /// getBuiltinDiagClass - Return the class field of the diagnostic.
00245 ///
00246 static unsigned getBuiltinDiagClass(unsigned DiagID) {
00247   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
00248     return Info->Class;
00249   return ~0U;
00250 }
00251 
00252 //===----------------------------------------------------------------------===//
00253 // Custom Diagnostic information
00254 //===----------------------------------------------------------------------===//
00255 
00256 namespace clang {
00257   namespace diag {
00258     class CustomDiagInfo {
00259       typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
00260       std::vector<DiagDesc> DiagInfo;
00261       std::map<DiagDesc, unsigned> DiagIDs;
00262     public:
00263 
00264       /// getDescription - Return the description of the specified custom
00265       /// diagnostic.
00266       StringRef getDescription(unsigned DiagID) const {
00267         assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
00268                "Invalid diagnostic ID");
00269         return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
00270       }
00271 
00272       /// getLevel - Return the level of the specified custom diagnostic.
00273       DiagnosticIDs::Level getLevel(unsigned DiagID) const {
00274         assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
00275                "Invalid diagnostic ID");
00276         return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
00277       }
00278 
00279       unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
00280                                  DiagnosticIDs &Diags) {
00281         DiagDesc D(L, Message);
00282         // Check to see if it already exists.
00283         std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
00284         if (I != DiagIDs.end() && I->first == D)
00285           return I->second;
00286 
00287         // If not, assign a new ID.
00288         unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
00289         DiagIDs.insert(std::make_pair(D, ID));
00290         DiagInfo.push_back(D);
00291         return ID;
00292       }
00293     };
00294 
00295   } // end diag namespace
00296 } // end clang namespace
00297 
00298 
00299 //===----------------------------------------------------------------------===//
00300 // Common Diagnostic implementation
00301 //===----------------------------------------------------------------------===//
00302 
00303 DiagnosticIDs::DiagnosticIDs() { CustomDiagInfo = nullptr; }
00304 
00305 DiagnosticIDs::~DiagnosticIDs() {
00306   delete CustomDiagInfo;
00307 }
00308 
00309 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
00310 /// and level.  If this is the first request for this diagnostic, it is
00311 /// registered and created, otherwise the existing ID is returned.
00312 ///
00313 /// \param FormatString A fixed diagnostic format string that will be hashed and
00314 /// mapped to a unique DiagID.
00315 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
00316   if (!CustomDiagInfo)
00317     CustomDiagInfo = new diag::CustomDiagInfo();
00318   return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
00319 }
00320 
00321 
00322 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
00323 /// level of the specified diagnostic ID is a Warning or Extension.
00324 /// This only works on builtin diagnostics, not custom ones, and is not legal to
00325 /// call on NOTEs.
00326 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
00327   return DiagID < diag::DIAG_UPPER_LIMIT &&
00328          getBuiltinDiagClass(DiagID) != CLASS_ERROR;
00329 }
00330 
00331 /// \brief Determine whether the given built-in diagnostic ID is a
00332 /// Note.
00333 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
00334   return DiagID < diag::DIAG_UPPER_LIMIT &&
00335     getBuiltinDiagClass(DiagID) == CLASS_NOTE;
00336 }
00337 
00338 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
00339 /// ID is for an extension of some sort.  This also returns EnabledByDefault,
00340 /// which is set to indicate whether the diagnostic is ignored by default (in
00341 /// which case -pedantic enables it) or treated as a warning/error by default.
00342 ///
00343 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
00344                                         bool &EnabledByDefault) {
00345   if (DiagID >= diag::DIAG_UPPER_LIMIT ||
00346       getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
00347     return false;
00348 
00349   EnabledByDefault =
00350       GetDefaultDiagMapping(DiagID).getSeverity() != diag::Severity::Ignored;
00351   return true;
00352 }
00353 
00354 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
00355   if (DiagID >= diag::DIAG_UPPER_LIMIT)
00356     return false;
00357 
00358   return GetDefaultDiagMapping(DiagID).getSeverity() == diag::Severity::Error;
00359 }
00360 
00361 /// getDescription - Given a diagnostic ID, return a description of the
00362 /// issue.
00363 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
00364   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
00365     return Info->getDescription();
00366   assert(CustomDiagInfo && "Invalid CustomDiagInfo");
00367   return CustomDiagInfo->getDescription(DiagID);
00368 }
00369 
00370 static DiagnosticIDs::Level toLevel(diag::Severity SV) {
00371   switch (SV) {
00372   case diag::Severity::Ignored:
00373     return DiagnosticIDs::Ignored;
00374   case diag::Severity::Remark:
00375     return DiagnosticIDs::Remark;
00376   case diag::Severity::Warning:
00377     return DiagnosticIDs::Warning;
00378   case diag::Severity::Error:
00379     return DiagnosticIDs::Error;
00380   case diag::Severity::Fatal:
00381     return DiagnosticIDs::Fatal;
00382   }
00383   llvm_unreachable("unexpected severity");
00384 }
00385 
00386 /// getDiagnosticLevel - Based on the way the client configured the
00387 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level,
00388 /// by consumable the DiagnosticClient.
00389 DiagnosticIDs::Level
00390 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
00391                                   const DiagnosticsEngine &Diag) const {
00392   // Handle custom diagnostics, which cannot be mapped.
00393   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
00394     assert(CustomDiagInfo && "Invalid CustomDiagInfo");
00395     return CustomDiagInfo->getLevel(DiagID);
00396   }
00397 
00398   unsigned DiagClass = getBuiltinDiagClass(DiagID);
00399   if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note;
00400   return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
00401 }
00402 
00403 /// \brief Based on the way the client configured the Diagnostic
00404 /// object, classify the specified diagnostic ID into a Level, consumable by
00405 /// the DiagnosticClient.
00406 ///
00407 /// \param Loc The source location we are interested in finding out the
00408 /// diagnostic state. Can be null in order to query the latest state.
00409 diag::Severity
00410 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
00411                                      const DiagnosticsEngine &Diag) const {
00412   assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE);
00413 
00414   // Specific non-error diagnostics may be mapped to various levels from ignored
00415   // to error.  Errors can only be mapped to fatal.
00416   diag::Severity Result = diag::Severity::Fatal;
00417 
00418   DiagnosticsEngine::DiagStatePointsTy::iterator
00419     Pos = Diag.GetDiagStatePointForLoc(Loc);
00420   DiagnosticsEngine::DiagState *State = Pos->State;
00421 
00422   // Get the mapping information, or compute it lazily.
00423   DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID);
00424 
00425   // TODO: Can a null severity really get here?
00426   if (Mapping.getSeverity() != diag::Severity())
00427     Result = Mapping.getSeverity();
00428 
00429   // Upgrade ignored diagnostics if -Weverything is enabled.
00430   if (Diag.EnableAllWarnings && Result == diag::Severity::Ignored &&
00431       !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK)
00432     Result = diag::Severity::Warning;
00433 
00434   // Ignore -pedantic diagnostics inside __extension__ blocks.
00435   // (The diagnostics controlled by -pedantic are the extension diagnostics
00436   // that are not enabled by default.)
00437   bool EnabledByDefault = false;
00438   bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
00439   if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
00440     return diag::Severity::Ignored;
00441 
00442   // For extension diagnostics that haven't been explicitly mapped, check if we
00443   // should upgrade the diagnostic.
00444   if (IsExtensionDiag && !Mapping.isUser())
00445     Result = std::max(Result, Diag.ExtBehavior);
00446 
00447   // At this point, ignored errors can no longer be upgraded.
00448   if (Result == diag::Severity::Ignored)
00449     return Result;
00450 
00451   // Honor -w, which is lower in priority than pedantic-errors, but higher than
00452   // -Werror.
00453   if (Result == diag::Severity::Warning && Diag.IgnoreAllWarnings)
00454     return diag::Severity::Ignored;
00455 
00456   // If -Werror is enabled, map warnings to errors unless explicitly disabled.
00457   if (Result == diag::Severity::Warning) {
00458     if (Diag.WarningsAsErrors && !Mapping.hasNoWarningAsError())
00459       Result = diag::Severity::Error;
00460   }
00461 
00462   // If -Wfatal-errors is enabled, map errors to fatal unless explicity
00463   // disabled.
00464   if (Result == diag::Severity::Error) {
00465     if (Diag.ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())
00466       Result = diag::Severity::Fatal;
00467   }
00468 
00469   // Custom diagnostics always are emitted in system headers.
00470   bool ShowInSystemHeader =
00471       !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
00472 
00473   // If we are in a system header, we ignore it. We look at the diagnostic class
00474   // because we also want to ignore extensions and warnings in -Werror and
00475   // -pedantic-errors modes, which *map* warnings/extensions to errors.
00476   if (Diag.SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&
00477       Diag.getSourceManager().isInSystemHeader(
00478           Diag.getSourceManager().getExpansionLoc(Loc)))
00479     return diag::Severity::Ignored;
00480 
00481   return Result;
00482 }
00483 
00484 #define GET_DIAG_ARRAYS
00485 #include "clang/Basic/DiagnosticGroups.inc"
00486 #undef GET_DIAG_ARRAYS
00487 
00488 namespace {
00489   struct WarningOption {
00490     uint16_t NameOffset;
00491     uint16_t Members;
00492     uint16_t SubGroups;
00493 
00494     // String is stored with a pascal-style length byte.
00495     StringRef getName() const {
00496       return StringRef(DiagGroupNames + NameOffset + 1,
00497                        DiagGroupNames[NameOffset]);
00498     }
00499   };
00500 }
00501 
00502 // Second the table of options, sorted by name for fast binary lookup.
00503 static const WarningOption OptionTable[] = {
00504 #define GET_DIAG_TABLE
00505 #include "clang/Basic/DiagnosticGroups.inc"
00506 #undef GET_DIAG_TABLE
00507 };
00508 static const size_t OptionTableSize = llvm::array_lengthof(OptionTable);
00509 
00510 static bool WarningOptionCompare(const WarningOption &LHS, StringRef RHS) {
00511   return LHS.getName() < RHS;
00512 }
00513 
00514 /// getWarningOptionForDiag - Return the lowest-level warning option that
00515 /// enables the specified diagnostic.  If there is no -Wfoo flag that controls
00516 /// the diagnostic, this returns null.
00517 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
00518   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
00519     return OptionTable[Info->getOptionGroupIndex()].getName();
00520   return StringRef();
00521 }
00522 
00523 /// Return \c true if any diagnostics were found in this group, even if they
00524 /// were filtered out due to having the wrong flavor.
00525 static bool getDiagnosticsInGroup(diag::Flavor Flavor,
00526                                   const WarningOption *Group,
00527                                   SmallVectorImpl<diag::kind> &Diags) {
00528   // An empty group is considered to be a warning group: we have empty groups
00529   // for GCC compatibility, and GCC does not have remarks.
00530   if (!Group->Members && !Group->SubGroups)
00531     return Flavor == diag::Flavor::Remark ? true : false;
00532 
00533   bool NotFound = true;
00534 
00535   // Add the members of the option diagnostic set.
00536   const int16_t *Member = DiagArrays + Group->Members;
00537   for (; *Member != -1; ++Member) {
00538     if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
00539       NotFound = false;
00540       Diags.push_back(*Member);
00541     }
00542   }
00543 
00544   // Add the members of the subgroups.
00545   const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
00546   for (; *SubGroups != (int16_t)-1; ++SubGroups)
00547     NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
00548                                       Diags);
00549 
00550   return NotFound;
00551 }
00552 
00553 bool
00554 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
00555                                      SmallVectorImpl<diag::kind> &Diags) const {
00556   const WarningOption *Found = std::lower_bound(
00557       OptionTable, OptionTable + OptionTableSize, Group, WarningOptionCompare);
00558   if (Found == OptionTable + OptionTableSize ||
00559       Found->getName() != Group)
00560     return true; // Option not found.
00561 
00562   return ::getDiagnosticsInGroup(Flavor, Found, Diags);
00563 }
00564 
00565 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
00566                                      SmallVectorImpl<diag::kind> &Diags) const {
00567   for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
00568     if (StaticDiagInfo[i].getFlavor() == Flavor)
00569       Diags.push_back(StaticDiagInfo[i].DiagID);
00570 }
00571 
00572 StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
00573                                           StringRef Group) {
00574   StringRef Best;
00575   unsigned BestDistance = Group.size() + 1; // Sanity threshold.
00576   for (const WarningOption *i = OptionTable, *e = OptionTable + OptionTableSize;
00577        i != e; ++i) {
00578     // Don't suggest ignored warning flags.
00579     if (!i->Members && !i->SubGroups)
00580       continue;
00581 
00582     unsigned Distance = i->getName().edit_distance(Group, true, BestDistance);
00583     if (Distance > BestDistance)
00584       continue;
00585 
00586     // Don't suggest groups that are not of this kind.
00587     llvm::SmallVector<diag::kind, 8> Diags;
00588     if (::getDiagnosticsInGroup(Flavor, i, Diags) || Diags.empty())
00589       continue;
00590 
00591     if (Distance == BestDistance) {
00592       // Two matches with the same distance, don't prefer one over the other.
00593       Best = "";
00594     } else if (Distance < BestDistance) {
00595       // This is a better match.
00596       Best = i->getName();
00597       BestDistance = Distance;
00598     }
00599   }
00600 
00601   return Best;
00602 }
00603 
00604 /// ProcessDiag - This is the method used to report a diagnostic that is
00605 /// finally fully formed.
00606 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
00607   Diagnostic Info(&Diag);
00608 
00609   if (Diag.SuppressAllDiagnostics)
00610     return false;
00611 
00612   assert(Diag.getClient() && "DiagnosticClient not set!");
00613 
00614   // Figure out the diagnostic level of this message.
00615   unsigned DiagID = Info.getID();
00616   DiagnosticIDs::Level DiagLevel
00617     = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
00618 
00619   if (DiagLevel != DiagnosticIDs::Note) {
00620     // Record that a fatal error occurred only when we see a second
00621     // non-note diagnostic. This allows notes to be attached to the
00622     // fatal error, but suppresses any diagnostics that follow those
00623     // notes.
00624     if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
00625       Diag.FatalErrorOccurred = true;
00626 
00627     Diag.LastDiagLevel = DiagLevel;
00628   }
00629 
00630   // Update counts for DiagnosticErrorTrap even if a fatal error occurred.
00631   if (DiagLevel >= DiagnosticIDs::Error) {
00632     ++Diag.TrapNumErrorsOccurred;
00633     if (isUnrecoverable(DiagID))
00634       ++Diag.TrapNumUnrecoverableErrorsOccurred;
00635   }
00636 
00637   // If a fatal error has already been emitted, silence all subsequent
00638   // diagnostics.
00639   if (Diag.FatalErrorOccurred) {
00640     if (DiagLevel >= DiagnosticIDs::Error &&
00641         Diag.Client->IncludeInDiagnosticCounts()) {
00642       ++Diag.NumErrors;
00643     }
00644 
00645     return false;
00646   }
00647 
00648   // If the client doesn't care about this message, don't issue it.  If this is
00649   // a note and the last real diagnostic was ignored, ignore it too.
00650   if (DiagLevel == DiagnosticIDs::Ignored ||
00651       (DiagLevel == DiagnosticIDs::Note &&
00652        Diag.LastDiagLevel == DiagnosticIDs::Ignored))
00653     return false;
00654 
00655   if (DiagLevel >= DiagnosticIDs::Error) {
00656     if (isUnrecoverable(DiagID))
00657       Diag.UnrecoverableErrorOccurred = true;
00658 
00659     // Warnings which have been upgraded to errors do not prevent compilation.
00660     if (isDefaultMappingAsError(DiagID))
00661       Diag.UncompilableErrorOccurred = true;
00662 
00663     Diag.ErrorOccurred = true;
00664     if (Diag.Client->IncludeInDiagnosticCounts()) {
00665       ++Diag.NumErrors;
00666     }
00667 
00668     // If we've emitted a lot of errors, emit a fatal error instead of it to 
00669     // stop a flood of bogus errors.
00670     if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
00671         DiagLevel == DiagnosticIDs::Error) {
00672       Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
00673       return false;
00674     }
00675   }
00676 
00677   // Finally, report it.
00678   EmitDiag(Diag, DiagLevel);
00679   return true;
00680 }
00681 
00682 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
00683   Diagnostic Info(&Diag);
00684   assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
00685 
00686   Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
00687   if (Diag.Client->IncludeInDiagnosticCounts()) {
00688     if (DiagLevel == DiagnosticIDs::Warning)
00689       ++Diag.NumWarnings;
00690   }
00691 
00692   Diag.CurDiagID = ~0U;
00693 }
00694 
00695 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
00696   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
00697     assert(CustomDiagInfo && "Invalid CustomDiagInfo");
00698     // Custom diagnostics.
00699     return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
00700   }
00701 
00702   // Only errors may be unrecoverable.
00703   if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
00704     return false;
00705 
00706   if (DiagID == diag::err_unavailable ||
00707       DiagID == diag::err_unavailable_message)
00708     return false;
00709 
00710   // Currently we consider all ARC errors as recoverable.
00711   if (isARCDiagnostic(DiagID))
00712     return false;
00713 
00714   return true;
00715 }
00716 
00717 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
00718   unsigned cat = getCategoryNumberForDiag(DiagID);
00719   return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
00720 }