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