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   // If explicitly requested, map fatal errors to errors.
485   if (Result == diag::Severity::Fatal &&
486       Diag.CurDiagID != diag::fatal_too_many_errors && Diag.FatalsAsError)
487     Result = diag::Severity::Error;
488 
489   // Custom diagnostics always are emitted in system headers.
490   bool ShowInSystemHeader =
491       !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
492 
493   // If we are in a system header, we ignore it. We look at the diagnostic class
494   // because we also want to ignore extensions and warnings in -Werror and
495   // -pedantic-errors modes, which *map* warnings/extensions to errors.
496   if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&
497       Diag.getSourceManager().isInSystemHeader(
498           Diag.getSourceManager().getExpansionLoc(Loc)))
499     return diag::Severity::Ignored;
500 
501   return Result;
502 }
503 
504 #define GET_DIAG_ARRAYS
505 #include "clang/Basic/DiagnosticGroups.inc"
506 #undef GET_DIAG_ARRAYS
507 
508 namespace {
509   struct WarningOption {
510     uint16_t NameOffset;
511     uint16_t Members;
512     uint16_t SubGroups;
513 
514     // String is stored with a pascal-style length byte.
515     StringRef getName() const {
516       return StringRef(DiagGroupNames + NameOffset + 1,
517                        DiagGroupNames[NameOffset]);
518     }
519   };
520 }
521 
522 // Second the table of options, sorted by name for fast binary lookup.
523 static const WarningOption OptionTable[] = {
524 #define GET_DIAG_TABLE
525 #include "clang/Basic/DiagnosticGroups.inc"
526 #undef GET_DIAG_TABLE
527 };
528 
529 /// getWarningOptionForDiag - Return the lowest-level warning option that
530 /// enables the specified diagnostic.  If there is no -Wfoo flag that controls
531 /// the diagnostic, this returns null.
532 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
533   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
534     return OptionTable[Info->getOptionGroupIndex()].getName();
535   return StringRef();
536 }
537 
538 std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() {
539   std::vector<std::string> Res;
540   for (size_t I = 1; DiagGroupNames[I] != '\0';) {
541     std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
542     I += DiagGroupNames[I] + 1;
543     Res.push_back("-W" + Diag);
544     Res.push_back("-Wno-" + Diag);
545   }
546 
547   return Res;
548 }
549 
550 /// Return \c true if any diagnostics were found in this group, even if they
551 /// were filtered out due to having the wrong flavor.
552 static bool getDiagnosticsInGroup(diag::Flavor Flavor,
553                                   const WarningOption *Group,
554                                   SmallVectorImpl<diag::kind> &Diags) {
555   // An empty group is considered to be a warning group: we have empty groups
556   // for GCC compatibility, and GCC does not have remarks.
557   if (!Group->Members && !Group->SubGroups)
558     return Flavor == diag::Flavor::Remark;
559 
560   bool NotFound = true;
561 
562   // Add the members of the option diagnostic set.
563   const int16_t *Member = DiagArrays + Group->Members;
564   for (; *Member != -1; ++Member) {
565     if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
566       NotFound = false;
567       Diags.push_back(*Member);
568     }
569   }
570 
571   // Add the members of the subgroups.
572   const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
573   for (; *SubGroups != (int16_t)-1; ++SubGroups)
574     NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
575                                       Diags);
576 
577   return NotFound;
578 }
579 
580 bool
581 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
582                                      SmallVectorImpl<diag::kind> &Diags) const {
583   auto Found = std::lower_bound(std::begin(OptionTable), std::end(OptionTable),
584                                 Group,
585                                 [](const WarningOption &LHS, StringRef RHS) {
586                                   return LHS.getName() < RHS;
587                                 });
588   if (Found == std::end(OptionTable) || Found->getName() != Group)
589     return true; // Option not found.
590 
591   return ::getDiagnosticsInGroup(Flavor, Found, Diags);
592 }
593 
594 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
595                                       std::vector<diag::kind> &Diags) {
596   for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
597     if (StaticDiagInfo[i].getFlavor() == Flavor)
598       Diags.push_back(StaticDiagInfo[i].DiagID);
599 }
600 
601 StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
602                                           StringRef Group) {
603   StringRef Best;
604   unsigned BestDistance = Group.size() + 1; // Sanity threshold.
605   for (const WarningOption &O : OptionTable) {
606     // Don't suggest ignored warning flags.
607     if (!O.Members && !O.SubGroups)
608       continue;
609 
610     unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
611     if (Distance > BestDistance)
612       continue;
613 
614     // Don't suggest groups that are not of this kind.
615     llvm::SmallVector<diag::kind, 8> Diags;
616     if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty())
617       continue;
618 
619     if (Distance == BestDistance) {
620       // Two matches with the same distance, don't prefer one over the other.
621       Best = "";
622     } else if (Distance < BestDistance) {
623       // This is a better match.
624       Best = O.getName();
625       BestDistance = Distance;
626     }
627   }
628 
629   return Best;
630 }
631 
632 /// ProcessDiag - This is the method used to report a diagnostic that is
633 /// finally fully formed.
634 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
635   Diagnostic Info(&Diag);
636 
637   assert(Diag.getClient() && "DiagnosticClient not set!");
638 
639   // Figure out the diagnostic level of this message.
640   unsigned DiagID = Info.getID();
641   DiagnosticIDs::Level DiagLevel
642     = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
643 
644   // Update counts for DiagnosticErrorTrap even if a fatal error occurred
645   // or diagnostics are suppressed.
646   if (DiagLevel >= DiagnosticIDs::Error) {
647     ++Diag.TrapNumErrorsOccurred;
648     if (isUnrecoverable(DiagID))
649       ++Diag.TrapNumUnrecoverableErrorsOccurred;
650   }
651 
652   if (Diag.SuppressAllDiagnostics)
653     return false;
654 
655   if (DiagLevel != DiagnosticIDs::Note) {
656     // Record that a fatal error occurred only when we see a second
657     // non-note diagnostic. This allows notes to be attached to the
658     // fatal error, but suppresses any diagnostics that follow those
659     // notes.
660     if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
661       Diag.FatalErrorOccurred = true;
662 
663     Diag.LastDiagLevel = DiagLevel;
664   }
665 
666   // If a fatal error has already been emitted, silence all subsequent
667   // diagnostics.
668   if (Diag.FatalErrorOccurred) {
669     if (DiagLevel >= DiagnosticIDs::Error &&
670         Diag.Client->IncludeInDiagnosticCounts()) {
671       ++Diag.NumErrors;
672     }
673 
674     return false;
675   }
676 
677   // If the client doesn't care about this message, don't issue it.  If this is
678   // a note and the last real diagnostic was ignored, ignore it too.
679   if (DiagLevel == DiagnosticIDs::Ignored ||
680       (DiagLevel == DiagnosticIDs::Note &&
681        Diag.LastDiagLevel == DiagnosticIDs::Ignored))
682     return false;
683 
684   if (DiagLevel >= DiagnosticIDs::Error) {
685     if (isUnrecoverable(DiagID))
686       Diag.UnrecoverableErrorOccurred = true;
687 
688     // Warnings which have been upgraded to errors do not prevent compilation.
689     if (isDefaultMappingAsError(DiagID))
690       Diag.UncompilableErrorOccurred = true;
691 
692     Diag.ErrorOccurred = true;
693     if (Diag.Client->IncludeInDiagnosticCounts()) {
694       ++Diag.NumErrors;
695     }
696 
697     // If we've emitted a lot of errors, emit a fatal error instead of it to
698     // stop a flood of bogus errors.
699     if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
700         DiagLevel == DiagnosticIDs::Error) {
701       Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
702       return false;
703     }
704   }
705 
706   // Make sure we set FatalErrorOccurred to ensure that the notes from the
707   // diagnostic that caused `fatal_too_many_errors` won't be emitted.
708   if (Diag.CurDiagID == diag::fatal_too_many_errors)
709     Diag.FatalErrorOccurred = true;
710   // Finally, report it.
711   EmitDiag(Diag, DiagLevel);
712   return true;
713 }
714 
715 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
716   Diagnostic Info(&Diag);
717   assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
718 
719   Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
720   if (Diag.Client->IncludeInDiagnosticCounts()) {
721     if (DiagLevel == DiagnosticIDs::Warning)
722       ++Diag.NumWarnings;
723   }
724 
725   Diag.CurDiagID = ~0U;
726 }
727 
728 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
729   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
730     assert(CustomDiagInfo && "Invalid CustomDiagInfo");
731     // Custom diagnostics.
732     return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
733   }
734 
735   // Only errors may be unrecoverable.
736   if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
737     return false;
738 
739   if (DiagID == diag::err_unavailable ||
740       DiagID == diag::err_unavailable_message)
741     return false;
742 
743   // Currently we consider all ARC errors as recoverable.
744   if (isARCDiagnostic(DiagID))
745     return false;
746 
747   return true;
748 }
749 
750 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
751   unsigned cat = getCategoryNumberForDiag(DiagID);
752   return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
753 }
754