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