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