18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/ADT/StringTable.h"
21#include "llvm/Support/Compiler.h"
22#include "llvm/Support/ErrorHandling.h"
33struct StaticDiagInfoRec;
35#define GET_DIAG_STABLE_ID_ARRAYS
36#include "clang/Basic/DiagnosticStableIDs.inc"
37#undef GET_DIAG_STABLE_ID_ARRAYS
39extern const StaticDiagInfoRec StaticDiagInfo[];
41const uint32_t StaticDiagInfoStableIDOffsets[] = {
42#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
43 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, STABLE_ID, \
50const uint32_t StaticDiagInfoLegacyStableIDStartOffsets[] = {
51#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
52 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, STABLE_ID, \
68struct StaticDiagInfoRec {
72 LLVM_PREFERRED_TYPE(DiagnosticClass)
78 LLVM_PREFERRED_TYPE(
bool)
80 LLVM_PREFERRED_TYPE(
bool)
82 LLVM_PREFERRED_TYPE(
bool)
87 LLVM_PREFERRED_TYPE(
bool)
94 unsigned getOptionGroupIndex()
const {
95 return OptionGroupIndex;
98 StringRef getDescription()
const {
100 DescriptionOffsetLow | (
uint32_t(DescriptionOffsetHigh) << 16);
101 return StringRef(StaticDiagInfoDescriptionsStorage + Offset,
105 StringRef getStableID()
const {
106 size_t MyIndex =
this - &StaticDiagInfo[0];
107 uint32_t StringOffset = StaticDiagInfoStableIDOffsets[MyIndex];
108 return DiagStableIDs[StringOffset];
111 llvm::SmallVector<StringRef, 4> getLegacyStableIDs()
const {
112 llvm::SmallVector<StringRef, 4>
Result;
113 size_t MyIndex =
this - &StaticDiagInfo[0];
114 uint32_t StartOffset = StaticDiagInfoLegacyStableIDStartOffsets[MyIndex];
115 for (
uint32_t Offset = StartOffset; DiagLegacyStableIDs[Offset] != 0;
117 Result.push_back(DiagStableIDs[DiagLegacyStableIDs[Offset]]);
124 return Class == CLASS_REMARK ? diag::Flavor::Remark
125 : diag::Flavor::WarningOrError;
128 bool operator<(
const StaticDiagInfoRec &RHS)
const {
129 return DiagID < RHS.DiagID;
132static_assert(
sizeof(StaticDiagInfoRec) == 10);
134 "too many diagnostic groups for StaticDiagInfoRec");
136#define STRINGIFY_NAME(NAME) #NAME
137#define VALIDATE_DIAG_SIZE(NAME) \
139 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
140 static_cast<unsigned>(diag::DIAG_START_##NAME) + \
141 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
143 DIAG_SIZE_##NAME) " is insufficient to contain all " \
144 "diagnostics, it may need to be made larger in " \
161#undef VALIDATE_DIAG_SIZE
164const StaticDiagInfoRec StaticDiagInfo[] = {
166#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
167 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, STABLE_ID, \
173 DiagnosticIDs::SFINAE, \
180 uint16_t(DIAG_DESC_OFFSET_##ENUM), \
181 uint16_t(DIAG_DESC_OFFSET_##ENUM >> 16), \
182 STR_SIZE(DESC, uint16_t)},
183#include "clang/Basic/DiagnosticCommonKinds.inc"
184#include "clang/Basic/DiagnosticDriverKinds.inc"
185#include "clang/Basic/DiagnosticFrontendKinds.inc"
186#include "clang/Basic/DiagnosticCodeGenKinds.inc"
187#include "clang/Basic/DiagnosticSerializationKinds.inc"
188#include "clang/Basic/DiagnosticLexKinds.inc"
189#include "clang/Basic/DiagnosticParseKinds.inc"
190#include "clang/Basic/DiagnosticASTKinds.inc"
191#include "clang/Basic/DiagnosticCommentKinds.inc"
192#include "clang/Basic/DiagnosticCrossTUKinds.inc"
193#include "clang/Basic/DiagnosticSemaKinds.inc"
194#include "clang/Basic/DiagnosticAnalysisKinds.inc"
195#include "clang/Basic/DiagnosticRefactoringKinds.inc"
196#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
197#include "clang/Basic/DiagnosticTrapKinds.inc"
210 using namespace diag;
211 if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
223 unsigned ID = DiagID - DIAG_START_COMMON - 1;
224#define CATEGORY(NAME, PREV) \
225 if (DiagID > DIAG_START_##NAME) { \
226 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
227 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
251 const StaticDiagInfoRec *
Found = &StaticDiagInfo[ID + Offset];
255 if (
Found->DiagID != DiagID)
268 std::vector<CustomDiagDesc> DiagInfo;
269 std::map<CustomDiagDesc, unsigned> DiagIDs;
270 std::map<diag::Group, std::vector<unsigned>> GroupToDiags;
277 "Invalid diagnostic ID");
283 std::map<CustomDiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
284 if (I != DiagIDs.end() && I->first == D)
289 DiagIDs.insert(std::make_pair(D, ID));
290 DiagInfo.push_back(D);
292 GroupToDiags[*
Group].emplace_back(ID);
297 if (
auto Diags = GroupToDiags.find(G); Diags != GroupToDiags.end())
298 return Diags->second;
312 CustomDiagInfo->getDescription(DiagID).GetDefaultSeverity());
313 }
else if (
const StaticDiagInfoRec *StaticInfo =
GetDiagInfo(DiagID)) {
316 if (StaticInfo->WarnNoWerror) {
318 "Unexpected mapping with no-Werror bit!");
329 const auto &
Diag = CustomDiagInfo->getDescription(DiagID);
330 if (
auto Group =
Diag.GetGroup()) {
345 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
346 return Info->Category;
352 struct StaticDiagCategoryRec {
356 StringRef getName()
const {
357 return StringRef(NameStr, NameLen);
363#define GET_CATEGORY_TABLE
364#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
365#include "clang/Basic/DiagnosticGroups.inc"
366#undef GET_CATEGORY_TABLE
388 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
394 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
395 return Info->Deferrable;
416 return CustomDiagInfo->getOrCreateDiagID(
Diag);
422 : CustomDiagInfo->getDescription(DiagID).GetClass() !=
CLASS_ERROR;
437 bool &EnabledByDefault)
const {
453 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
454 return Info->getDescription();
455 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
456 return CustomDiagInfo->getDescription(DiagID).GetDescription();
461 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
462 return Info->getStableID().str();
463 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
467 return std::to_string(DiagID);
474 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
475 return Info->getLegacyStableIDs();
476 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
496 llvm_unreachable(
"unexpected severity");
503DiagnosticIDs::getDiagnosticLevel(
unsigned DiagID,
SourceLocation Loc,
505 unsigned DiagClass = getDiagClass(DiagID);
507 return toLevel(getDiagnosticSeverity(DiagID, Loc,
Diag));
517DiagnosticIDs::getDiagnosticSeverity(
unsigned DiagID,
SourceLocation Loc,
519 return getDiagnosticListHighestSeverity({DiagID}, Loc,
Diag);
525 DiagnosticsEngine::DiagState *State =
Diag.GetDiagStateForLoc(Loc);
536 DiagnosticMapping Mapping = State->getOrAddMapping((
diag::kind)DiagID);
551 bool EnabledByDefault =
false;
553 if (
Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
559 if (IsExtensionDiag &&
578 if (State->IgnoreAllWarnings) {
580 CustomDiagInfo->getDescription(DiagID).GetGroup()) &&
603 DiagID != diag::fatal_too_many_errors &&
Diag.FatalsAsError)
608 if (!
Diag.hasSourceManager())
616 if (State->SuppressSystemWarnings && !
Diag.getForceSystemWarnings() &&
623 if (!Mapping.
isPragma() &&
Diag.isSuppressedViaMapping(DiagID, Loc))
631 CompositeResult = std::max(CompositeResult, checkSingleDiag(DiagID));
643 return CompositeResult;
652 const auto &SM =
Diag.getSourceManager();
655 if (SM.isInSystemHeader(SM.getExpansionLoc(Loc))) {
656 bool ShowInSystemHeader =
true;
659 CustomDiagInfo->getDescription(DiagID).ShouldShowInSystemHeader();
660 else if (
const StaticDiagInfoRec *Rec =
GetDiagInfo(DiagID))
661 ShowInSystemHeader = Rec->WarnShowInSystemHeader;
663 if (!ShowInSystemHeader)
668 bool ShowInSystemMacro =
true;
673 if (
const StaticDiagInfoRec *Rec =
GetDiagInfo(DiagID))
674 ShowInSystemMacro = Rec->WarnShowInSystemMacro;
676 if (!ShowInSystemMacro && SM.isInSystemMacro(Loc))
684 return Class(CustomDiagInfo->getDescription(DiagID).GetClass());
686 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
687 return Class(Info->Class);
691#define GET_DIAG_ARRAYS
692#include "clang/Basic/DiagnosticGroups.inc"
693#undef GET_DIAG_ARRAYS
696 struct WarningOption {
700 StringRef Documentation;
702 StringRef getName()
const {
return DiagGroupNames[NameOffset]; }
708#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
709 {FlagNameOffset, Members, SubGroups, Docs},
710#include "clang/Basic/DiagnosticGroups.inc"
716 return OptionTable[
static_cast<int>(Group)].Documentation;
720 return OptionTable[
static_cast<int>(Group)].getName();
723std::optional<diag::Group>
725 const auto *
Found = llvm::partition_point(
726 OptionTable, [=](
const WarningOption &O) {
return O.getName() < Name; });
732std::optional<diag::Group>
735 assert(CustomDiagInfo);
736 return CustomDiagInfo->getDescription(DiagID).GetGroup();
738 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
739 return static_cast<diag::Group>(Info->getOptionGroupIndex());
753 std::vector<std::string> Res{
"-W",
"-Wno-"};
754 for (StringRef Name : DiagGroupNames) {
758 Res.push_back((Twine(
"-W") + Name).str());
759 Res.push_back((Twine(
"-Wno-") + Name).str());
768 const WarningOption *Group,
773 if (!Group->Members && !Group->SubGroups)
788 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
789 for (; *SubGroups != (
int16_t)-1; ++SubGroups) {
793 std::back_inserter(Diags));
795 Diags, CustomDiagInfo);
806 llvm::copy(CustomDiagInfo->getDiagsInGroup(*G),
807 std::back_inserter(Diags));
808 return ::getDiagnosticsInGroup(Flavor,
810 Diags, CustomDiagInfo.get());
817 for (
const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
818 *SubGroups != -1; ++SubGroups) {
819 func(
static_cast<size_t>(*SubGroups));
826 const WarningOption *WarningOpt = &
OptionTable[
static_cast<size_t>(Group)];
827 func(
static_cast<size_t>(Group));
834 GroupInfos[SubGroup].Severity =
static_cast<unsigned>(Sev);
842 GroupInfos[
static_cast<size_t>(*G)].HasNoWarningAsError = Val;
848 std::vector<diag::kind> &Diags) {
850 if (StaticDiagInfo[i].getFlavor() == Flavor)
851 Diags.push_back(StaticDiagInfo[i].DiagID);
857 unsigned BestDistance = Group.size() + 1;
860 if (!O.Members && !O.SubGroups)
863 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
864 if (Distance > BestDistance)
872 if (Distance == BestDistance) {
875 }
else if (Distance < BestDistance) {
878 BestDistance = Distance;
886 unsigned CompatDiagId) {
904#define DIAG_COMPAT_IDS_BEGIN()
905#define DIAG_COMPAT_IDS_END()
906#define DIAG_COMPAT_ID(Value, Name, Std, Diag, DiagPre) \
907 {Std >= 98 ? 1900 + Std : 2000 + Std, diag::Diag, diag::DiagPre},
908 static constexpr CompatDiag Diags[]{
909#include "clang/Basic/DiagnosticAllCompatIDs.inc"
912#undef DIAG_COMPAT_IDS_BEGIN
913#undef DIAG_COMPAT_IDS_END
915 assert(CompatDiagId < std::size(Diags) &&
"Invalid compat diag id");
917 unsigned StdVer = [&] {
918 if (!LangOpts.CPlusPlus) {
932 if (LangOpts.CPlusPlus29)
934 if (LangOpts.CPlusPlus26)
936 if (LangOpts.CPlusPlus23)
938 if (LangOpts.CPlusPlus20)
940 if (LangOpts.CPlusPlus17)
942 if (LangOpts.CPlusPlus14)
944 if (LangOpts.CPlusPlus11)
949 const CompatDiag &D = Diags[CompatDiagId];
950 return StdVer >= D.StdVer ? D.DiagId : D.PreDiagId;
953bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
958 if (DiagID == diag::err_unavailable ||
959 DiagID == diag::err_unavailable_message)
967 if (
isARCDiagnostic(DiagID) && DiagID != diag::err_arc_may_not_respond &&
968 DiagID != diag::err_arc_atomic_ownership)
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 bool getDiagnosticsInGroup(diag::Flavor Flavor, const WarningOption *Group, SmallVectorImpl< diag::kind > &Diags, diag::CustomDiagInfo *CustomDiagInfo)
Return true if any diagnostics were found in this group, even if they were filtered out due to having...
static DiagnosticIDs::Level toLevel(diag::Severity SV)
static void forEachSubGroupImpl(const WarningOption *Group, Func func)
#define VALIDATE_DIAG_SIZE(NAME)
#define CATEGORY(NAME, PREV)
static const unsigned StaticDiagInfoSize
static const WarningOption OptionTable[]
static const StaticDiagCategoryRec CategoryNameTable[]
static void forEachSubGroup(diag::Group Group, Func func)
Defines the Diagnostic IDs-related interfaces.
Defines the clang::LangOptions interface.
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.
Defines the SourceManager interface.
std::optional< diag::Group > GetGroup() const
void initCustomDiagMapping(DiagnosticMapping &, unsigned DiagID)
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.
bool isWarningOrExtension(unsigned DiagID) const
Return true if the unmapped diagnostic levelof the specified diagnostic ID is a Warning or Extension.
void setGroupSeverity(StringRef Group, diag::Severity)
bool isExtensionDiag(unsigned DiagID) const
Determine whether the given diagnostic ID is for an extension of some sort.
DiagnosticMapping getDefaultMapping(unsigned DiagID) const
Get the default mapping for this diagnostic.
std::string getStableID(unsigned DiagID) const
Given a diagnostic ID, return the stable ID of the diagnostic.
static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID)
Determines whether the given built-in diagnostic ID is for an error that is suppressed if it occurs d...
bool shouldSuppressAsSystemWarning(unsigned DiagID, SourceLocation Loc, const DiagnosticsEngine &Diag) const
Return true if either of the following two conditions hold:
bool isDefaultMappingAsError(unsigned DiagID) const
Return true if the specified diagnostic is mapped to errors by default.
void setGroupNoWarningsAsError(StringRef Group, bool)
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.
bool isNote(unsigned DiagID) const
Determine whether the given diagnostic ID is a Note.
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.
friend class DiagnosticsEngine
static bool IsCustomDiag(diag::kind Diag)
static unsigned getCompatDiagId(const LangOptions &LangOpts, unsigned CompatDiagId)
Get the appropriate diagnostic Id to use for issuing a compatibility diagnostic.
unsigned getCustomDiagID(CustomDiagDesc Diag)
Return an ID for a diagnostic with the specified format string and level.
Level
The level of the diagnostic, after it has been through mapping.
static unsigned getCategoryNumberForDiag(unsigned DiagID)
Return the category number that a specified DiagID belongs to, or 0 if no category.
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.
static void getAllDiagnostics(diag::Flavor Flavor, std::vector< diag::kind > &Diags)
Get the set of all diagnostic IDs.
std::optional< diag::Group > getGroupForDiag(unsigned DiagID) const
Return the lowest-level group that contains the specified diagnostic.
static bool isDeferrable(unsigned DiagID)
Whether the diagnostic message can be deferred.
llvm::SmallVector< StringRef, 4 > getLegacyStableIDs(unsigned DiagID) const
Given a diagnostic ID, return the previous stable IDs of the diagnostic.
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)
void setNoErrorAsFatal(bool Value)
bool hasNoWarningAsError() const
Concrete class used by the front-end to report problems and issues.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
unsigned getOrCreateDiagID(DiagnosticIDs::CustomDiagDesc D)
const CustomDiagDesc & getDescription(unsigned DiagID) const
getDescription - Return the description of the specified custom diagnostic.
ArrayRef< unsigned > getDiagsInGroup(diag::Group G) const
DiagnosticIDs::CustomDiagDesc CustomDiagDesc
Flavor
Flavors of diagnostics we can emit.
@ Remark
A diagnostic that indicates normal progress through compilation.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
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.
Top level wrappers for InstallAPI frontend operations.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ Result
The result type of a method or function.
int32_t uint32_t uint32_t __packed_splat4 int16_t
int32_t uint32_t uint32_t __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 uint16_t
unsigned HasNoWarningAsError