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"
22 using namespace clang
;
24 //===----------------------------------------------------------------------===//
25 // Builtin Diagnostic information
26 //===----------------------------------------------------------------------===//
30 struct StaticDiagInfoRec
;
32 // Store the descriptions in a separate table to avoid pointers that need to
33 // be relocated, and also decrease the amount of data needed on 64-bit
34 // platforms. See "How To Write Shared Libraries" by Ulrich Drepper.
35 struct StaticDiagInfoDescriptionStringTable
{
36 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
37 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
38 char ENUM##_desc[sizeof(DESC)];
40 #include "clang/Basic/DiagnosticCommonKinds.inc"
41 #include "clang/Basic/DiagnosticDriverKinds.inc"
42 #include "clang/Basic/DiagnosticFrontendKinds.inc"
43 #include "clang/Basic/DiagnosticSerializationKinds.inc"
44 #include "clang/Basic/DiagnosticLexKinds.inc"
45 #include "clang/Basic/DiagnosticParseKinds.inc"
46 #include "clang/Basic/DiagnosticASTKinds.inc"
47 #include "clang/Basic/DiagnosticCommentKinds.inc"
48 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
49 #include "clang/Basic/DiagnosticSemaKinds.inc"
50 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
51 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
56 const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions
= {
57 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
58 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
61 #include "clang/Basic/DiagnosticCommonKinds.inc"
62 #include "clang/Basic/DiagnosticDriverKinds.inc"
63 #include "clang/Basic/DiagnosticFrontendKinds.inc"
64 #include "clang/Basic/DiagnosticSerializationKinds.inc"
65 #include "clang/Basic/DiagnosticLexKinds.inc"
66 #include "clang/Basic/DiagnosticParseKinds.inc"
67 #include "clang/Basic/DiagnosticASTKinds.inc"
68 #include "clang/Basic/DiagnosticCommentKinds.inc"
69 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
70 #include "clang/Basic/DiagnosticSemaKinds.inc"
71 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
72 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
77 extern const StaticDiagInfoRec StaticDiagInfo
[];
79 // Stored separately from StaticDiagInfoRec to pack better. Otherwise,
80 // StaticDiagInfoRec would have extra padding on 64-bit platforms.
81 const uint32_t StaticDiagInfoDescriptionOffsets
[] = {
82 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
83 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
84 offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc),
86 #include "clang/Basic/DiagnosticCommonKinds.inc"
87 #include "clang/Basic/DiagnosticDriverKinds.inc"
88 #include "clang/Basic/DiagnosticFrontendKinds.inc"
89 #include "clang/Basic/DiagnosticSerializationKinds.inc"
90 #include "clang/Basic/DiagnosticLexKinds.inc"
91 #include "clang/Basic/DiagnosticParseKinds.inc"
92 #include "clang/Basic/DiagnosticASTKinds.inc"
93 #include "clang/Basic/DiagnosticCommentKinds.inc"
94 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
95 #include "clang/Basic/DiagnosticSemaKinds.inc"
96 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
97 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
102 // Diagnostic classes.
106 CLASS_WARNING
= 0x03,
107 CLASS_EXTENSION
= 0x04,
111 struct StaticDiagInfoRec
{
113 uint8_t DefaultSeverity
: 3;
116 uint8_t Category
: 6;
117 uint8_t WarnNoWerror
: 1;
118 uint8_t WarnShowInSystemHeader
: 1;
119 uint8_t WarnShowInSystemMacro
: 1;
121 uint16_t OptionGroupIndex
: 15;
122 uint16_t Deferrable
: 1;
124 uint16_t DescriptionLen
;
126 unsigned getOptionGroupIndex() const {
127 return OptionGroupIndex
;
130 StringRef
getDescription() const {
131 size_t MyIndex
= this - &StaticDiagInfo
[0];
132 uint32_t StringOffset
= StaticDiagInfoDescriptionOffsets
[MyIndex
];
133 const char* Table
= reinterpret_cast<const char*>(&StaticDiagInfoDescriptions
);
134 return StringRef(&Table
[StringOffset
], DescriptionLen
);
137 diag::Flavor
getFlavor() const {
138 return Class
== CLASS_REMARK
? diag::Flavor::Remark
139 : diag::Flavor::WarningOrError
;
142 bool operator<(const StaticDiagInfoRec
&RHS
) const {
143 return DiagID
< RHS
.DiagID
;
147 #define STRINGIFY_NAME(NAME) #NAME
148 #define VALIDATE_DIAG_SIZE(NAME) \
150 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
151 static_cast<unsigned>(diag::DIAG_START_##NAME) + \
152 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
154 DIAG_SIZE_##NAME) " is insufficient to contain all " \
155 "diagnostics, it may need to be made larger in " \
157 VALIDATE_DIAG_SIZE(COMMON
)
158 VALIDATE_DIAG_SIZE(DRIVER
)
159 VALIDATE_DIAG_SIZE(FRONTEND
)
160 VALIDATE_DIAG_SIZE(SERIALIZATION
)
161 VALIDATE_DIAG_SIZE(LEX
)
162 VALIDATE_DIAG_SIZE(PARSE
)
163 VALIDATE_DIAG_SIZE(AST
)
164 VALIDATE_DIAG_SIZE(COMMENT
)
165 VALIDATE_DIAG_SIZE(CROSSTU
)
166 VALIDATE_DIAG_SIZE(SEMA
)
167 VALIDATE_DIAG_SIZE(ANALYSIS
)
168 VALIDATE_DIAG_SIZE(REFACTORING
)
169 #undef VALIDATE_DIAG_SIZE
170 #undef STRINGIFY_NAME
172 const StaticDiagInfoRec StaticDiagInfo
[] = {
174 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
175 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
180 DiagnosticIDs::SFINAE, \
187 STR_SIZE(DESC, uint16_t)},
188 #include "clang/Basic/DiagnosticCommonKinds.inc"
189 #include "clang/Basic/DiagnosticDriverKinds.inc"
190 #include "clang/Basic/DiagnosticFrontendKinds.inc"
191 #include "clang/Basic/DiagnosticSerializationKinds.inc"
192 #include "clang/Basic/DiagnosticLexKinds.inc"
193 #include "clang/Basic/DiagnosticParseKinds.inc"
194 #include "clang/Basic/DiagnosticASTKinds.inc"
195 #include "clang/Basic/DiagnosticCommentKinds.inc"
196 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
197 #include "clang/Basic/DiagnosticSemaKinds.inc"
198 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
199 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
206 static const unsigned StaticDiagInfoSize
= std::size(StaticDiagInfo
);
208 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
209 /// or null if the ID is invalid.
210 static const StaticDiagInfoRec
*GetDiagInfo(unsigned DiagID
) {
211 // Out of bounds diag. Can't be in the table.
212 using namespace diag
;
213 if (DiagID
>= DIAG_UPPER_LIMIT
|| DiagID
<= DIAG_START_COMMON
)
216 // Compute the index of the requested diagnostic in the static table.
217 // 1. Add the number of diagnostics in each category preceding the
218 // diagnostic and of the category the diagnostic is in. This gives us
219 // the offset of the category in the table.
220 // 2. Subtract the number of IDs in each category from our ID. This gives us
221 // the offset of the diagnostic in the category.
222 // This is cheaper than a binary search on the table as it doesn't touch
225 unsigned ID
= DiagID
- DIAG_START_COMMON
- 1;
226 #define CATEGORY(NAME, PREV) \
227 if (DiagID > DIAG_START_##NAME) { \
228 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
229 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
231 CATEGORY(DRIVER
, COMMON
)
232 CATEGORY(FRONTEND
, DRIVER
)
233 CATEGORY(SERIALIZATION
, FRONTEND
)
234 CATEGORY(LEX
, SERIALIZATION
)
237 CATEGORY(COMMENT
, AST
)
238 CATEGORY(CROSSTU
, COMMENT
)
239 CATEGORY(SEMA
, CROSSTU
)
240 CATEGORY(ANALYSIS
, SEMA
)
241 CATEGORY(REFACTORING
, ANALYSIS
)
244 // Avoid out of bounds reads.
245 if (ID
+ Offset
>= StaticDiagInfoSize
)
248 assert(ID
< StaticDiagInfoSize
&& Offset
< StaticDiagInfoSize
);
250 const StaticDiagInfoRec
*Found
= &StaticDiagInfo
[ID
+ Offset
];
251 // If the diag id doesn't match we found a different diag, abort. This can
252 // happen when this function is called with an ID that points into a hole in
254 if (Found
->DiagID
!= DiagID
)
259 static DiagnosticMapping
GetDefaultDiagMapping(unsigned DiagID
) {
260 DiagnosticMapping Info
= DiagnosticMapping::Make(
261 diag::Severity::Fatal
, /*IsUser=*/false, /*IsPragma=*/false);
263 if (const StaticDiagInfoRec
*StaticInfo
= GetDiagInfo(DiagID
)) {
264 Info
.setSeverity((diag::Severity
)StaticInfo
->DefaultSeverity
);
266 if (StaticInfo
->WarnNoWerror
) {
267 assert(Info
.getSeverity() == diag::Severity::Warning
&&
268 "Unexpected mapping with no-Werror bit!");
269 Info
.setNoWarningAsError(true);
276 /// getCategoryNumberForDiag - Return the category number that a specified
277 /// DiagID belongs to, or 0 if no category.
278 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID
) {
279 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
280 return Info
->Category
;
285 // The diagnostic category names.
286 struct StaticDiagCategoryRec
{
290 StringRef
getName() const {
291 return StringRef(NameStr
, NameLen
);
296 // Unfortunately, the split between DiagnosticIDs and Diagnostic is not
297 // particularly clean, but for now we just implement this method here so we can
298 // access GetDefaultDiagMapping.
300 DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag
) {
301 std::pair
<iterator
, bool> Result
=
302 DiagMap
.insert(std::make_pair(Diag
, DiagnosticMapping()));
304 // Initialize the entry if we added it.
306 Result
.first
->second
= GetDefaultDiagMapping(Diag
);
308 return Result
.first
->second
;
311 static const StaticDiagCategoryRec CategoryNameTable
[] = {
312 #define GET_CATEGORY_TABLE
313 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
314 #include "clang/Basic/DiagnosticGroups.inc"
315 #undef GET_CATEGORY_TABLE
319 /// getNumberOfCategories - Return the number of categories
320 unsigned DiagnosticIDs::getNumberOfCategories() {
321 return std::size(CategoryNameTable
) - 1;
324 /// getCategoryNameFromID - Given a category ID, return the name of the
325 /// category, an empty string if CategoryID is zero, or null if CategoryID is
327 StringRef
DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID
) {
328 if (CategoryID
>= getNumberOfCategories())
330 return CategoryNameTable
[CategoryID
].getName();
335 DiagnosticIDs::SFINAEResponse
336 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID
) {
337 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
338 return static_cast<DiagnosticIDs::SFINAEResponse
>(Info
->SFINAE
);
339 return SFINAE_Report
;
342 bool DiagnosticIDs::isDeferrable(unsigned DiagID
) {
343 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
344 return Info
->Deferrable
;
348 /// getBuiltinDiagClass - Return the class field of the diagnostic.
350 static unsigned getBuiltinDiagClass(unsigned DiagID
) {
351 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
356 //===----------------------------------------------------------------------===//
357 // Custom Diagnostic information
358 //===----------------------------------------------------------------------===//
362 class CustomDiagInfo
{
363 typedef std::pair
<DiagnosticIDs::Level
, std::string
> DiagDesc
;
364 std::vector
<DiagDesc
> DiagInfo
;
365 std::map
<DiagDesc
, unsigned> DiagIDs
;
368 /// getDescription - Return the description of the specified custom
370 StringRef
getDescription(unsigned DiagID
) const {
371 assert(DiagID
- DIAG_UPPER_LIMIT
< DiagInfo
.size() &&
372 "Invalid diagnostic ID");
373 return DiagInfo
[DiagID
-DIAG_UPPER_LIMIT
].second
;
376 /// getLevel - Return the level of the specified custom diagnostic.
377 DiagnosticIDs::Level
getLevel(unsigned DiagID
) const {
378 assert(DiagID
- DIAG_UPPER_LIMIT
< DiagInfo
.size() &&
379 "Invalid diagnostic ID");
380 return DiagInfo
[DiagID
-DIAG_UPPER_LIMIT
].first
;
383 unsigned getOrCreateDiagID(DiagnosticIDs::Level L
, StringRef Message
,
384 DiagnosticIDs
&Diags
) {
385 DiagDesc
D(L
, std::string(Message
));
386 // Check to see if it already exists.
387 std::map
<DiagDesc
, unsigned>::iterator I
= DiagIDs
.lower_bound(D
);
388 if (I
!= DiagIDs
.end() && I
->first
== D
)
391 // If not, assign a new ID.
392 unsigned ID
= DiagInfo
.size()+DIAG_UPPER_LIMIT
;
393 DiagIDs
.insert(std::make_pair(D
, ID
));
394 DiagInfo
.push_back(D
);
399 } // end diag namespace
400 } // end clang namespace
403 //===----------------------------------------------------------------------===//
404 // Common Diagnostic implementation
405 //===----------------------------------------------------------------------===//
407 DiagnosticIDs::DiagnosticIDs() {}
409 DiagnosticIDs::~DiagnosticIDs() {}
411 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
412 /// and level. If this is the first request for this diagnostic, it is
413 /// registered and created, otherwise the existing ID is returned.
415 /// \param FormatString A fixed diagnostic format string that will be hashed and
416 /// mapped to a unique DiagID.
417 unsigned DiagnosticIDs::getCustomDiagID(Level L
, StringRef FormatString
) {
419 CustomDiagInfo
.reset(new diag::CustomDiagInfo());
420 return CustomDiagInfo
->getOrCreateDiagID(L
, FormatString
, *this);
424 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
425 /// level of the specified diagnostic ID is a Warning or Extension.
426 /// This only works on builtin diagnostics, not custom ones, and is not legal to
428 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID
) {
429 return DiagID
< diag::DIAG_UPPER_LIMIT
&&
430 getBuiltinDiagClass(DiagID
) != CLASS_ERROR
;
433 /// Determine whether the given built-in diagnostic ID is a
435 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID
) {
436 return DiagID
< diag::DIAG_UPPER_LIMIT
&&
437 getBuiltinDiagClass(DiagID
) == CLASS_NOTE
;
440 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
441 /// ID is for an extension of some sort. This also returns EnabledByDefault,
442 /// which is set to indicate whether the diagnostic is ignored by default (in
443 /// which case -pedantic enables it) or treated as a warning/error by default.
445 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID
,
446 bool &EnabledByDefault
) {
447 if (DiagID
>= diag::DIAG_UPPER_LIMIT
||
448 getBuiltinDiagClass(DiagID
) != CLASS_EXTENSION
)
452 GetDefaultDiagMapping(DiagID
).getSeverity() != diag::Severity::Ignored
;
456 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID
) {
457 if (DiagID
>= diag::DIAG_UPPER_LIMIT
)
460 return GetDefaultDiagMapping(DiagID
).getSeverity() >= diag::Severity::Error
;
463 /// getDescription - Given a diagnostic ID, return a description of the
465 StringRef
DiagnosticIDs::getDescription(unsigned DiagID
) const {
466 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
467 return Info
->getDescription();
468 assert(CustomDiagInfo
&& "Invalid CustomDiagInfo");
469 return CustomDiagInfo
->getDescription(DiagID
);
472 static DiagnosticIDs::Level
toLevel(diag::Severity SV
) {
474 case diag::Severity::Ignored
:
475 return DiagnosticIDs::Ignored
;
476 case diag::Severity::Remark
:
477 return DiagnosticIDs::Remark
;
478 case diag::Severity::Warning
:
479 return DiagnosticIDs::Warning
;
480 case diag::Severity::Error
:
481 return DiagnosticIDs::Error
;
482 case diag::Severity::Fatal
:
483 return DiagnosticIDs::Fatal
;
485 llvm_unreachable("unexpected severity");
488 /// getDiagnosticLevel - Based on the way the client configured the
489 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level,
490 /// by consumable the DiagnosticClient.
492 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID
, SourceLocation Loc
,
493 const DiagnosticsEngine
&Diag
) const {
494 // Handle custom diagnostics, which cannot be mapped.
495 if (DiagID
>= diag::DIAG_UPPER_LIMIT
) {
496 assert(CustomDiagInfo
&& "Invalid CustomDiagInfo");
497 return CustomDiagInfo
->getLevel(DiagID
);
500 unsigned DiagClass
= getBuiltinDiagClass(DiagID
);
501 if (DiagClass
== CLASS_NOTE
) return DiagnosticIDs::Note
;
502 return toLevel(getDiagnosticSeverity(DiagID
, Loc
, Diag
));
505 /// Based on the way the client configured the Diagnostic
506 /// object, classify the specified diagnostic ID into a Level, consumable by
507 /// the DiagnosticClient.
509 /// \param Loc The source location we are interested in finding out the
510 /// diagnostic state. Can be null in order to query the latest state.
512 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID
, SourceLocation Loc
,
513 const DiagnosticsEngine
&Diag
) const {
514 assert(getBuiltinDiagClass(DiagID
) != CLASS_NOTE
);
516 // Specific non-error diagnostics may be mapped to various levels from ignored
517 // to error. Errors can only be mapped to fatal.
518 diag::Severity Result
= diag::Severity::Fatal
;
520 // Get the mapping information, or compute it lazily.
521 DiagnosticsEngine::DiagState
*State
= Diag
.GetDiagStateForLoc(Loc
);
522 DiagnosticMapping
&Mapping
= State
->getOrAddMapping((diag::kind
)DiagID
);
524 // TODO: Can a null severity really get here?
525 if (Mapping
.getSeverity() != diag::Severity())
526 Result
= Mapping
.getSeverity();
528 // Upgrade ignored diagnostics if -Weverything is enabled.
529 if (State
->EnableAllWarnings
&& Result
== diag::Severity::Ignored
&&
530 !Mapping
.isUser() && getBuiltinDiagClass(DiagID
) != CLASS_REMARK
)
531 Result
= diag::Severity::Warning
;
533 // Ignore -pedantic diagnostics inside __extension__ blocks.
534 // (The diagnostics controlled by -pedantic are the extension diagnostics
535 // that are not enabled by default.)
536 bool EnabledByDefault
= false;
537 bool IsExtensionDiag
= isBuiltinExtensionDiag(DiagID
, EnabledByDefault
);
538 if (Diag
.AllExtensionsSilenced
&& IsExtensionDiag
&& !EnabledByDefault
)
539 return diag::Severity::Ignored
;
541 // For extension diagnostics that haven't been explicitly mapped, check if we
542 // should upgrade the diagnostic.
543 if (IsExtensionDiag
&& !Mapping
.isUser())
544 Result
= std::max(Result
, State
->ExtBehavior
);
546 // At this point, ignored errors can no longer be upgraded.
547 if (Result
== diag::Severity::Ignored
)
550 // Honor -w: this disables all messages which are not Error/Fatal by
551 // default (disregarding attempts to upgrade severity from Warning to Error),
552 // as well as disabling all messages which are currently mapped to Warning
553 // (whether by default or downgraded from Error via e.g. -Wno-error or #pragma
555 if (State
->IgnoreAllWarnings
) {
556 if (Result
== diag::Severity::Warning
||
557 (Result
>= diag::Severity::Error
&&
558 !isDefaultMappingAsError((diag::kind
)DiagID
)))
559 return diag::Severity::Ignored
;
562 // If -Werror is enabled, map warnings to errors unless explicitly disabled.
563 if (Result
== diag::Severity::Warning
) {
564 if (State
->WarningsAsErrors
&& !Mapping
.hasNoWarningAsError())
565 Result
= diag::Severity::Error
;
568 // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
570 if (Result
== diag::Severity::Error
) {
571 if (State
->ErrorsAsFatal
&& !Mapping
.hasNoErrorAsFatal())
572 Result
= diag::Severity::Fatal
;
575 // If explicitly requested, map fatal errors to errors.
576 if (Result
== diag::Severity::Fatal
&&
577 Diag
.CurDiagID
!= diag::fatal_too_many_errors
&& Diag
.FatalsAsError
)
578 Result
= diag::Severity::Error
;
580 // Custom diagnostics always are emitted in system headers.
581 bool ShowInSystemHeader
=
582 !GetDiagInfo(DiagID
) || GetDiagInfo(DiagID
)->WarnShowInSystemHeader
;
584 // If we are in a system header, we ignore it. We look at the diagnostic class
585 // because we also want to ignore extensions and warnings in -Werror and
586 // -pedantic-errors modes, which *map* warnings/extensions to errors.
587 if (State
->SuppressSystemWarnings
&& !ShowInSystemHeader
&& Loc
.isValid() &&
588 Diag
.getSourceManager().isInSystemHeader(
589 Diag
.getSourceManager().getExpansionLoc(Loc
)))
590 return diag::Severity::Ignored
;
592 // We also ignore warnings due to system macros
593 bool ShowInSystemMacro
=
594 !GetDiagInfo(DiagID
) || GetDiagInfo(DiagID
)->WarnShowInSystemMacro
;
595 if (State
->SuppressSystemWarnings
&& !ShowInSystemMacro
&& Loc
.isValid() &&
596 Diag
.getSourceManager().isInSystemMacro(Loc
))
597 return diag::Severity::Ignored
;
602 #define GET_DIAG_ARRAYS
603 #include "clang/Basic/DiagnosticGroups.inc"
604 #undef GET_DIAG_ARRAYS
607 struct WarningOption
{
611 StringRef Documentation
;
613 // String is stored with a pascal-style length byte.
614 StringRef
getName() const {
615 return StringRef(DiagGroupNames
+ NameOffset
+ 1,
616 DiagGroupNames
[NameOffset
]);
621 // Second the table of options, sorted by name for fast binary lookup.
622 static const WarningOption OptionTable
[] = {
623 #define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
624 {FlagNameOffset, Members, SubGroups, Docs},
625 #include "clang/Basic/DiagnosticGroups.inc"
629 /// Given a diagnostic group ID, return its documentation.
630 StringRef
DiagnosticIDs::getWarningOptionDocumentation(diag::Group Group
) {
631 return OptionTable
[static_cast<int>(Group
)].Documentation
;
634 StringRef
DiagnosticIDs::getWarningOptionForGroup(diag::Group Group
) {
635 return OptionTable
[static_cast<int>(Group
)].getName();
638 std::optional
<diag::Group
>
639 DiagnosticIDs::getGroupForWarningOption(StringRef Name
) {
640 const auto *Found
= llvm::partition_point(
641 OptionTable
, [=](const WarningOption
&O
) { return O
.getName() < Name
; });
642 if (Found
== std::end(OptionTable
) || Found
->getName() != Name
)
644 return static_cast<diag::Group
>(Found
- OptionTable
);
647 std::optional
<diag::Group
> DiagnosticIDs::getGroupForDiag(unsigned DiagID
) {
648 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
649 return static_cast<diag::Group
>(Info
->getOptionGroupIndex());
653 /// getWarningOptionForDiag - Return the lowest-level warning option that
654 /// enables the specified diagnostic. If there is no -Wfoo flag that controls
655 /// the diagnostic, this returns null.
656 StringRef
DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID
) {
657 if (auto G
= getGroupForDiag(DiagID
))
658 return getWarningOptionForGroup(*G
);
662 std::vector
<std::string
> DiagnosticIDs::getDiagnosticFlags() {
663 std::vector
<std::string
> Res
{"-W", "-Wno-"};
664 for (size_t I
= 1; DiagGroupNames
[I
] != '\0';) {
665 std::string
Diag(DiagGroupNames
+ I
+ 1, DiagGroupNames
[I
]);
666 I
+= DiagGroupNames
[I
] + 1;
667 Res
.push_back("-W" + Diag
);
668 Res
.push_back("-Wno-" + Diag
);
674 /// Return \c true if any diagnostics were found in this group, even if they
675 /// were filtered out due to having the wrong flavor.
676 static bool getDiagnosticsInGroup(diag::Flavor Flavor
,
677 const WarningOption
*Group
,
678 SmallVectorImpl
<diag::kind
> &Diags
) {
679 // An empty group is considered to be a warning group: we have empty groups
680 // for GCC compatibility, and GCC does not have remarks.
681 if (!Group
->Members
&& !Group
->SubGroups
)
682 return Flavor
== diag::Flavor::Remark
;
684 bool NotFound
= true;
686 // Add the members of the option diagnostic set.
687 const int16_t *Member
= DiagArrays
+ Group
->Members
;
688 for (; *Member
!= -1; ++Member
) {
689 if (GetDiagInfo(*Member
)->getFlavor() == Flavor
) {
691 Diags
.push_back(*Member
);
695 // Add the members of the subgroups.
696 const int16_t *SubGroups
= DiagSubGroups
+ Group
->SubGroups
;
697 for (; *SubGroups
!= (int16_t)-1; ++SubGroups
)
698 NotFound
&= getDiagnosticsInGroup(Flavor
, &OptionTable
[(short)*SubGroups
],
705 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor
, StringRef Group
,
706 SmallVectorImpl
<diag::kind
> &Diags
) const {
707 if (std::optional
<diag::Group
> G
= getGroupForWarningOption(Group
))
708 return ::getDiagnosticsInGroup(
709 Flavor
, &OptionTable
[static_cast<unsigned>(*G
)], Diags
);
713 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor
,
714 std::vector
<diag::kind
> &Diags
) {
715 for (unsigned i
= 0; i
!= StaticDiagInfoSize
; ++i
)
716 if (StaticDiagInfo
[i
].getFlavor() == Flavor
)
717 Diags
.push_back(StaticDiagInfo
[i
].DiagID
);
720 StringRef
DiagnosticIDs::getNearestOption(diag::Flavor Flavor
,
723 unsigned BestDistance
= Group
.size() + 1; // Maximum threshold.
724 for (const WarningOption
&O
: OptionTable
) {
725 // Don't suggest ignored warning flags.
726 if (!O
.Members
&& !O
.SubGroups
)
729 unsigned Distance
= O
.getName().edit_distance(Group
, true, BestDistance
);
730 if (Distance
> BestDistance
)
733 // Don't suggest groups that are not of this kind.
734 llvm::SmallVector
<diag::kind
, 8> Diags
;
735 if (::getDiagnosticsInGroup(Flavor
, &O
, Diags
) || Diags
.empty())
738 if (Distance
== BestDistance
) {
739 // Two matches with the same distance, don't prefer one over the other.
741 } else if (Distance
< BestDistance
) {
742 // This is a better match.
744 BestDistance
= Distance
;
751 /// ProcessDiag - This is the method used to report a diagnostic that is
752 /// finally fully formed.
753 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine
&Diag
) const {
754 Diagnostic
Info(&Diag
);
756 assert(Diag
.getClient() && "DiagnosticClient not set!");
758 // Figure out the diagnostic level of this message.
759 unsigned DiagID
= Info
.getID();
760 DiagnosticIDs::Level DiagLevel
761 = getDiagnosticLevel(DiagID
, Info
.getLocation(), Diag
);
763 // Update counts for DiagnosticErrorTrap even if a fatal error occurred
764 // or diagnostics are suppressed.
765 if (DiagLevel
>= DiagnosticIDs::Error
) {
766 ++Diag
.TrapNumErrorsOccurred
;
767 if (isUnrecoverable(DiagID
))
768 ++Diag
.TrapNumUnrecoverableErrorsOccurred
;
771 if (Diag
.SuppressAllDiagnostics
)
774 if (DiagLevel
!= DiagnosticIDs::Note
) {
775 // Record that a fatal error occurred only when we see a second
776 // non-note diagnostic. This allows notes to be attached to the
777 // fatal error, but suppresses any diagnostics that follow those
779 if (Diag
.LastDiagLevel
== DiagnosticIDs::Fatal
)
780 Diag
.FatalErrorOccurred
= true;
782 Diag
.LastDiagLevel
= DiagLevel
;
785 // If a fatal error has already been emitted, silence all subsequent
787 if (Diag
.FatalErrorOccurred
) {
788 if (DiagLevel
>= DiagnosticIDs::Error
&&
789 Diag
.Client
->IncludeInDiagnosticCounts()) {
796 // If the client doesn't care about this message, don't issue it. If this is
797 // a note and the last real diagnostic was ignored, ignore it too.
798 if (DiagLevel
== DiagnosticIDs::Ignored
||
799 (DiagLevel
== DiagnosticIDs::Note
&&
800 Diag
.LastDiagLevel
== DiagnosticIDs::Ignored
))
803 if (DiagLevel
>= DiagnosticIDs::Error
) {
804 if (isUnrecoverable(DiagID
))
805 Diag
.UnrecoverableErrorOccurred
= true;
807 // Warnings which have been upgraded to errors do not prevent compilation.
808 if (isDefaultMappingAsError(DiagID
))
809 Diag
.UncompilableErrorOccurred
= true;
811 Diag
.ErrorOccurred
= true;
812 if (Diag
.Client
->IncludeInDiagnosticCounts()) {
816 // If we've emitted a lot of errors, emit a fatal error instead of it to
817 // stop a flood of bogus errors.
818 if (Diag
.ErrorLimit
&& Diag
.NumErrors
> Diag
.ErrorLimit
&&
819 DiagLevel
== DiagnosticIDs::Error
) {
820 Diag
.SetDelayedDiagnostic(diag::fatal_too_many_errors
);
825 // Make sure we set FatalErrorOccurred to ensure that the notes from the
826 // diagnostic that caused `fatal_too_many_errors` won't be emitted.
827 if (Diag
.CurDiagID
== diag::fatal_too_many_errors
)
828 Diag
.FatalErrorOccurred
= true;
829 // Finally, report it.
830 EmitDiag(Diag
, DiagLevel
);
834 void DiagnosticIDs::EmitDiag(DiagnosticsEngine
&Diag
, Level DiagLevel
) const {
835 Diagnostic
Info(&Diag
);
836 assert(DiagLevel
!= DiagnosticIDs::Ignored
&& "Cannot emit ignored diagnostics!");
838 Diag
.Client
->HandleDiagnostic((DiagnosticsEngine::Level
)DiagLevel
, Info
);
839 if (Diag
.Client
->IncludeInDiagnosticCounts()) {
840 if (DiagLevel
== DiagnosticIDs::Warning
)
844 Diag
.CurDiagID
= ~0U;
847 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID
) const {
848 if (DiagID
>= diag::DIAG_UPPER_LIMIT
) {
849 assert(CustomDiagInfo
&& "Invalid CustomDiagInfo");
850 // Custom diagnostics.
851 return CustomDiagInfo
->getLevel(DiagID
) >= DiagnosticIDs::Error
;
854 // Only errors may be unrecoverable.
855 if (getBuiltinDiagClass(DiagID
) < CLASS_ERROR
)
858 if (DiagID
== diag::err_unavailable
||
859 DiagID
== diag::err_unavailable_message
)
862 // Currently we consider all ARC errors as recoverable.
863 if (isARCDiagnostic(DiagID
))
869 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID
) {
870 unsigned cat
= getCategoryNumberForDiag(DiagID
);
871 return DiagnosticIDs::getCategoryNameFromID(cat
).startswith("ARC ");