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"
21 using namespace clang
;
23 //===----------------------------------------------------------------------===//
24 // Builtin Diagnostic information
25 //===----------------------------------------------------------------------===//
29 struct StaticDiagInfoRec
;
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, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
37 char ENUM##_desc[sizeof(DESC)];
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"
55 const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions
= {
56 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
57 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
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"
76 extern const StaticDiagInfoRec StaticDiagInfo
[];
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, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
83 offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc),
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"
101 // Diagnostic classes.
105 CLASS_WARNING
= 0x03,
106 CLASS_EXTENSION
= 0x04,
110 struct StaticDiagInfoRec
{
112 uint8_t DefaultSeverity
: 3;
115 uint8_t Category
: 6;
116 uint8_t WarnNoWerror
: 1;
117 uint8_t WarnShowInSystemHeader
: 1;
118 uint8_t WarnShowInSystemMacro
: 1;
120 uint16_t OptionGroupIndex
: 15;
121 uint16_t Deferrable
: 1;
123 uint16_t DescriptionLen
;
125 unsigned getOptionGroupIndex() const {
126 return OptionGroupIndex
;
129 StringRef
getDescription() const {
130 size_t MyIndex
= this - &StaticDiagInfo
[0];
131 uint32_t StringOffset
= StaticDiagInfoDescriptionOffsets
[MyIndex
];
132 const char* Table
= reinterpret_cast<const char*>(&StaticDiagInfoDescriptions
);
133 return StringRef(&Table
[StringOffset
], DescriptionLen
);
136 diag::Flavor
getFlavor() const {
137 return Class
== CLASS_REMARK
? diag::Flavor::Remark
138 : diag::Flavor::WarningOrError
;
141 bool operator<(const StaticDiagInfoRec
&RHS
) const {
142 return DiagID
< RHS
.DiagID
;
146 #define STRINGIFY_NAME(NAME) #NAME
147 #define VALIDATE_DIAG_SIZE(NAME) \
149 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
150 static_cast<unsigned>(diag::DIAG_START_##NAME) + \
151 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
153 DIAG_SIZE_##NAME) " is insufficient to contain all " \
154 "diagnostics, it may need to be made larger in " \
156 VALIDATE_DIAG_SIZE(COMMON
)
157 VALIDATE_DIAG_SIZE(DRIVER
)
158 VALIDATE_DIAG_SIZE(FRONTEND
)
159 VALIDATE_DIAG_SIZE(SERIALIZATION
)
160 VALIDATE_DIAG_SIZE(LEX
)
161 VALIDATE_DIAG_SIZE(PARSE
)
162 VALIDATE_DIAG_SIZE(AST
)
163 VALIDATE_DIAG_SIZE(COMMENT
)
164 VALIDATE_DIAG_SIZE(CROSSTU
)
165 VALIDATE_DIAG_SIZE(SEMA
)
166 VALIDATE_DIAG_SIZE(ANALYSIS
)
167 VALIDATE_DIAG_SIZE(REFACTORING
)
168 #undef VALIDATE_DIAG_SIZE
169 #undef STRINGIFY_NAME
171 const StaticDiagInfoRec StaticDiagInfo
[] = {
173 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
174 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
179 DiagnosticIDs::SFINAE, \
186 STR_SIZE(DESC, uint16_t)},
187 #include "clang/Basic/DiagnosticCommonKinds.inc"
188 #include "clang/Basic/DiagnosticDriverKinds.inc"
189 #include "clang/Basic/DiagnosticFrontendKinds.inc"
190 #include "clang/Basic/DiagnosticSerializationKinds.inc"
191 #include "clang/Basic/DiagnosticLexKinds.inc"
192 #include "clang/Basic/DiagnosticParseKinds.inc"
193 #include "clang/Basic/DiagnosticASTKinds.inc"
194 #include "clang/Basic/DiagnosticCommentKinds.inc"
195 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
196 #include "clang/Basic/DiagnosticSemaKinds.inc"
197 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
198 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
205 static const unsigned StaticDiagInfoSize
= std::size(StaticDiagInfo
);
207 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
208 /// or null if the ID is invalid.
209 static const StaticDiagInfoRec
*GetDiagInfo(unsigned DiagID
) {
210 // Out of bounds diag. Can't be in the table.
211 using namespace diag
;
212 if (DiagID
>= DIAG_UPPER_LIMIT
|| DiagID
<= DIAG_START_COMMON
)
215 // Compute the index of the requested diagnostic in the static table.
216 // 1. Add the number of diagnostics in each category preceding the
217 // diagnostic and of the category the diagnostic is in. This gives us
218 // the offset of the category in the table.
219 // 2. Subtract the number of IDs in each category from our ID. This gives us
220 // the offset of the diagnostic in the category.
221 // This is cheaper than a binary search on the table as it doesn't touch
224 unsigned ID
= DiagID
- DIAG_START_COMMON
- 1;
225 #define CATEGORY(NAME, PREV) \
226 if (DiagID > DIAG_START_##NAME) { \
227 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
228 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
230 CATEGORY(DRIVER
, COMMON
)
231 CATEGORY(FRONTEND
, DRIVER
)
232 CATEGORY(SERIALIZATION
, FRONTEND
)
233 CATEGORY(LEX
, SERIALIZATION
)
236 CATEGORY(COMMENT
, AST
)
237 CATEGORY(CROSSTU
, COMMENT
)
238 CATEGORY(SEMA
, CROSSTU
)
239 CATEGORY(ANALYSIS
, SEMA
)
240 CATEGORY(REFACTORING
, ANALYSIS
)
243 // Avoid out of bounds reads.
244 if (ID
+ Offset
>= StaticDiagInfoSize
)
247 assert(ID
< StaticDiagInfoSize
&& Offset
< StaticDiagInfoSize
);
249 const StaticDiagInfoRec
*Found
= &StaticDiagInfo
[ID
+ Offset
];
250 // If the diag id doesn't match we found a different diag, abort. This can
251 // happen when this function is called with an ID that points into a hole in
253 if (Found
->DiagID
!= DiagID
)
258 static DiagnosticMapping
GetDefaultDiagMapping(unsigned DiagID
) {
259 DiagnosticMapping Info
= DiagnosticMapping::Make(
260 diag::Severity::Fatal
, /*IsUser=*/false, /*IsPragma=*/false);
262 if (const StaticDiagInfoRec
*StaticInfo
= GetDiagInfo(DiagID
)) {
263 Info
.setSeverity((diag::Severity
)StaticInfo
->DefaultSeverity
);
265 if (StaticInfo
->WarnNoWerror
) {
266 assert(Info
.getSeverity() == diag::Severity::Warning
&&
267 "Unexpected mapping with no-Werror bit!");
268 Info
.setNoWarningAsError(true);
275 /// getCategoryNumberForDiag - Return the category number that a specified
276 /// DiagID belongs to, or 0 if no category.
277 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID
) {
278 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
279 return Info
->Category
;
284 // The diagnostic category names.
285 struct StaticDiagCategoryRec
{
289 StringRef
getName() const {
290 return StringRef(NameStr
, NameLen
);
295 // Unfortunately, the split between DiagnosticIDs and Diagnostic is not
296 // particularly clean, but for now we just implement this method here so we can
297 // access GetDefaultDiagMapping.
299 DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag
) {
300 std::pair
<iterator
, bool> Result
=
301 DiagMap
.insert(std::make_pair(Diag
, DiagnosticMapping()));
303 // Initialize the entry if we added it.
305 Result
.first
->second
= GetDefaultDiagMapping(Diag
);
307 return Result
.first
->second
;
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 GetDefaultDiagMapping(DiagID
).getSeverity() != diag::Severity::Ignored
;
455 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID
) {
456 if (DiagID
>= diag::DIAG_UPPER_LIMIT
)
459 return GetDefaultDiagMapping(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 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 Diag
.CurDiagID
!= diag::fatal_too_many_errors
&& Diag
.FatalsAsError
)
577 Result
= diag::Severity::Error
;
579 // Custom diagnostics always are emitted in system headers.
580 bool ShowInSystemHeader
=
581 !GetDiagInfo(DiagID
) || GetDiagInfo(DiagID
)->WarnShowInSystemHeader
;
583 // If we are in a system header, we ignore it. We look at the diagnostic class
584 // because we also want to ignore extensions and warnings in -Werror and
585 // -pedantic-errors modes, which *map* warnings/extensions to errors.
586 if (State
->SuppressSystemWarnings
&& !ShowInSystemHeader
&& Loc
.isValid() &&
587 Diag
.getSourceManager().isInSystemHeader(
588 Diag
.getSourceManager().getExpansionLoc(Loc
)))
589 return diag::Severity::Ignored
;
591 // We also ignore warnings due to system macros
592 bool ShowInSystemMacro
=
593 !GetDiagInfo(DiagID
) || GetDiagInfo(DiagID
)->WarnShowInSystemMacro
;
594 if (State
->SuppressSystemWarnings
&& !ShowInSystemMacro
&& Loc
.isValid() &&
595 Diag
.getSourceManager().isInSystemMacro(Loc
))
596 return diag::Severity::Ignored
;
601 #define GET_DIAG_ARRAYS
602 #include "clang/Basic/DiagnosticGroups.inc"
603 #undef GET_DIAG_ARRAYS
606 struct WarningOption
{
610 StringRef Documentation
;
612 // String is stored with a pascal-style length byte.
613 StringRef
getName() const {
614 return StringRef(DiagGroupNames
+ NameOffset
+ 1,
615 DiagGroupNames
[NameOffset
]);
620 // Second the table of options, sorted by name for fast binary lookup.
621 static const WarningOption OptionTable
[] = {
622 #define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
623 {FlagNameOffset, Members, SubGroups, Docs},
624 #include "clang/Basic/DiagnosticGroups.inc"
628 /// Given a diagnostic group ID, return its documentation.
629 StringRef
DiagnosticIDs::getWarningOptionDocumentation(diag::Group Group
) {
630 return OptionTable
[static_cast<int>(Group
)].Documentation
;
633 StringRef
DiagnosticIDs::getWarningOptionForGroup(diag::Group Group
) {
634 return OptionTable
[static_cast<int>(Group
)].getName();
637 llvm::Optional
<diag::Group
>
638 DiagnosticIDs::getGroupForWarningOption(StringRef Name
) {
639 const auto *Found
= llvm::partition_point(
640 OptionTable
, [=](const WarningOption
&O
) { return O
.getName() < Name
; });
641 if (Found
== std::end(OptionTable
) || Found
->getName() != Name
)
643 return static_cast<diag::Group
>(Found
- OptionTable
);
646 llvm::Optional
<diag::Group
> DiagnosticIDs::getGroupForDiag(unsigned DiagID
) {
647 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
648 return static_cast<diag::Group
>(Info
->getOptionGroupIndex());
652 /// getWarningOptionForDiag - Return the lowest-level warning option that
653 /// enables the specified diagnostic. If there is no -Wfoo flag that controls
654 /// the diagnostic, this returns null.
655 StringRef
DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID
) {
656 if (auto G
= getGroupForDiag(DiagID
))
657 return getWarningOptionForGroup(*G
);
661 std::vector
<std::string
> DiagnosticIDs::getDiagnosticFlags() {
662 std::vector
<std::string
> Res
{"-W", "-Wno-"};
663 for (size_t I
= 1; DiagGroupNames
[I
] != '\0';) {
664 std::string
Diag(DiagGroupNames
+ I
+ 1, DiagGroupNames
[I
]);
665 I
+= DiagGroupNames
[I
] + 1;
666 Res
.push_back("-W" + Diag
);
667 Res
.push_back("-Wno-" + Diag
);
673 /// Return \c true if any diagnostics were found in this group, even if they
674 /// were filtered out due to having the wrong flavor.
675 static bool getDiagnosticsInGroup(diag::Flavor Flavor
,
676 const WarningOption
*Group
,
677 SmallVectorImpl
<diag::kind
> &Diags
) {
678 // An empty group is considered to be a warning group: we have empty groups
679 // for GCC compatibility, and GCC does not have remarks.
680 if (!Group
->Members
&& !Group
->SubGroups
)
681 return Flavor
== diag::Flavor::Remark
;
683 bool NotFound
= true;
685 // Add the members of the option diagnostic set.
686 const int16_t *Member
= DiagArrays
+ Group
->Members
;
687 for (; *Member
!= -1; ++Member
) {
688 if (GetDiagInfo(*Member
)->getFlavor() == Flavor
) {
690 Diags
.push_back(*Member
);
694 // Add the members of the subgroups.
695 const int16_t *SubGroups
= DiagSubGroups
+ Group
->SubGroups
;
696 for (; *SubGroups
!= (int16_t)-1; ++SubGroups
)
697 NotFound
&= getDiagnosticsInGroup(Flavor
, &OptionTable
[(short)*SubGroups
],
704 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor
, StringRef Group
,
705 SmallVectorImpl
<diag::kind
> &Diags
) const {
706 if (llvm::Optional
<diag::Group
> G
= getGroupForWarningOption(Group
))
707 return ::getDiagnosticsInGroup(
708 Flavor
, &OptionTable
[static_cast<unsigned>(*G
)], Diags
);
712 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor
,
713 std::vector
<diag::kind
> &Diags
) {
714 for (unsigned i
= 0; i
!= StaticDiagInfoSize
; ++i
)
715 if (StaticDiagInfo
[i
].getFlavor() == Flavor
)
716 Diags
.push_back(StaticDiagInfo
[i
].DiagID
);
719 StringRef
DiagnosticIDs::getNearestOption(diag::Flavor Flavor
,
722 unsigned BestDistance
= Group
.size() + 1; // Maximum threshold.
723 for (const WarningOption
&O
: OptionTable
) {
724 // Don't suggest ignored warning flags.
725 if (!O
.Members
&& !O
.SubGroups
)
728 unsigned Distance
= O
.getName().edit_distance(Group
, true, BestDistance
);
729 if (Distance
> BestDistance
)
732 // Don't suggest groups that are not of this kind.
733 llvm::SmallVector
<diag::kind
, 8> Diags
;
734 if (::getDiagnosticsInGroup(Flavor
, &O
, Diags
) || Diags
.empty())
737 if (Distance
== BestDistance
) {
738 // Two matches with the same distance, don't prefer one over the other.
740 } else if (Distance
< BestDistance
) {
741 // This is a better match.
743 BestDistance
= Distance
;
750 /// ProcessDiag - This is the method used to report a diagnostic that is
751 /// finally fully formed.
752 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine
&Diag
) const {
753 Diagnostic
Info(&Diag
);
755 assert(Diag
.getClient() && "DiagnosticClient not set!");
757 // Figure out the diagnostic level of this message.
758 unsigned DiagID
= Info
.getID();
759 DiagnosticIDs::Level DiagLevel
760 = getDiagnosticLevel(DiagID
, Info
.getLocation(), Diag
);
762 // Update counts for DiagnosticErrorTrap even if a fatal error occurred
763 // or diagnostics are suppressed.
764 if (DiagLevel
>= DiagnosticIDs::Error
) {
765 ++Diag
.TrapNumErrorsOccurred
;
766 if (isUnrecoverable(DiagID
))
767 ++Diag
.TrapNumUnrecoverableErrorsOccurred
;
770 if (Diag
.SuppressAllDiagnostics
)
773 if (DiagLevel
!= DiagnosticIDs::Note
) {
774 // Record that a fatal error occurred only when we see a second
775 // non-note diagnostic. This allows notes to be attached to the
776 // fatal error, but suppresses any diagnostics that follow those
778 if (Diag
.LastDiagLevel
== DiagnosticIDs::Fatal
)
779 Diag
.FatalErrorOccurred
= true;
781 Diag
.LastDiagLevel
= DiagLevel
;
784 // If a fatal error has already been emitted, silence all subsequent
786 if (Diag
.FatalErrorOccurred
) {
787 if (DiagLevel
>= DiagnosticIDs::Error
&&
788 Diag
.Client
->IncludeInDiagnosticCounts()) {
795 // If the client doesn't care about this message, don't issue it. If this is
796 // a note and the last real diagnostic was ignored, ignore it too.
797 if (DiagLevel
== DiagnosticIDs::Ignored
||
798 (DiagLevel
== DiagnosticIDs::Note
&&
799 Diag
.LastDiagLevel
== DiagnosticIDs::Ignored
))
802 if (DiagLevel
>= DiagnosticIDs::Error
) {
803 if (isUnrecoverable(DiagID
))
804 Diag
.UnrecoverableErrorOccurred
= true;
806 // Warnings which have been upgraded to errors do not prevent compilation.
807 if (isDefaultMappingAsError(DiagID
))
808 Diag
.UncompilableErrorOccurred
= true;
810 Diag
.ErrorOccurred
= true;
811 if (Diag
.Client
->IncludeInDiagnosticCounts()) {
815 // If we've emitted a lot of errors, emit a fatal error instead of it to
816 // stop a flood of bogus errors.
817 if (Diag
.ErrorLimit
&& Diag
.NumErrors
> Diag
.ErrorLimit
&&
818 DiagLevel
== DiagnosticIDs::Error
) {
819 Diag
.SetDelayedDiagnostic(diag::fatal_too_many_errors
);
824 // Make sure we set FatalErrorOccurred to ensure that the notes from the
825 // diagnostic that caused `fatal_too_many_errors` won't be emitted.
826 if (Diag
.CurDiagID
== diag::fatal_too_many_errors
)
827 Diag
.FatalErrorOccurred
= true;
828 // Finally, report it.
829 EmitDiag(Diag
, DiagLevel
);
833 void DiagnosticIDs::EmitDiag(DiagnosticsEngine
&Diag
, Level DiagLevel
) const {
834 Diagnostic
Info(&Diag
);
835 assert(DiagLevel
!= DiagnosticIDs::Ignored
&& "Cannot emit ignored diagnostics!");
837 Diag
.Client
->HandleDiagnostic((DiagnosticsEngine::Level
)DiagLevel
, Info
);
838 if (Diag
.Client
->IncludeInDiagnosticCounts()) {
839 if (DiagLevel
== DiagnosticIDs::Warning
)
843 Diag
.CurDiagID
= ~0U;
846 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID
) const {
847 if (DiagID
>= diag::DIAG_UPPER_LIMIT
) {
848 assert(CustomDiagInfo
&& "Invalid CustomDiagInfo");
849 // Custom diagnostics.
850 return CustomDiagInfo
->getLevel(DiagID
) >= DiagnosticIDs::Error
;
853 // Only errors may be unrecoverable.
854 if (getBuiltinDiagClass(DiagID
) < CLASS_ERROR
)
857 if (DiagID
== diag::err_unavailable
||
858 DiagID
== diag::err_unavailable_message
)
861 // Currently we consider all ARC errors as recoverable.
862 if (isARCDiagnostic(DiagID
))
868 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID
) {
869 unsigned cat
= getCategoryNumberForDiag(DiagID
);
870 return DiagnosticIDs::getCategoryNameFromID(cat
).startswith("ARC ");