Rename GetLanguageInfo to GetLanguageSpecificData (#117012)
[llvm-project.git] / clang / lib / Basic / DiagnosticIDs.cpp
blob44922aa7872dbf76b52299d376db4e967fdc231a
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.
11 //===----------------------------------------------------------------------===//
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 "llvm/Support/Path.h"
21 #include <map>
22 #include <optional>
23 using namespace clang;
25 //===----------------------------------------------------------------------===//
26 // Builtin Diagnostic information
27 //===----------------------------------------------------------------------===//
29 namespace {
31 struct StaticDiagInfoRec;
33 // Store the descriptions in a separate table to avoid pointers that need to
34 // be relocated, and also decrease the amount of data needed on 64-bit
35 // platforms. See "How To Write Shared Libraries" by Ulrich Drepper.
36 struct StaticDiagInfoDescriptionStringTable {
37 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
38 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
39 char ENUM##_desc[sizeof(DESC)];
40 // clang-format off
41 #include "clang/Basic/DiagnosticCommonKinds.inc"
42 #include "clang/Basic/DiagnosticDriverKinds.inc"
43 #include "clang/Basic/DiagnosticFrontendKinds.inc"
44 #include "clang/Basic/DiagnosticSerializationKinds.inc"
45 #include "clang/Basic/DiagnosticLexKinds.inc"
46 #include "clang/Basic/DiagnosticParseKinds.inc"
47 #include "clang/Basic/DiagnosticASTKinds.inc"
48 #include "clang/Basic/DiagnosticCommentKinds.inc"
49 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
50 #include "clang/Basic/DiagnosticSemaKinds.inc"
51 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
52 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
53 #include "clang/Basic/DiagnosticInstallAPIKinds.inc"
54 // clang-format on
55 #undef DIAG
58 const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions = {
59 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
60 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
61 DESC,
62 // clang-format off
63 #include "clang/Basic/DiagnosticCommonKinds.inc"
64 #include "clang/Basic/DiagnosticDriverKinds.inc"
65 #include "clang/Basic/DiagnosticFrontendKinds.inc"
66 #include "clang/Basic/DiagnosticSerializationKinds.inc"
67 #include "clang/Basic/DiagnosticLexKinds.inc"
68 #include "clang/Basic/DiagnosticParseKinds.inc"
69 #include "clang/Basic/DiagnosticASTKinds.inc"
70 #include "clang/Basic/DiagnosticCommentKinds.inc"
71 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
72 #include "clang/Basic/DiagnosticSemaKinds.inc"
73 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
74 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
75 #include "clang/Basic/DiagnosticInstallAPIKinds.inc"
76 // clang-format on
77 #undef DIAG
80 extern const StaticDiagInfoRec StaticDiagInfo[];
82 // Stored separately from StaticDiagInfoRec to pack better. Otherwise,
83 // StaticDiagInfoRec would have extra padding on 64-bit platforms.
84 const uint32_t StaticDiagInfoDescriptionOffsets[] = {
85 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
86 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
87 offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc),
88 // clang-format off
89 #include "clang/Basic/DiagnosticCommonKinds.inc"
90 #include "clang/Basic/DiagnosticDriverKinds.inc"
91 #include "clang/Basic/DiagnosticFrontendKinds.inc"
92 #include "clang/Basic/DiagnosticSerializationKinds.inc"
93 #include "clang/Basic/DiagnosticLexKinds.inc"
94 #include "clang/Basic/DiagnosticParseKinds.inc"
95 #include "clang/Basic/DiagnosticASTKinds.inc"
96 #include "clang/Basic/DiagnosticCommentKinds.inc"
97 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
98 #include "clang/Basic/DiagnosticSemaKinds.inc"
99 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
100 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
101 #include "clang/Basic/DiagnosticInstallAPIKinds.inc"
102 // clang-format on
103 #undef DIAG
106 // Diagnostic classes.
107 enum DiagnosticClass {
108 CLASS_NOTE = 0x01,
109 CLASS_REMARK = 0x02,
110 CLASS_WARNING = 0x03,
111 CLASS_EXTENSION = 0x04,
112 CLASS_ERROR = 0x05
115 struct StaticDiagInfoRec {
116 uint16_t DiagID;
117 LLVM_PREFERRED_TYPE(diag::Severity)
118 uint8_t DefaultSeverity : 3;
119 LLVM_PREFERRED_TYPE(DiagnosticClass)
120 uint8_t Class : 3;
121 LLVM_PREFERRED_TYPE(DiagnosticIDs::SFINAEResponse)
122 uint8_t SFINAE : 2;
123 uint8_t Category : 6;
124 LLVM_PREFERRED_TYPE(bool)
125 uint8_t WarnNoWerror : 1;
126 LLVM_PREFERRED_TYPE(bool)
127 uint8_t WarnShowInSystemHeader : 1;
128 LLVM_PREFERRED_TYPE(bool)
129 uint8_t WarnShowInSystemMacro : 1;
131 uint16_t OptionGroupIndex : 15;
132 LLVM_PREFERRED_TYPE(bool)
133 uint16_t Deferrable : 1;
135 uint16_t DescriptionLen;
137 unsigned getOptionGroupIndex() const {
138 return OptionGroupIndex;
141 StringRef getDescription() const {
142 size_t MyIndex = this - &StaticDiagInfo[0];
143 uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex];
144 const char* Table = reinterpret_cast<const char*>(&StaticDiagInfoDescriptions);
145 return StringRef(&Table[StringOffset], DescriptionLen);
148 diag::Flavor getFlavor() const {
149 return Class == CLASS_REMARK ? diag::Flavor::Remark
150 : diag::Flavor::WarningOrError;
153 bool operator<(const StaticDiagInfoRec &RHS) const {
154 return DiagID < RHS.DiagID;
158 #define STRINGIFY_NAME(NAME) #NAME
159 #define VALIDATE_DIAG_SIZE(NAME) \
160 static_assert( \
161 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
162 static_cast<unsigned>(diag::DIAG_START_##NAME) + \
163 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
164 STRINGIFY_NAME( \
165 DIAG_SIZE_##NAME) " is insufficient to contain all " \
166 "diagnostics, it may need to be made larger in " \
167 "DiagnosticIDs.h.");
168 VALIDATE_DIAG_SIZE(COMMON)
169 VALIDATE_DIAG_SIZE(DRIVER)
170 VALIDATE_DIAG_SIZE(FRONTEND)
171 VALIDATE_DIAG_SIZE(SERIALIZATION)
172 VALIDATE_DIAG_SIZE(LEX)
173 VALIDATE_DIAG_SIZE(PARSE)
174 VALIDATE_DIAG_SIZE(AST)
175 VALIDATE_DIAG_SIZE(COMMENT)
176 VALIDATE_DIAG_SIZE(CROSSTU)
177 VALIDATE_DIAG_SIZE(SEMA)
178 VALIDATE_DIAG_SIZE(ANALYSIS)
179 VALIDATE_DIAG_SIZE(REFACTORING)
180 VALIDATE_DIAG_SIZE(INSTALLAPI)
181 #undef VALIDATE_DIAG_SIZE
182 #undef STRINGIFY_NAME
184 const StaticDiagInfoRec StaticDiagInfo[] = {
185 // clang-format off
186 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
187 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
189 diag::ENUM, \
190 DEFAULT_SEVERITY, \
191 CLASS, \
192 DiagnosticIDs::SFINAE, \
193 CATEGORY, \
194 NOWERROR, \
195 SHOWINSYSHEADER, \
196 SHOWINSYSMACRO, \
197 GROUP, \
198 DEFERRABLE, \
199 STR_SIZE(DESC, uint16_t)},
200 #include "clang/Basic/DiagnosticCommonKinds.inc"
201 #include "clang/Basic/DiagnosticDriverKinds.inc"
202 #include "clang/Basic/DiagnosticFrontendKinds.inc"
203 #include "clang/Basic/DiagnosticSerializationKinds.inc"
204 #include "clang/Basic/DiagnosticLexKinds.inc"
205 #include "clang/Basic/DiagnosticParseKinds.inc"
206 #include "clang/Basic/DiagnosticASTKinds.inc"
207 #include "clang/Basic/DiagnosticCommentKinds.inc"
208 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
209 #include "clang/Basic/DiagnosticSemaKinds.inc"
210 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
211 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
212 #include "clang/Basic/DiagnosticInstallAPIKinds.inc"
213 // clang-format on
214 #undef DIAG
217 } // namespace
219 static const unsigned StaticDiagInfoSize = std::size(StaticDiagInfo);
221 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
222 /// or null if the ID is invalid.
223 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
224 // Out of bounds diag. Can't be in the table.
225 using namespace diag;
226 if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
227 return nullptr;
229 // Compute the index of the requested diagnostic in the static table.
230 // 1. Add the number of diagnostics in each category preceding the
231 // diagnostic and of the category the diagnostic is in. This gives us
232 // the offset of the category in the table.
233 // 2. Subtract the number of IDs in each category from our ID. This gives us
234 // the offset of the diagnostic in the category.
235 // This is cheaper than a binary search on the table as it doesn't touch
236 // memory at all.
237 unsigned Offset = 0;
238 unsigned ID = DiagID - DIAG_START_COMMON - 1;
239 #define CATEGORY(NAME, PREV) \
240 if (DiagID > DIAG_START_##NAME) { \
241 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
242 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
244 CATEGORY(DRIVER, COMMON)
245 CATEGORY(FRONTEND, DRIVER)
246 CATEGORY(SERIALIZATION, FRONTEND)
247 CATEGORY(LEX, SERIALIZATION)
248 CATEGORY(PARSE, LEX)
249 CATEGORY(AST, PARSE)
250 CATEGORY(COMMENT, AST)
251 CATEGORY(CROSSTU, COMMENT)
252 CATEGORY(SEMA, CROSSTU)
253 CATEGORY(ANALYSIS, SEMA)
254 CATEGORY(REFACTORING, ANALYSIS)
255 CATEGORY(INSTALLAPI, REFACTORING)
256 #undef CATEGORY
258 // Avoid out of bounds reads.
259 if (ID + Offset >= StaticDiagInfoSize)
260 return nullptr;
262 assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize);
264 const StaticDiagInfoRec *Found = &StaticDiagInfo[ID + Offset];
265 // If the diag id doesn't match we found a different diag, abort. This can
266 // happen when this function is called with an ID that points into a hole in
267 // the diagID space.
268 if (Found->DiagID != DiagID)
269 return nullptr;
270 return Found;
273 DiagnosticMapping DiagnosticIDs::getDefaultMapping(unsigned DiagID) {
274 DiagnosticMapping Info = DiagnosticMapping::Make(
275 diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false);
277 if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) {
278 Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity);
280 if (StaticInfo->WarnNoWerror) {
281 assert(Info.getSeverity() == diag::Severity::Warning &&
282 "Unexpected mapping with no-Werror bit!");
283 Info.setNoWarningAsError(true);
287 return Info;
290 /// getCategoryNumberForDiag - Return the category number that a specified
291 /// DiagID belongs to, or 0 if no category.
292 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
293 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
294 return Info->Category;
295 return 0;
298 namespace {
299 // The diagnostic category names.
300 struct StaticDiagCategoryRec {
301 const char *NameStr;
302 uint8_t NameLen;
304 StringRef getName() const {
305 return StringRef(NameStr, NameLen);
310 static const StaticDiagCategoryRec CategoryNameTable[] = {
311 #define GET_CATEGORY_TABLE
312 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
313 #include "clang/Basic/DiagnosticGroups.inc"
314 #undef GET_CATEGORY_TABLE
315 { nullptr, 0 }
318 /// getNumberOfCategories - Return the number of categories
319 unsigned DiagnosticIDs::getNumberOfCategories() {
320 return std::size(CategoryNameTable) - 1;
323 /// getCategoryNameFromID - Given a category ID, return the name of the
324 /// category, an empty string if CategoryID is zero, or null if CategoryID is
325 /// invalid.
326 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
327 if (CategoryID >= getNumberOfCategories())
328 return StringRef();
329 return CategoryNameTable[CategoryID].getName();
334 DiagnosticIDs::SFINAEResponse
335 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
336 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
337 return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE);
338 return SFINAE_Report;
341 bool DiagnosticIDs::isDeferrable(unsigned DiagID) {
342 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
343 return Info->Deferrable;
344 return false;
347 /// getBuiltinDiagClass - Return the class field of the diagnostic.
349 static unsigned getBuiltinDiagClass(unsigned DiagID) {
350 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
351 return Info->Class;
352 return ~0U;
355 //===----------------------------------------------------------------------===//
356 // Custom Diagnostic information
357 //===----------------------------------------------------------------------===//
359 namespace clang {
360 namespace diag {
361 class CustomDiagInfo {
362 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
363 std::vector<DiagDesc> DiagInfo;
364 std::map<DiagDesc, unsigned> DiagIDs;
365 public:
367 /// getDescription - Return the description of the specified custom
368 /// diagnostic.
369 StringRef getDescription(unsigned DiagID) const {
370 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
371 "Invalid diagnostic ID");
372 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
375 /// getLevel - Return the level of the specified custom diagnostic.
376 DiagnosticIDs::Level getLevel(unsigned DiagID) const {
377 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
378 "Invalid diagnostic ID");
379 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
382 unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
383 DiagnosticIDs &Diags) {
384 DiagDesc D(L, std::string(Message));
385 // Check to see if it already exists.
386 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
387 if (I != DiagIDs.end() && I->first == D)
388 return I->second;
390 // If not, assign a new ID.
391 unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
392 DiagIDs.insert(std::make_pair(D, ID));
393 DiagInfo.push_back(D);
394 return ID;
398 } // end diag namespace
399 } // end clang namespace
402 //===----------------------------------------------------------------------===//
403 // Common Diagnostic implementation
404 //===----------------------------------------------------------------------===//
406 DiagnosticIDs::DiagnosticIDs() {}
408 DiagnosticIDs::~DiagnosticIDs() {}
410 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
411 /// and level. If this is the first request for this diagnostic, it is
412 /// registered and created, otherwise the existing ID is returned.
414 /// \param FormatString A fixed diagnostic format string that will be hashed and
415 /// mapped to a unique DiagID.
416 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
417 if (!CustomDiagInfo)
418 CustomDiagInfo.reset(new diag::CustomDiagInfo());
419 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
423 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
424 /// level of the specified diagnostic ID is a Warning or Extension.
425 /// This only works on builtin diagnostics, not custom ones, and is not legal to
426 /// call on NOTEs.
427 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
428 return DiagID < diag::DIAG_UPPER_LIMIT &&
429 getBuiltinDiagClass(DiagID) != CLASS_ERROR;
432 /// Determine whether the given built-in diagnostic ID is a
433 /// Note.
434 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
435 return DiagID < diag::DIAG_UPPER_LIMIT &&
436 getBuiltinDiagClass(DiagID) == CLASS_NOTE;
439 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
440 /// ID is for an extension of some sort. This also returns EnabledByDefault,
441 /// which is set to indicate whether the diagnostic is ignored by default (in
442 /// which case -pedantic enables it) or treated as a warning/error by default.
444 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
445 bool &EnabledByDefault) {
446 if (DiagID >= diag::DIAG_UPPER_LIMIT ||
447 getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
448 return false;
450 EnabledByDefault =
451 getDefaultMapping(DiagID).getSeverity() != diag::Severity::Ignored;
452 return true;
455 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
456 if (DiagID >= diag::DIAG_UPPER_LIMIT)
457 return false;
459 return getDefaultMapping(DiagID).getSeverity() >= diag::Severity::Error;
462 /// getDescription - Given a diagnostic ID, return a description of the
463 /// issue.
464 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
465 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
466 return Info->getDescription();
467 assert(CustomDiagInfo && "Invalid CustomDiagInfo");
468 return CustomDiagInfo->getDescription(DiagID);
471 static DiagnosticIDs::Level toLevel(diag::Severity SV) {
472 switch (SV) {
473 case diag::Severity::Ignored:
474 return DiagnosticIDs::Ignored;
475 case diag::Severity::Remark:
476 return DiagnosticIDs::Remark;
477 case diag::Severity::Warning:
478 return DiagnosticIDs::Warning;
479 case diag::Severity::Error:
480 return DiagnosticIDs::Error;
481 case diag::Severity::Fatal:
482 return DiagnosticIDs::Fatal;
484 llvm_unreachable("unexpected severity");
487 /// getDiagnosticLevel - Based on the way the client configured the
488 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level,
489 /// by consumable the DiagnosticClient.
490 DiagnosticIDs::Level
491 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
492 const DiagnosticsEngine &Diag) const {
493 // Handle custom diagnostics, which cannot be mapped.
494 if (DiagID >= diag::DIAG_UPPER_LIMIT) {
495 assert(CustomDiagInfo && "Invalid CustomDiagInfo");
496 return CustomDiagInfo->getLevel(DiagID);
499 unsigned DiagClass = getBuiltinDiagClass(DiagID);
500 if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note;
501 return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
504 /// Based on the way the client configured the Diagnostic
505 /// object, classify the specified diagnostic ID into a Level, consumable by
506 /// the DiagnosticClient.
508 /// \param Loc The source location we are interested in finding out the
509 /// diagnostic state. Can be null in order to query the latest state.
510 diag::Severity
511 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
512 const DiagnosticsEngine &Diag) const {
513 assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE);
515 // Specific non-error diagnostics may be mapped to various levels from ignored
516 // to error. Errors can only be mapped to fatal.
517 diag::Severity Result = diag::Severity::Fatal;
519 // Get the mapping information, or compute it lazily.
520 DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc);
521 DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID);
523 // TODO: Can a null severity really get here?
524 if (Mapping.getSeverity() != diag::Severity())
525 Result = Mapping.getSeverity();
527 // Upgrade ignored diagnostics if -Weverything is enabled.
528 if (State->EnableAllWarnings && Result == diag::Severity::Ignored &&
529 !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK)
530 Result = diag::Severity::Warning;
532 // Ignore -pedantic diagnostics inside __extension__ blocks.
533 // (The diagnostics controlled by -pedantic are the extension diagnostics
534 // that are not enabled by default.)
535 bool EnabledByDefault = false;
536 bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
537 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
538 return diag::Severity::Ignored;
540 // For extension diagnostics that haven't been explicitly mapped, check if we
541 // should upgrade the diagnostic.
542 if (IsExtensionDiag && !Mapping.isUser())
543 Result = std::max(Result, State->ExtBehavior);
545 // At this point, ignored errors can no longer be upgraded.
546 if (Result == diag::Severity::Ignored)
547 return Result;
549 // Honor -w: this disables all messages which are not Error/Fatal by
550 // default (disregarding attempts to upgrade severity from Warning to Error),
551 // as well as disabling all messages which are currently mapped to Warning
552 // (whether by default or downgraded from Error via e.g. -Wno-error or #pragma
553 // diagnostic.)
554 if (State->IgnoreAllWarnings) {
555 if (Result == diag::Severity::Warning ||
556 (Result >= diag::Severity::Error &&
557 !isDefaultMappingAsError((diag::kind)DiagID)))
558 return diag::Severity::Ignored;
561 // If -Werror is enabled, map warnings to errors unless explicitly disabled.
562 if (Result == diag::Severity::Warning) {
563 if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError())
564 Result = diag::Severity::Error;
567 // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
568 // disabled.
569 if (Result == diag::Severity::Error) {
570 if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())
571 Result = diag::Severity::Fatal;
574 // If explicitly requested, map fatal errors to errors.
575 if (Result == diag::Severity::Fatal &&
576 DiagID != diag::fatal_too_many_errors && Diag.FatalsAsError)
577 Result = diag::Severity::Error;
579 // Rest of the mappings are only applicable for diagnostics associated with a
580 // SourceLocation, bail out early for others.
581 if (!Diag.hasSourceManager())
582 return Result;
584 const auto &SM = Diag.getSourceManager();
585 // Custom diagnostics always are emitted in system headers.
586 bool ShowInSystemHeader =
587 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
589 // If we are in a system header, we ignore it. We look at the diagnostic class
590 // because we also want to ignore extensions and warnings in -Werror and
591 // -pedantic-errors modes, which *map* warnings/extensions to errors.
592 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&
593 SM.isInSystemHeader(SM.getExpansionLoc(Loc)))
594 return diag::Severity::Ignored;
596 // We also ignore warnings due to system macros
597 bool ShowInSystemMacro =
598 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemMacro;
599 if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.isValid() &&
600 SM.isInSystemMacro(Loc))
601 return diag::Severity::Ignored;
603 // Clang-diagnostics pragmas always take precedence over suppression mapping.
604 if (!Mapping.isPragma() && Diag.DiagSuppressionMapping) {
605 // We also use presumed locations here to improve reproducibility for
606 // preprocessed inputs.
607 if (PresumedLoc PLoc = SM.getPresumedLoc(Loc);
608 PLoc.isValid() && Diag.isSuppressedViaMapping(
609 DiagID, llvm::sys::path::remove_leading_dotslash(
610 PLoc.getFilename())))
611 return diag::Severity::Ignored;
614 return Result;
617 #define GET_DIAG_ARRAYS
618 #include "clang/Basic/DiagnosticGroups.inc"
619 #undef GET_DIAG_ARRAYS
621 namespace {
622 struct WarningOption {
623 uint16_t NameOffset;
624 uint16_t Members;
625 uint16_t SubGroups;
626 StringRef Documentation;
628 // String is stored with a pascal-style length byte.
629 StringRef getName() const {
630 return StringRef(DiagGroupNames + NameOffset + 1,
631 DiagGroupNames[NameOffset]);
636 // Second the table of options, sorted by name for fast binary lookup.
637 static const WarningOption OptionTable[] = {
638 #define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
639 {FlagNameOffset, Members, SubGroups, Docs},
640 #include "clang/Basic/DiagnosticGroups.inc"
641 #undef DIAG_ENTRY
644 /// Given a diagnostic group ID, return its documentation.
645 StringRef DiagnosticIDs::getWarningOptionDocumentation(diag::Group Group) {
646 return OptionTable[static_cast<int>(Group)].Documentation;
649 StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) {
650 return OptionTable[static_cast<int>(Group)].getName();
653 std::optional<diag::Group>
654 DiagnosticIDs::getGroupForWarningOption(StringRef Name) {
655 const auto *Found = llvm::partition_point(
656 OptionTable, [=](const WarningOption &O) { return O.getName() < Name; });
657 if (Found == std::end(OptionTable) || Found->getName() != Name)
658 return std::nullopt;
659 return static_cast<diag::Group>(Found - OptionTable);
662 std::optional<diag::Group> DiagnosticIDs::getGroupForDiag(unsigned DiagID) {
663 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
664 return static_cast<diag::Group>(Info->getOptionGroupIndex());
665 return std::nullopt;
668 /// getWarningOptionForDiag - Return the lowest-level warning option that
669 /// enables the specified diagnostic. If there is no -Wfoo flag that controls
670 /// the diagnostic, this returns null.
671 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
672 if (auto G = getGroupForDiag(DiagID))
673 return getWarningOptionForGroup(*G);
674 return StringRef();
677 std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() {
678 std::vector<std::string> Res{"-W", "-Wno-"};
679 for (size_t I = 1; DiagGroupNames[I] != '\0';) {
680 std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
681 I += DiagGroupNames[I] + 1;
682 Res.push_back("-W" + Diag);
683 Res.push_back("-Wno-" + Diag);
686 return Res;
689 /// Return \c true if any diagnostics were found in this group, even if they
690 /// were filtered out due to having the wrong flavor.
691 static bool getDiagnosticsInGroup(diag::Flavor Flavor,
692 const WarningOption *Group,
693 SmallVectorImpl<diag::kind> &Diags) {
694 // An empty group is considered to be a warning group: we have empty groups
695 // for GCC compatibility, and GCC does not have remarks.
696 if (!Group->Members && !Group->SubGroups)
697 return Flavor == diag::Flavor::Remark;
699 bool NotFound = true;
701 // Add the members of the option diagnostic set.
702 const int16_t *Member = DiagArrays + Group->Members;
703 for (; *Member != -1; ++Member) {
704 if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
705 NotFound = false;
706 Diags.push_back(*Member);
710 // Add the members of the subgroups.
711 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
712 for (; *SubGroups != (int16_t)-1; ++SubGroups)
713 NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
714 Diags);
716 return NotFound;
719 bool
720 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
721 SmallVectorImpl<diag::kind> &Diags) const {
722 if (std::optional<diag::Group> G = getGroupForWarningOption(Group))
723 return ::getDiagnosticsInGroup(
724 Flavor, &OptionTable[static_cast<unsigned>(*G)], Diags);
725 return true;
728 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
729 std::vector<diag::kind> &Diags) {
730 for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
731 if (StaticDiagInfo[i].getFlavor() == Flavor)
732 Diags.push_back(StaticDiagInfo[i].DiagID);
735 StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
736 StringRef Group) {
737 StringRef Best;
738 unsigned BestDistance = Group.size() + 1; // Maximum threshold.
739 for (const WarningOption &O : OptionTable) {
740 // Don't suggest ignored warning flags.
741 if (!O.Members && !O.SubGroups)
742 continue;
744 unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
745 if (Distance > BestDistance)
746 continue;
748 // Don't suggest groups that are not of this kind.
749 llvm::SmallVector<diag::kind, 8> Diags;
750 if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty())
751 continue;
753 if (Distance == BestDistance) {
754 // Two matches with the same distance, don't prefer one over the other.
755 Best = "";
756 } else if (Distance < BestDistance) {
757 // This is a better match.
758 Best = O.getName();
759 BestDistance = Distance;
763 return Best;
766 /// ProcessDiag - This is the method used to report a diagnostic that is
767 /// finally fully formed.
768 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag,
769 const DiagnosticBuilder &DiagBuilder) const {
770 Diagnostic Info(&Diag, DiagBuilder);
772 assert(Diag.getClient() && "DiagnosticClient not set!");
774 // Figure out the diagnostic level of this message.
775 unsigned DiagID = Info.getID();
776 DiagnosticIDs::Level DiagLevel
777 = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
779 // Update counts for DiagnosticErrorTrap even if a fatal error occurred
780 // or diagnostics are suppressed.
781 if (DiagLevel >= DiagnosticIDs::Error) {
782 ++Diag.TrapNumErrorsOccurred;
783 if (isUnrecoverable(DiagID))
784 ++Diag.TrapNumUnrecoverableErrorsOccurred;
787 if (Diag.SuppressAllDiagnostics)
788 return false;
790 if (DiagLevel != DiagnosticIDs::Note) {
791 // Record that a fatal error occurred only when we see a second
792 // non-note diagnostic. This allows notes to be attached to the
793 // fatal error, but suppresses any diagnostics that follow those
794 // notes.
795 if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
796 Diag.FatalErrorOccurred = true;
798 Diag.LastDiagLevel = DiagLevel;
801 // If a fatal error has already been emitted, silence all subsequent
802 // diagnostics.
803 if (Diag.FatalErrorOccurred) {
804 if (DiagLevel >= DiagnosticIDs::Error &&
805 Diag.Client->IncludeInDiagnosticCounts()) {
806 ++Diag.NumErrors;
809 return false;
812 // If the client doesn't care about this message, don't issue it. If this is
813 // a note and the last real diagnostic was ignored, ignore it too.
814 if (DiagLevel == DiagnosticIDs::Ignored ||
815 (DiagLevel == DiagnosticIDs::Note &&
816 Diag.LastDiagLevel == DiagnosticIDs::Ignored))
817 return false;
819 if (DiagLevel >= DiagnosticIDs::Error) {
820 if (isUnrecoverable(DiagID))
821 Diag.UnrecoverableErrorOccurred = true;
823 // Warnings which have been upgraded to errors do not prevent compilation.
824 if (isDefaultMappingAsError(DiagID))
825 Diag.UncompilableErrorOccurred = true;
827 Diag.ErrorOccurred = true;
828 if (Diag.Client->IncludeInDiagnosticCounts()) {
829 ++Diag.NumErrors;
832 // If we've emitted a lot of errors, emit a fatal error instead of it to
833 // stop a flood of bogus errors.
834 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
835 DiagLevel == DiagnosticIDs::Error) {
836 Diag.Report(diag::fatal_too_many_errors);
837 return false;
841 // Make sure we set FatalErrorOccurred to ensure that the notes from the
842 // diagnostic that caused `fatal_too_many_errors` won't be emitted.
843 if (Info.getID() == diag::fatal_too_many_errors)
844 Diag.FatalErrorOccurred = true;
845 // Finally, report it.
846 EmitDiag(Diag, DiagBuilder, DiagLevel);
847 return true;
850 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag,
851 const DiagnosticBuilder &DiagBuilder,
852 Level DiagLevel) const {
853 Diagnostic Info(&Diag, DiagBuilder);
854 assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
856 Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
857 if (Diag.Client->IncludeInDiagnosticCounts()) {
858 if (DiagLevel == DiagnosticIDs::Warning)
859 ++Diag.NumWarnings;
863 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
864 if (DiagID >= diag::DIAG_UPPER_LIMIT) {
865 assert(CustomDiagInfo && "Invalid CustomDiagInfo");
866 // Custom diagnostics.
867 return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
870 // Only errors may be unrecoverable.
871 if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
872 return false;
874 if (DiagID == diag::err_unavailable ||
875 DiagID == diag::err_unavailable_message)
876 return false;
878 // Currently we consider all ARC errors as recoverable.
879 if (isARCDiagnostic(DiagID))
880 return false;
882 if (isCodegenABICheckDiagnostic(DiagID))
883 return false;
885 return true;
888 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
889 unsigned cat = getCategoryNumberForDiag(DiagID);
890 return DiagnosticIDs::getCategoryNameFromID(cat).starts_with("ARC ");
893 bool DiagnosticIDs::isCodegenABICheckDiagnostic(unsigned DiagID) {
894 unsigned cat = getCategoryNumberForDiag(DiagID);
895 return DiagnosticIDs::getCategoryNameFromID(cat) == "Codegen ABI Check";