1 //===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
23 using namespace clang
;
25 //===----------------------------------------------------------------------===//
26 // Builtin Diagnostic information
27 //===----------------------------------------------------------------------===//
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)];
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"
58 const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions
= {
59 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
60 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
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"
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),
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"
106 // Diagnostic classes.
107 enum DiagnosticClass
{
110 CLASS_WARNING
= 0x03,
111 CLASS_EXTENSION
= 0x04,
115 struct StaticDiagInfoRec
{
117 LLVM_PREFERRED_TYPE(diag::Severity
)
118 uint8_t DefaultSeverity
: 3;
119 LLVM_PREFERRED_TYPE(DiagnosticClass
)
121 LLVM_PREFERRED_TYPE(DiagnosticIDs::SFINAEResponse
)
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) \
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), \
165 DIAG_SIZE_##NAME) " is insufficient to contain all " \
166 "diagnostics, it may need to be made larger in " \
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
[] = {
186 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
187 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
192 DiagnosticIDs::SFINAE, \
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"
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
)
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
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
)
250 CATEGORY(COMMENT
, AST
)
251 CATEGORY(CROSSTU
, COMMENT
)
252 CATEGORY(SEMA
, CROSSTU
)
253 CATEGORY(ANALYSIS
, SEMA
)
254 CATEGORY(REFACTORING
, ANALYSIS
)
255 CATEGORY(INSTALLAPI
, REFACTORING
)
258 // Avoid out of bounds reads.
259 if (ID
+ Offset
>= StaticDiagInfoSize
)
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
268 if (Found
->DiagID
!= DiagID
)
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);
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
;
299 // The diagnostic category names.
300 struct StaticDiagCategoryRec
{
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
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
326 StringRef
DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID
) {
327 if (CategoryID
>= getNumberOfCategories())
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
;
347 /// getBuiltinDiagClass - Return the class field of the diagnostic.
349 static unsigned getBuiltinDiagClass(unsigned DiagID
) {
350 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
355 //===----------------------------------------------------------------------===//
356 // Custom Diagnostic information
357 //===----------------------------------------------------------------------===//
361 class CustomDiagInfo
{
362 typedef std::pair
<DiagnosticIDs::Level
, std::string
> DiagDesc
;
363 std::vector
<DiagDesc
> DiagInfo
;
364 std::map
<DiagDesc
, unsigned> DiagIDs
;
367 /// getDescription - Return the description of the specified custom
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
)
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
);
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
) {
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
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
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
)
451 getDefaultMapping(DiagID
).getSeverity() != diag::Severity::Ignored
;
455 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID
) {
456 if (DiagID
>= diag::DIAG_UPPER_LIMIT
)
459 return getDefaultMapping(DiagID
).getSeverity() >= diag::Severity::Error
;
462 /// getDescription - Given a diagnostic ID, return a description of the
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
) {
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.
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.
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
)
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
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
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())
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
;
617 #define GET_DIAG_ARRAYS
618 #include "clang/Basic/DiagnosticGroups.inc"
619 #undef GET_DIAG_ARRAYS
622 struct WarningOption
{
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"
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
)
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());
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
);
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
);
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
) {
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
],
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
);
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
,
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
)
744 unsigned Distance
= O
.getName().edit_distance(Group
, true, BestDistance
);
745 if (Distance
> BestDistance
)
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())
753 if (Distance
== BestDistance
) {
754 // Two matches with the same distance, don't prefer one over the other.
756 } else if (Distance
< BestDistance
) {
757 // This is a better match.
759 BestDistance
= Distance
;
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
)
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
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
803 if (Diag
.FatalErrorOccurred
) {
804 if (DiagLevel
>= DiagnosticIDs::Error
&&
805 Diag
.Client
->IncludeInDiagnosticCounts()) {
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
))
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()) {
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
);
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
);
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
)
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
)
874 if (DiagID
== diag::err_unavailable
||
875 DiagID
== diag::err_unavailable_message
)
878 // Currently we consider all ARC errors as recoverable.
879 if (isARCDiagnostic(DiagID
))
882 if (isCodegenABICheckDiagnostic(DiagID
))
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";