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 DiagnosticMapping
DiagnosticIDs::getDefaultMapping(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 static const StaticDiagCategoryRec CategoryNameTable
[] = {
297 #define GET_CATEGORY_TABLE
298 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
299 #include "clang/Basic/DiagnosticGroups.inc"
300 #undef GET_CATEGORY_TABLE
304 /// getNumberOfCategories - Return the number of categories
305 unsigned DiagnosticIDs::getNumberOfCategories() {
306 return std::size(CategoryNameTable
) - 1;
309 /// getCategoryNameFromID - Given a category ID, return the name of the
310 /// category, an empty string if CategoryID is zero, or null if CategoryID is
312 StringRef
DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID
) {
313 if (CategoryID
>= getNumberOfCategories())
315 return CategoryNameTable
[CategoryID
].getName();
320 DiagnosticIDs::SFINAEResponse
321 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID
) {
322 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
323 return static_cast<DiagnosticIDs::SFINAEResponse
>(Info
->SFINAE
);
324 return SFINAE_Report
;
327 bool DiagnosticIDs::isDeferrable(unsigned DiagID
) {
328 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
329 return Info
->Deferrable
;
333 /// getBuiltinDiagClass - Return the class field of the diagnostic.
335 static unsigned getBuiltinDiagClass(unsigned DiagID
) {
336 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
341 //===----------------------------------------------------------------------===//
342 // Custom Diagnostic information
343 //===----------------------------------------------------------------------===//
347 class CustomDiagInfo
{
348 typedef std::pair
<DiagnosticIDs::Level
, std::string
> DiagDesc
;
349 std::vector
<DiagDesc
> DiagInfo
;
350 std::map
<DiagDesc
, unsigned> DiagIDs
;
353 /// getDescription - Return the description of the specified custom
355 StringRef
getDescription(unsigned DiagID
) const {
356 assert(DiagID
- DIAG_UPPER_LIMIT
< DiagInfo
.size() &&
357 "Invalid diagnostic ID");
358 return DiagInfo
[DiagID
-DIAG_UPPER_LIMIT
].second
;
361 /// getLevel - Return the level of the specified custom diagnostic.
362 DiagnosticIDs::Level
getLevel(unsigned DiagID
) const {
363 assert(DiagID
- DIAG_UPPER_LIMIT
< DiagInfo
.size() &&
364 "Invalid diagnostic ID");
365 return DiagInfo
[DiagID
-DIAG_UPPER_LIMIT
].first
;
368 unsigned getOrCreateDiagID(DiagnosticIDs::Level L
, StringRef Message
,
369 DiagnosticIDs
&Diags
) {
370 DiagDesc
D(L
, std::string(Message
));
371 // Check to see if it already exists.
372 std::map
<DiagDesc
, unsigned>::iterator I
= DiagIDs
.lower_bound(D
);
373 if (I
!= DiagIDs
.end() && I
->first
== D
)
376 // If not, assign a new ID.
377 unsigned ID
= DiagInfo
.size()+DIAG_UPPER_LIMIT
;
378 DiagIDs
.insert(std::make_pair(D
, ID
));
379 DiagInfo
.push_back(D
);
384 } // end diag namespace
385 } // end clang namespace
388 //===----------------------------------------------------------------------===//
389 // Common Diagnostic implementation
390 //===----------------------------------------------------------------------===//
392 DiagnosticIDs::DiagnosticIDs() {}
394 DiagnosticIDs::~DiagnosticIDs() {}
396 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
397 /// and level. If this is the first request for this diagnostic, it is
398 /// registered and created, otherwise the existing ID is returned.
400 /// \param FormatString A fixed diagnostic format string that will be hashed and
401 /// mapped to a unique DiagID.
402 unsigned DiagnosticIDs::getCustomDiagID(Level L
, StringRef FormatString
) {
404 CustomDiagInfo
.reset(new diag::CustomDiagInfo());
405 return CustomDiagInfo
->getOrCreateDiagID(L
, FormatString
, *this);
409 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
410 /// level of the specified diagnostic ID is a Warning or Extension.
411 /// This only works on builtin diagnostics, not custom ones, and is not legal to
413 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID
) {
414 return DiagID
< diag::DIAG_UPPER_LIMIT
&&
415 getBuiltinDiagClass(DiagID
) != CLASS_ERROR
;
418 /// Determine whether the given built-in diagnostic ID is a
420 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID
) {
421 return DiagID
< diag::DIAG_UPPER_LIMIT
&&
422 getBuiltinDiagClass(DiagID
) == CLASS_NOTE
;
425 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
426 /// ID is for an extension of some sort. This also returns EnabledByDefault,
427 /// which is set to indicate whether the diagnostic is ignored by default (in
428 /// which case -pedantic enables it) or treated as a warning/error by default.
430 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID
,
431 bool &EnabledByDefault
) {
432 if (DiagID
>= diag::DIAG_UPPER_LIMIT
||
433 getBuiltinDiagClass(DiagID
) != CLASS_EXTENSION
)
437 getDefaultMapping(DiagID
).getSeverity() != diag::Severity::Ignored
;
441 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID
) {
442 if (DiagID
>= diag::DIAG_UPPER_LIMIT
)
445 return getDefaultMapping(DiagID
).getSeverity() >= diag::Severity::Error
;
448 /// getDescription - Given a diagnostic ID, return a description of the
450 StringRef
DiagnosticIDs::getDescription(unsigned DiagID
) const {
451 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
452 return Info
->getDescription();
453 assert(CustomDiagInfo
&& "Invalid CustomDiagInfo");
454 return CustomDiagInfo
->getDescription(DiagID
);
457 static DiagnosticIDs::Level
toLevel(diag::Severity SV
) {
459 case diag::Severity::Ignored
:
460 return DiagnosticIDs::Ignored
;
461 case diag::Severity::Remark
:
462 return DiagnosticIDs::Remark
;
463 case diag::Severity::Warning
:
464 return DiagnosticIDs::Warning
;
465 case diag::Severity::Error
:
466 return DiagnosticIDs::Error
;
467 case diag::Severity::Fatal
:
468 return DiagnosticIDs::Fatal
;
470 llvm_unreachable("unexpected severity");
473 /// getDiagnosticLevel - Based on the way the client configured the
474 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level,
475 /// by consumable the DiagnosticClient.
477 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID
, SourceLocation Loc
,
478 const DiagnosticsEngine
&Diag
) const {
479 // Handle custom diagnostics, which cannot be mapped.
480 if (DiagID
>= diag::DIAG_UPPER_LIMIT
) {
481 assert(CustomDiagInfo
&& "Invalid CustomDiagInfo");
482 return CustomDiagInfo
->getLevel(DiagID
);
485 unsigned DiagClass
= getBuiltinDiagClass(DiagID
);
486 if (DiagClass
== CLASS_NOTE
) return DiagnosticIDs::Note
;
487 return toLevel(getDiagnosticSeverity(DiagID
, Loc
, Diag
));
490 /// Based on the way the client configured the Diagnostic
491 /// object, classify the specified diagnostic ID into a Level, consumable by
492 /// the DiagnosticClient.
494 /// \param Loc The source location we are interested in finding out the
495 /// diagnostic state. Can be null in order to query the latest state.
497 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID
, SourceLocation Loc
,
498 const DiagnosticsEngine
&Diag
) const {
499 assert(getBuiltinDiagClass(DiagID
) != CLASS_NOTE
);
501 // Specific non-error diagnostics may be mapped to various levels from ignored
502 // to error. Errors can only be mapped to fatal.
503 diag::Severity Result
= diag::Severity::Fatal
;
505 // Get the mapping information, or compute it lazily.
506 DiagnosticsEngine::DiagState
*State
= Diag
.GetDiagStateForLoc(Loc
);
507 DiagnosticMapping
&Mapping
= State
->getOrAddMapping((diag::kind
)DiagID
);
509 // TODO: Can a null severity really get here?
510 if (Mapping
.getSeverity() != diag::Severity())
511 Result
= Mapping
.getSeverity();
513 // Upgrade ignored diagnostics if -Weverything is enabled.
514 if (State
->EnableAllWarnings
&& Result
== diag::Severity::Ignored
&&
515 !Mapping
.isUser() && getBuiltinDiagClass(DiagID
) != CLASS_REMARK
)
516 Result
= diag::Severity::Warning
;
518 // Ignore -pedantic diagnostics inside __extension__ blocks.
519 // (The diagnostics controlled by -pedantic are the extension diagnostics
520 // that are not enabled by default.)
521 bool EnabledByDefault
= false;
522 bool IsExtensionDiag
= isBuiltinExtensionDiag(DiagID
, EnabledByDefault
);
523 if (Diag
.AllExtensionsSilenced
&& IsExtensionDiag
&& !EnabledByDefault
)
524 return diag::Severity::Ignored
;
526 // For extension diagnostics that haven't been explicitly mapped, check if we
527 // should upgrade the diagnostic.
528 if (IsExtensionDiag
&& !Mapping
.isUser())
529 Result
= std::max(Result
, State
->ExtBehavior
);
531 // At this point, ignored errors can no longer be upgraded.
532 if (Result
== diag::Severity::Ignored
)
535 // Honor -w: this disables all messages which are not Error/Fatal by
536 // default (disregarding attempts to upgrade severity from Warning to Error),
537 // as well as disabling all messages which are currently mapped to Warning
538 // (whether by default or downgraded from Error via e.g. -Wno-error or #pragma
540 if (State
->IgnoreAllWarnings
) {
541 if (Result
== diag::Severity::Warning
||
542 (Result
>= diag::Severity::Error
&&
543 !isDefaultMappingAsError((diag::kind
)DiagID
)))
544 return diag::Severity::Ignored
;
547 // If -Werror is enabled, map warnings to errors unless explicitly disabled.
548 if (Result
== diag::Severity::Warning
) {
549 if (State
->WarningsAsErrors
&& !Mapping
.hasNoWarningAsError())
550 Result
= diag::Severity::Error
;
553 // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
555 if (Result
== diag::Severity::Error
) {
556 if (State
->ErrorsAsFatal
&& !Mapping
.hasNoErrorAsFatal())
557 Result
= diag::Severity::Fatal
;
560 // If explicitly requested, map fatal errors to errors.
561 if (Result
== diag::Severity::Fatal
&&
562 Diag
.CurDiagID
!= diag::fatal_too_many_errors
&& Diag
.FatalsAsError
)
563 Result
= diag::Severity::Error
;
565 // Custom diagnostics always are emitted in system headers.
566 bool ShowInSystemHeader
=
567 !GetDiagInfo(DiagID
) || GetDiagInfo(DiagID
)->WarnShowInSystemHeader
;
569 // If we are in a system header, we ignore it. We look at the diagnostic class
570 // because we also want to ignore extensions and warnings in -Werror and
571 // -pedantic-errors modes, which *map* warnings/extensions to errors.
572 if (State
->SuppressSystemWarnings
&& !ShowInSystemHeader
&& Loc
.isValid() &&
573 Diag
.getSourceManager().isInSystemHeader(
574 Diag
.getSourceManager().getExpansionLoc(Loc
)))
575 return diag::Severity::Ignored
;
577 // We also ignore warnings due to system macros
578 bool ShowInSystemMacro
=
579 !GetDiagInfo(DiagID
) || GetDiagInfo(DiagID
)->WarnShowInSystemMacro
;
580 if (State
->SuppressSystemWarnings
&& !ShowInSystemMacro
&& Loc
.isValid() &&
581 Diag
.getSourceManager().isInSystemMacro(Loc
))
582 return diag::Severity::Ignored
;
587 #define GET_DIAG_ARRAYS
588 #include "clang/Basic/DiagnosticGroups.inc"
589 #undef GET_DIAG_ARRAYS
592 struct WarningOption
{
596 StringRef Documentation
;
598 // String is stored with a pascal-style length byte.
599 StringRef
getName() const {
600 return StringRef(DiagGroupNames
+ NameOffset
+ 1,
601 DiagGroupNames
[NameOffset
]);
606 // Second the table of options, sorted by name for fast binary lookup.
607 static const WarningOption OptionTable
[] = {
608 #define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
609 {FlagNameOffset, Members, SubGroups, Docs},
610 #include "clang/Basic/DiagnosticGroups.inc"
614 /// Given a diagnostic group ID, return its documentation.
615 StringRef
DiagnosticIDs::getWarningOptionDocumentation(diag::Group Group
) {
616 return OptionTable
[static_cast<int>(Group
)].Documentation
;
619 StringRef
DiagnosticIDs::getWarningOptionForGroup(diag::Group Group
) {
620 return OptionTable
[static_cast<int>(Group
)].getName();
623 std::optional
<diag::Group
>
624 DiagnosticIDs::getGroupForWarningOption(StringRef Name
) {
625 const auto *Found
= llvm::partition_point(
626 OptionTable
, [=](const WarningOption
&O
) { return O
.getName() < Name
; });
627 if (Found
== std::end(OptionTable
) || Found
->getName() != Name
)
629 return static_cast<diag::Group
>(Found
- OptionTable
);
632 std::optional
<diag::Group
> DiagnosticIDs::getGroupForDiag(unsigned DiagID
) {
633 if (const StaticDiagInfoRec
*Info
= GetDiagInfo(DiagID
))
634 return static_cast<diag::Group
>(Info
->getOptionGroupIndex());
638 /// getWarningOptionForDiag - Return the lowest-level warning option that
639 /// enables the specified diagnostic. If there is no -Wfoo flag that controls
640 /// the diagnostic, this returns null.
641 StringRef
DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID
) {
642 if (auto G
= getGroupForDiag(DiagID
))
643 return getWarningOptionForGroup(*G
);
647 std::vector
<std::string
> DiagnosticIDs::getDiagnosticFlags() {
648 std::vector
<std::string
> Res
{"-W", "-Wno-"};
649 for (size_t I
= 1; DiagGroupNames
[I
] != '\0';) {
650 std::string
Diag(DiagGroupNames
+ I
+ 1, DiagGroupNames
[I
]);
651 I
+= DiagGroupNames
[I
] + 1;
652 Res
.push_back("-W" + Diag
);
653 Res
.push_back("-Wno-" + Diag
);
659 /// Return \c true if any diagnostics were found in this group, even if they
660 /// were filtered out due to having the wrong flavor.
661 static bool getDiagnosticsInGroup(diag::Flavor Flavor
,
662 const WarningOption
*Group
,
663 SmallVectorImpl
<diag::kind
> &Diags
) {
664 // An empty group is considered to be a warning group: we have empty groups
665 // for GCC compatibility, and GCC does not have remarks.
666 if (!Group
->Members
&& !Group
->SubGroups
)
667 return Flavor
== diag::Flavor::Remark
;
669 bool NotFound
= true;
671 // Add the members of the option diagnostic set.
672 const int16_t *Member
= DiagArrays
+ Group
->Members
;
673 for (; *Member
!= -1; ++Member
) {
674 if (GetDiagInfo(*Member
)->getFlavor() == Flavor
) {
676 Diags
.push_back(*Member
);
680 // Add the members of the subgroups.
681 const int16_t *SubGroups
= DiagSubGroups
+ Group
->SubGroups
;
682 for (; *SubGroups
!= (int16_t)-1; ++SubGroups
)
683 NotFound
&= getDiagnosticsInGroup(Flavor
, &OptionTable
[(short)*SubGroups
],
690 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor
, StringRef Group
,
691 SmallVectorImpl
<diag::kind
> &Diags
) const {
692 if (std::optional
<diag::Group
> G
= getGroupForWarningOption(Group
))
693 return ::getDiagnosticsInGroup(
694 Flavor
, &OptionTable
[static_cast<unsigned>(*G
)], Diags
);
698 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor
,
699 std::vector
<diag::kind
> &Diags
) {
700 for (unsigned i
= 0; i
!= StaticDiagInfoSize
; ++i
)
701 if (StaticDiagInfo
[i
].getFlavor() == Flavor
)
702 Diags
.push_back(StaticDiagInfo
[i
].DiagID
);
705 StringRef
DiagnosticIDs::getNearestOption(diag::Flavor Flavor
,
708 unsigned BestDistance
= Group
.size() + 1; // Maximum threshold.
709 for (const WarningOption
&O
: OptionTable
) {
710 // Don't suggest ignored warning flags.
711 if (!O
.Members
&& !O
.SubGroups
)
714 unsigned Distance
= O
.getName().edit_distance(Group
, true, BestDistance
);
715 if (Distance
> BestDistance
)
718 // Don't suggest groups that are not of this kind.
719 llvm::SmallVector
<diag::kind
, 8> Diags
;
720 if (::getDiagnosticsInGroup(Flavor
, &O
, Diags
) || Diags
.empty())
723 if (Distance
== BestDistance
) {
724 // Two matches with the same distance, don't prefer one over the other.
726 } else if (Distance
< BestDistance
) {
727 // This is a better match.
729 BestDistance
= Distance
;
736 /// ProcessDiag - This is the method used to report a diagnostic that is
737 /// finally fully formed.
738 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine
&Diag
) const {
739 Diagnostic
Info(&Diag
);
741 assert(Diag
.getClient() && "DiagnosticClient not set!");
743 // Figure out the diagnostic level of this message.
744 unsigned DiagID
= Info
.getID();
745 DiagnosticIDs::Level DiagLevel
746 = getDiagnosticLevel(DiagID
, Info
.getLocation(), Diag
);
748 // Update counts for DiagnosticErrorTrap even if a fatal error occurred
749 // or diagnostics are suppressed.
750 if (DiagLevel
>= DiagnosticIDs::Error
) {
751 ++Diag
.TrapNumErrorsOccurred
;
752 if (isUnrecoverable(DiagID
))
753 ++Diag
.TrapNumUnrecoverableErrorsOccurred
;
756 if (Diag
.SuppressAllDiagnostics
)
759 if (DiagLevel
!= DiagnosticIDs::Note
) {
760 // Record that a fatal error occurred only when we see a second
761 // non-note diagnostic. This allows notes to be attached to the
762 // fatal error, but suppresses any diagnostics that follow those
764 if (Diag
.LastDiagLevel
== DiagnosticIDs::Fatal
)
765 Diag
.FatalErrorOccurred
= true;
767 Diag
.LastDiagLevel
= DiagLevel
;
770 // If a fatal error has already been emitted, silence all subsequent
772 if (Diag
.FatalErrorOccurred
) {
773 if (DiagLevel
>= DiagnosticIDs::Error
&&
774 Diag
.Client
->IncludeInDiagnosticCounts()) {
781 // If the client doesn't care about this message, don't issue it. If this is
782 // a note and the last real diagnostic was ignored, ignore it too.
783 if (DiagLevel
== DiagnosticIDs::Ignored
||
784 (DiagLevel
== DiagnosticIDs::Note
&&
785 Diag
.LastDiagLevel
== DiagnosticIDs::Ignored
))
788 if (DiagLevel
>= DiagnosticIDs::Error
) {
789 if (isUnrecoverable(DiagID
))
790 Diag
.UnrecoverableErrorOccurred
= true;
792 // Warnings which have been upgraded to errors do not prevent compilation.
793 if (isDefaultMappingAsError(DiagID
))
794 Diag
.UncompilableErrorOccurred
= true;
796 Diag
.ErrorOccurred
= true;
797 if (Diag
.Client
->IncludeInDiagnosticCounts()) {
801 // If we've emitted a lot of errors, emit a fatal error instead of it to
802 // stop a flood of bogus errors.
803 if (Diag
.ErrorLimit
&& Diag
.NumErrors
> Diag
.ErrorLimit
&&
804 DiagLevel
== DiagnosticIDs::Error
) {
805 Diag
.SetDelayedDiagnostic(diag::fatal_too_many_errors
);
810 // Make sure we set FatalErrorOccurred to ensure that the notes from the
811 // diagnostic that caused `fatal_too_many_errors` won't be emitted.
812 if (Diag
.CurDiagID
== diag::fatal_too_many_errors
)
813 Diag
.FatalErrorOccurred
= true;
814 // Finally, report it.
815 EmitDiag(Diag
, DiagLevel
);
819 void DiagnosticIDs::EmitDiag(DiagnosticsEngine
&Diag
, Level DiagLevel
) const {
820 Diagnostic
Info(&Diag
);
821 assert(DiagLevel
!= DiagnosticIDs::Ignored
&& "Cannot emit ignored diagnostics!");
823 Diag
.Client
->HandleDiagnostic((DiagnosticsEngine::Level
)DiagLevel
, Info
);
824 if (Diag
.Client
->IncludeInDiagnosticCounts()) {
825 if (DiagLevel
== DiagnosticIDs::Warning
)
829 Diag
.CurDiagID
= ~0U;
832 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID
) const {
833 if (DiagID
>= diag::DIAG_UPPER_LIMIT
) {
834 assert(CustomDiagInfo
&& "Invalid CustomDiagInfo");
835 // Custom diagnostics.
836 return CustomDiagInfo
->getLevel(DiagID
) >= DiagnosticIDs::Error
;
839 // Only errors may be unrecoverable.
840 if (getBuiltinDiagClass(DiagID
) < CLASS_ERROR
)
843 if (DiagID
== diag::err_unavailable
||
844 DiagID
== diag::err_unavailable_message
)
847 // Currently we consider all ARC errors as recoverable.
848 if (isARCDiagnostic(DiagID
))
854 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID
) {
855 unsigned cat
= getCategoryNumberForDiag(DiagID
);
856 return DiagnosticIDs::getCategoryNameFromID(cat
).startswith("ARC ");