17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/Support/ErrorHandling.h"
30struct StaticDiagInfoRec;
35struct 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"
52#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
57const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions = {
58#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
59 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
62#include "clang/Basic/DiagnosticCommonKinds.inc"
63#include "clang/Basic/DiagnosticDriverKinds.inc"
64#include "clang/Basic/DiagnosticFrontendKinds.inc"
65#include "clang/Basic/DiagnosticSerializationKinds.inc"
66#include "clang/Basic/DiagnosticLexKinds.inc"
67#include "clang/Basic/DiagnosticParseKinds.inc"
68#include "clang/Basic/DiagnosticASTKinds.inc"
69#include "clang/Basic/DiagnosticCommentKinds.inc"
70#include "clang/Basic/DiagnosticCrossTUKinds.inc"
71#include "clang/Basic/DiagnosticSemaKinds.inc"
72#include "clang/Basic/DiagnosticAnalysisKinds.inc"
73#include "clang/Basic/DiagnosticRefactoringKinds.inc"
74#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
79extern const StaticDiagInfoRec StaticDiagInfo[];
83const uint32_t StaticDiagInfoDescriptionOffsets[] = {
84#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
85 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
86 offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc),
88#include "clang/Basic/DiagnosticCommonKinds.inc"
89#include "clang/Basic/DiagnosticDriverKinds.inc"
90#include "clang/Basic/DiagnosticFrontendKinds.inc"
91#include "clang/Basic/DiagnosticSerializationKinds.inc"
92#include "clang/Basic/DiagnosticLexKinds.inc"
93#include "clang/Basic/DiagnosticParseKinds.inc"
94#include "clang/Basic/DiagnosticASTKinds.inc"
95#include "clang/Basic/DiagnosticCommentKinds.inc"
96#include "clang/Basic/DiagnosticCrossTUKinds.inc"
97#include "clang/Basic/DiagnosticSemaKinds.inc"
98#include "clang/Basic/DiagnosticAnalysisKinds.inc"
99#include "clang/Basic/DiagnosticRefactoringKinds.inc"
100#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
106enum DiagnosticClass {
109 CLASS_WARNING = 0x03,
110 CLASS_EXTENSION = 0x04,
114struct StaticDiagInfoRec {
117 uint8_t DefaultSeverity : 3;
118 LLVM_PREFERRED_TYPE(DiagnosticClass)
123 LLVM_PREFERRED_TYPE(
bool)
124 uint8_t WarnNoWerror : 1;
125 LLVM_PREFERRED_TYPE(
bool)
126 uint8_t WarnShowInSystemHeader : 1;
127 LLVM_PREFERRED_TYPE(
bool)
128 uint8_t WarnShowInSystemMacro : 1;
130 uint16_t OptionGroupIndex : 15;
131 LLVM_PREFERRED_TYPE(
bool)
132 uint16_t Deferrable : 1;
134 uint16_t DescriptionLen;
136 unsigned getOptionGroupIndex()
const {
137 return OptionGroupIndex;
140 StringRef getDescription()
const {
141 size_t MyIndex =
this - &StaticDiagInfo[0];
142 uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex];
143 const char* Table =
reinterpret_cast<const char*
>(&StaticDiagInfoDescriptions);
144 return StringRef(&Table[StringOffset], DescriptionLen);
148 return Class == CLASS_REMARK ? diag::Flavor::Remark
149 : diag::Flavor::WarningOrError;
152 bool operator<(
const StaticDiagInfoRec &RHS)
const {
153 return DiagID < RHS.DiagID;
157#define STRINGIFY_NAME(NAME) #NAME
158#define VALIDATE_DIAG_SIZE(NAME) \
160 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
161 static_cast<unsigned>(diag::DIAG_START_##NAME) + \
162 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
164 DIAG_SIZE_##NAME) " is insufficient to contain all " \
165 "diagnostics, it may need to be made larger in " \
180#undef VALIDATE_DIAG_SIZE
183const StaticDiagInfoRec StaticDiagInfo[] = {
185#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
186 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
191 DiagnosticIDs::SFINAE, \
198 STR_SIZE(DESC, uint16_t)},
199#include "clang/Basic/DiagnosticCommonKinds.inc"
200#include "clang/Basic/DiagnosticDriverKinds.inc"
201#include "clang/Basic/DiagnosticFrontendKinds.inc"
202#include "clang/Basic/DiagnosticSerializationKinds.inc"
203#include "clang/Basic/DiagnosticLexKinds.inc"
204#include "clang/Basic/DiagnosticParseKinds.inc"
205#include "clang/Basic/DiagnosticASTKinds.inc"
206#include "clang/Basic/DiagnosticCommentKinds.inc"
207#include "clang/Basic/DiagnosticCrossTUKinds.inc"
208#include "clang/Basic/DiagnosticSemaKinds.inc"
209#include "clang/Basic/DiagnosticAnalysisKinds.inc"
210#include "clang/Basic/DiagnosticRefactoringKinds.inc"
211#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
224 using namespace diag;
225 if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
237 unsigned ID = DiagID - DIAG_START_COMMON - 1;
238#define CATEGORY(NAME, PREV) \
239 if (DiagID > DIAG_START_##NAME) { \
240 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
241 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
263 const StaticDiagInfoRec *
Found = &StaticDiagInfo[ID + Offset];
267 if (
Found->DiagID != DiagID)
276 if (
const StaticDiagInfoRec *StaticInfo =
GetDiagInfo(DiagID)) {
279 if (StaticInfo->WarnNoWerror) {
281 "Unexpected mapping with no-Werror bit!");
292 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
293 return Info->Category;
299 struct StaticDiagCategoryRec {
304 return StringRef(NameStr,
NameLen);
310#define GET_CATEGORY_TABLE
311#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
312#include "clang/Basic/DiagnosticGroups.inc"
313#undef GET_CATEGORY_TABLE
335 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
341 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
342 return Info->Deferrable;
349 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
361 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
362 std::vector<DiagDesc> DiagInfo;
363 std::map<DiagDesc, unsigned> DiagIDs;
370 "Invalid diagnostic ID");
377 "Invalid diagnostic ID");
383 DiagDesc
D(L, std::string(Message));
385 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(
D);
386 if (I != DiagIDs.end() && I->first ==
D)
391 DiagIDs.insert(std::make_pair(
D, ID));
392 DiagInfo.push_back(
D);
418 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *
this);
444 bool &EnabledByDefault) {
464 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
465 return Info->getDescription();
466 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
467 return CustomDiagInfo->getDescription(DiagID);
483 llvm_unreachable(
"unexpected severity");
494 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
495 return CustomDiagInfo->getLevel(DiagID);
519 DiagnosticsEngine::DiagState *State =
Diag.GetDiagStateForLoc(
Loc);
534 bool EnabledByDefault =
false;
536 if (
Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
541 if (IsExtensionDiag && !Mapping.
isUser())
553 if (State->IgnoreAllWarnings) {
575 Diag.CurDiagID != diag::fatal_too_many_errors &&
Diag.FatalsAsError)
579 bool ShowInSystemHeader =
585 if (State->SuppressSystemWarnings && !ShowInSystemHeader &&
Loc.
isValid() &&
586 Diag.getSourceManager().isInSystemHeader(
587 Diag.getSourceManager().getExpansionLoc(
Loc)))
591 bool ShowInSystemMacro =
593 if (State->SuppressSystemWarnings && !ShowInSystemMacro &&
Loc.
isValid() &&
594 Diag.getSourceManager().isInSystemMacro(
Loc))
600#define GET_DIAG_ARRAYS
601#include "clang/Basic/DiagnosticGroups.inc"
602#undef GET_DIAG_ARRAYS
605 struct WarningOption {
609 StringRef Documentation;
613 return StringRef(DiagGroupNames + NameOffset + 1,
614 DiagGroupNames[NameOffset]);
621#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
622 {FlagNameOffset, Members, SubGroups, Docs},
623#include "clang/Basic/DiagnosticGroups.inc"
629 return OptionTable[
static_cast<int>(Group)].Documentation;
636std::optional<diag::Group>
638 const auto *
Found = llvm::partition_point(
639 OptionTable, [=](
const WarningOption &O) {
return O.getName() < Name; });
646 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
647 return static_cast<diag::Group>(Info->getOptionGroupIndex());
661 std::vector<std::string> Res{
"-W",
"-Wno-"};
662 for (
size_t I = 1; DiagGroupNames[I] !=
'\0';) {
663 std::string
Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
664 I += DiagGroupNames[I] + 1;
665 Res.push_back(
"-W" +
Diag);
666 Res.push_back(
"-Wno-" +
Diag);
675 const WarningOption *Group,
679 if (!Group->Members && !Group->SubGroups)
685 const int16_t *
Member = DiagArrays + Group->Members;
694 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
695 for (; *SubGroups != (int16_t)-1; ++SubGroups)
706 return ::getDiagnosticsInGroup(
707 Flavor, &
OptionTable[
static_cast<unsigned>(*G)], Diags);
712 std::vector<diag::kind> &Diags) {
714 if (StaticDiagInfo[i].getFlavor() == Flavor)
715 Diags.push_back(StaticDiagInfo[i].DiagID);
721 unsigned BestDistance = Group.size() + 1;
724 if (!O.Members && !O.SubGroups)
727 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
728 if (Distance > BestDistance)
736 if (Distance == BestDistance) {
739 }
else if (Distance < BestDistance) {
742 BestDistance = Distance;
754 assert(
Diag.getClient() &&
"DiagnosticClient not set!");
757 unsigned DiagID = Info.getID();
759 = getDiagnosticLevel(DiagID, Info.getLocation(),
Diag);
764 ++
Diag.TrapNumErrorsOccurred;
765 if (isUnrecoverable(DiagID))
766 ++
Diag.TrapNumUnrecoverableErrorsOccurred;
769 if (
Diag.SuppressAllDiagnostics)
778 Diag.FatalErrorOccurred =
true;
780 Diag.LastDiagLevel = DiagLevel;
785 if (
Diag.FatalErrorOccurred) {
787 Diag.Client->IncludeInDiagnosticCounts()) {
802 if (isUnrecoverable(DiagID))
803 Diag.UnrecoverableErrorOccurred =
true;
807 Diag.UncompilableErrorOccurred =
true;
809 Diag.ErrorOccurred =
true;
810 if (
Diag.Client->IncludeInDiagnosticCounts()) {
816 if (
Diag.ErrorLimit &&
Diag.NumErrors >
Diag.ErrorLimit &&
818 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
825 if (
Diag.CurDiagID == diag::fatal_too_many_errors)
826 Diag.FatalErrorOccurred =
true;
828 EmitDiag(
Diag, DiagLevel);
837 if (
Diag.Client->IncludeInDiagnosticCounts()) {
842 Diag.CurDiagID = ~0
U;
845bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
847 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
856 if (DiagID == diag::err_unavailable ||
857 DiagID == diag::err_unavailable_message)
Includes all the separate Diagnostic headers & some related helpers.
static const StaticDiagInfoRec * GetDiagInfo(unsigned DiagID)
GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, or null if the ID is inval...
static DiagnosticIDs::Level toLevel(diag::Severity SV)
#define VALIDATE_DIAG_SIZE(NAME)
#define CATEGORY(NAME, PREV)
static const unsigned StaticDiagInfoSize
static unsigned getBuiltinDiagClass(unsigned DiagID)
getBuiltinDiagClass - Return the class field of the diagnostic.
static const WarningOption OptionTable[]
static bool getDiagnosticsInGroup(diag::Flavor Flavor, const WarningOption *Group, SmallVectorImpl< diag::kind > &Diags)
Return true if any diagnostics were found in this group, even if they were filtered out due to having...
static const StaticDiagCategoryRec CategoryNameTable[]
Defines the Diagnostic IDs-related interfaces.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
static std::string getName(const CallEvent &Call)
Defines the SourceManager interface.
Used for handling and querying diagnostic IDs.
static bool isBuiltinExtensionDiag(unsigned DiagID)
Determine whether the given built-in diagnostic ID is for an extension of some sort.
static StringRef getCategoryNameFromID(unsigned CategoryID)
Given a category ID, return the name of the category.
static unsigned getNumberOfCategories()
Return the number of diagnostic categories.
static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group)
Get the diagnostic option with the closest edit distance to the given group name.
bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, SmallVectorImpl< diag::kind > &Diags) const
Get the set of all diagnostic IDs in the group with the given name.
static std::vector< std::string > getDiagnosticFlags()
Get the string of all diagnostic flags.
static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID)
Determines whether the given built-in diagnostic ID is for an error that is suppressed if it occurs d...
static bool isDefaultMappingAsError(unsigned DiagID)
Return true if the specified diagnostic is mapped to errors by default.
static bool isBuiltinNote(unsigned DiagID)
Determine whether the given built-in diagnostic ID is a Note.
static bool isBuiltinWarningOrExtension(unsigned DiagID)
Return true if the unmapped diagnostic levelof the specified diagnostic ID is a Warning or Extension.
static bool isCodegenABICheckDiagnostic(unsigned DiagID)
Return true if a given diagnostic is a codegen-time ABI check.
StringRef getDescription(unsigned DiagID) const
Given a diagnostic ID, return a description of the issue.
SFINAEResponse
Enumeration describing how the emission of a diagnostic should be treated when it occurs during C++ t...
@ SFINAE_Report
The diagnostic should be reported.
static StringRef getWarningOptionForDiag(unsigned DiagID)
Return the lowest-level warning option that enables the specified diagnostic.
static StringRef getWarningOptionDocumentation(diag::Group GroupID)
Given a diagnostic group ID, return its documentation.
static std::optional< diag::Group > getGroupForWarningOption(StringRef)
Given a group ID, returns the flag that toggles the group.
static unsigned getCategoryNumberForDiag(unsigned DiagID)
Return the category number that a specified DiagID belongs to, or 0 if no category.
static std::optional< diag::Group > getGroupForDiag(unsigned DiagID)
Return the lowest-level group that contains the specified diagnostic.
static StringRef getWarningOptionForGroup(diag::Group)
Given a group ID, returns the flag that toggles the group.
static bool isARCDiagnostic(unsigned DiagID)
Return true if a given diagnostic falls into an ARC diagnostic category.
Level
The level of the diagnostic, after it has been through mapping.
static void getAllDiagnostics(diag::Flavor Flavor, std::vector< diag::kind > &Diags)
Get the set of all diagnostic IDs.
static DiagnosticMapping getDefaultMapping(unsigned DiagID)
Get the default mapping for this diagnostic.
unsigned getCustomDiagID(Level L, StringRef FormatString)
Return an ID for a diagnostic with the specified format string and level.
static bool isDeferrable(unsigned DiagID)
Whether the diagnostic message can be deferred.
bool hasNoErrorAsFatal() const
void setNoWarningAsError(bool Value)
void setSeverity(diag::Severity Value)
diag::Severity getSeverity() const
static DiagnosticMapping Make(diag::Severity Severity, bool IsUser, bool IsPragma)
bool hasNoWarningAsError() const
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Concrete class used by the front-end to report problems and issues.
Level
The level of the diagnostic, after it has been through mapping.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
StringRef getDescription(unsigned DiagID) const
getDescription - Return the description of the specified custom diagnostic.
unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message, DiagnosticIDs &Diags)
DiagnosticIDs::Level getLevel(unsigned DiagID) const
getLevel - Return the level of the specified custom diagnostic.
Severity
Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs to either Ignore (nothing),...
@ Warning
Present this diagnostic as a warning.
@ Fatal
Present this diagnostic as a fatal error.
@ Error
Present this diagnostic as an error.
@ Remark
Present this diagnostic as a remark.
@ Ignored
Do not present this diagnostic, ignore it.
Flavor
Flavors of diagnostics we can emit.
@ Remark
A diagnostic that indicates normal progress through compilation.
The JSON file list parser is used to communicate input to InstallAPI.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ Result
The result type of a method or function.
@ Class
The "class" keyword introduces the elaborated-type-specifier.