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