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 = llvm::partition_point(
584       OptionTable, [=](const WarningOption &O) { return O.getName() < Group; });
585   if (Found == std::end(OptionTable) || Found->getName() != Group)
586     return true; // Option not found.
587 
588   return ::getDiagnosticsInGroup(Flavor, Found, Diags);
589 }
590 
591 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
592                                       std::vector<diag::kind> &Diags) {
593   for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
594     if (StaticDiagInfo[i].getFlavor() == Flavor)
595       Diags.push_back(StaticDiagInfo[i].DiagID);
596 }
597 
598 StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
599                                           StringRef Group) {
600   StringRef Best;
601   unsigned BestDistance = Group.size() + 1; // Sanity threshold.
602   for (const WarningOption &O : OptionTable) {
603     // Don't suggest ignored warning flags.
604     if (!O.Members && !O.SubGroups)
605       continue;
606 
607     unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
608     if (Distance > BestDistance)
609       continue;
610 
611     // Don't suggest groups that are not of this kind.
612     llvm::SmallVector<diag::kind, 8> Diags;
613     if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty())
614       continue;
615 
616     if (Distance == BestDistance) {
617       // Two matches with the same distance, don't prefer one over the other.
618       Best = "";
619     } else if (Distance < BestDistance) {
620       // This is a better match.
621       Best = O.getName();
622       BestDistance = Distance;
623     }
624   }
625 
626   return Best;
627 }
628 
629 /// ProcessDiag - This is the method used to report a diagnostic that is
630 /// finally fully formed.
631 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
632   Diagnostic Info(&Diag);
633 
634   assert(Diag.getClient() && "DiagnosticClient not set!");
635 
636   // Figure out the diagnostic level of this message.
637   unsigned DiagID = Info.getID();
638   DiagnosticIDs::Level DiagLevel
639     = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
640 
641   // Update counts for DiagnosticErrorTrap even if a fatal error occurred
642   // or diagnostics are suppressed.
643   if (DiagLevel >= DiagnosticIDs::Error) {
644     ++Diag.TrapNumErrorsOccurred;
645     if (isUnrecoverable(DiagID))
646       ++Diag.TrapNumUnrecoverableErrorsOccurred;
647   }
648 
649   if (Diag.SuppressAllDiagnostics)
650     return false;
651 
652   if (DiagLevel != DiagnosticIDs::Note) {
653     // Record that a fatal error occurred only when we see a second
654     // non-note diagnostic. This allows notes to be attached to the
655     // fatal error, but suppresses any diagnostics that follow those
656     // notes.
657     if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
658       Diag.FatalErrorOccurred = true;
659 
660     Diag.LastDiagLevel = DiagLevel;
661   }
662 
663   // If a fatal error has already been emitted, silence all subsequent
664   // diagnostics.
665   if (Diag.FatalErrorOccurred) {
666     if (DiagLevel >= DiagnosticIDs::Error &&
667         Diag.Client->IncludeInDiagnosticCounts()) {
668       ++Diag.NumErrors;
669     }
670 
671     return false;
672   }
673 
674   // If the client doesn't care about this message, don't issue it.  If this is
675   // a note and the last real diagnostic was ignored, ignore it too.
676   if (DiagLevel == DiagnosticIDs::Ignored ||
677       (DiagLevel == DiagnosticIDs::Note &&
678        Diag.LastDiagLevel == DiagnosticIDs::Ignored))
679     return false;
680 
681   if (DiagLevel >= DiagnosticIDs::Error) {
682     if (isUnrecoverable(DiagID))
683       Diag.UnrecoverableErrorOccurred = true;
684 
685     // Warnings which have been upgraded to errors do not prevent compilation.
686     if (isDefaultMappingAsError(DiagID))
687       Diag.UncompilableErrorOccurred = true;
688 
689     Diag.ErrorOccurred = true;
690     if (Diag.Client->IncludeInDiagnosticCounts()) {
691       ++Diag.NumErrors;
692     }
693 
694     // If we've emitted a lot of errors, emit a fatal error instead of it to
695     // stop a flood of bogus errors.
696     if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
697         DiagLevel == DiagnosticIDs::Error) {
698       Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
699       return false;
700     }
701   }
702 
703   // Make sure we set FatalErrorOccurred to ensure that the notes from the
704   // diagnostic that caused `fatal_too_many_errors` won't be emitted.
705   if (Diag.CurDiagID == diag::fatal_too_many_errors)
706     Diag.FatalErrorOccurred = true;
707   // Finally, report it.
708   EmitDiag(Diag, DiagLevel);
709   return true;
710 }
711 
712 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
713   Diagnostic Info(&Diag);
714   assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
715 
716   Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
717   if (Diag.Client->IncludeInDiagnosticCounts()) {
718     if (DiagLevel == DiagnosticIDs::Warning)
719       ++Diag.NumWarnings;
720   }
721 
722   Diag.CurDiagID = ~0U;
723 }
724 
725 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
726   if (DiagID >= diag::DIAG_UPPER_LIMIT) {
727     assert(CustomDiagInfo && "Invalid CustomDiagInfo");
728     // Custom diagnostics.
729     return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
730   }
731 
732   // Only errors may be unrecoverable.
733   if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
734     return false;
735 
736   if (DiagID == diag::err_unavailable ||
737       DiagID == diag::err_unavailable_message)
738     return false;
739 
740   // Currently we consider all ARC errors as recoverable.
741   if (isARCDiagnostic(DiagID))
742     return false;
743 
744   return true;
745 }
746 
747 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
748   unsigned cat = getCategoryNumberForDiag(DiagID);
749   return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
750 }
751