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