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, \
68#if defined(_AIX) && (!defined(__GNUC__) || defined(__clang__))
71#define BEGIN_TWO_BYTE_PACK() _Pragma("pack(2)")
72#define END_TWO_BYTE_PACK() _Pragma("pack(pop)")
74#define BEGIN_TWO_BYTE_PACK()
75#define END_TWO_BYTE_PACK()
79struct StaticDiagInfoRec {
83 LLVM_PREFERRED_TYPE(DiagnosticClass)
89 LLVM_PREFERRED_TYPE(
bool)
91 LLVM_PREFERRED_TYPE(
bool)
93 LLVM_PREFERRED_TYPE(
bool)
98 LLVM_PREFERRED_TYPE(
bool)
105 unsigned getOptionGroupIndex()
const {
106 return OptionGroupIndex;
109 StringRef getDescription()
const {
111 DescriptionOffsetLow | (
uint32_t(DescriptionOffsetHigh) << 16);
112 return StringRef(StaticDiagInfoDescriptionsStorage + Offset,
116 StringRef getStableID()
const {
117 size_t MyIndex =
this - &StaticDiagInfo[0];
118 uint32_t StringOffset = StaticDiagInfoStableIDOffsets[MyIndex];
119 return DiagStableIDs[StringOffset];
124 size_t MyIndex =
this - &StaticDiagInfo[0];
125 uint32_t StartOffset = StaticDiagInfoLegacyStableIDStartOffsets[MyIndex];
126 for (
uint32_t Offset = StartOffset; DiagLegacyStableIDs[Offset] != 0;
128 Result.push_back(DiagStableIDs[DiagLegacyStableIDs[Offset]]);
139 bool operator<(
const StaticDiagInfoRec &RHS)
const {
140 return DiagID < RHS.DiagID;
145#undef BEGIN_TWO_BYTE_PACK
146#undef END_TWO_BYTE_PACK
148static_assert(
sizeof(StaticDiagInfoRec) == 10);
150 "too many diagnostic groups for StaticDiagInfoRec");
152#define STRINGIFY_NAME(NAME) #NAME
153#define VALIDATE_DIAG_SIZE(NAME) \
155 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
156 static_cast<unsigned>(diag::DIAG_START_##NAME) + \
157 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
159 DIAG_SIZE_##NAME) " is insufficient to contain all " \
160 "diagnostics, it may need to be made larger in " \
177#undef VALIDATE_DIAG_SIZE
180const StaticDiagInfoRec StaticDiagInfo[] = {
182#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
183 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, STABLE_ID, \
189 DiagnosticIDs::SFINAE, \
196 uint16_t(DIAG_DESC_OFFSET_##ENUM), \
197 uint16_t(DIAG_DESC_OFFSET_##ENUM >> 16), \
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/DiagnosticCodeGenKinds.inc"
203#include "clang/Basic/DiagnosticSerializationKinds.inc"
204#include "clang/Basic/DiagnosticLexKinds.inc"
205#include "clang/Basic/DiagnosticParseKinds.inc"
206#include "clang/Basic/DiagnosticASTKinds.inc"
207#include "clang/Basic/DiagnosticCommentKinds.inc"
208#include "clang/Basic/DiagnosticCrossTUKinds.inc"
209#include "clang/Basic/DiagnosticSemaKinds.inc"
210#include "clang/Basic/DiagnosticAnalysisKinds.inc"
211#include "clang/Basic/DiagnosticRefactoringKinds.inc"
212#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
213#include "clang/Basic/DiagnosticTrapKinds.inc"
226 using namespace diag;
227 if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
239 unsigned ID = DiagID - DIAG_START_COMMON - 1;
240#define CATEGORY(NAME, PREV) \
241 if (DiagID > DIAG_START_##NAME) { \
242 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
243 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
267 const StaticDiagInfoRec *
Found = &StaticDiagInfo[ID + Offset];
271 if (
Found->DiagID != DiagID)
284 std::vector<CustomDiagDesc> DiagInfo;
285 std::map<CustomDiagDesc, unsigned> DiagIDs;
286 std::map<diag::Group, std::vector<unsigned>> GroupToDiags;
293 "Invalid diagnostic ID");
299 std::map<CustomDiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
300 if (I != DiagIDs.end() && I->first == D)
305 DiagIDs.insert(std::make_pair(D, ID));
306 DiagInfo.push_back(D);
308 GroupToDiags[*
Group].emplace_back(ID);
313 if (
auto Diags = GroupToDiags.find(G); Diags != GroupToDiags.end())
314 return Diags->second;
328 CustomDiagInfo->getDescription(DiagID).GetDefaultSeverity());
329 }
else if (
const StaticDiagInfoRec *StaticInfo =
GetDiagInfo(DiagID)) {
332 if (StaticInfo->WarnNoWerror) {
334 "Unexpected mapping with no-Werror bit!");
345 const auto &
Diag = CustomDiagInfo->getDescription(DiagID);
346 if (
auto Group =
Diag.GetGroup()) {
361 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
362 return Info->Category;
368 struct StaticDiagCategoryRec {
372 StringRef getName()
const {
373 return StringRef(NameStr, NameLen);
379#define GET_CATEGORY_TABLE
380#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
381#include "clang/Basic/DiagnosticGroups.inc"
382#undef GET_CATEGORY_TABLE
404 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
410 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
411 return Info->Deferrable;
432 return CustomDiagInfo->getOrCreateDiagID(
Diag);
438 : CustomDiagInfo->getDescription(DiagID).GetClass() !=
CLASS_ERROR;
453 bool &EnabledByDefault)
const {
469 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
470 return Info->getDescription();
471 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
472 return CustomDiagInfo->getDescription(DiagID).GetDescription();
477 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
478 return Info->getStableID().str();
479 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
483 return std::to_string(DiagID);
490 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
491 return Info->getLegacyStableIDs();
492 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
512 llvm_unreachable(
"unexpected severity");
519DiagnosticIDs::getDiagnosticLevel(
unsigned DiagID,
SourceLocation Loc,
521 unsigned DiagClass = getDiagClass(DiagID);
523 return toLevel(getDiagnosticSeverity(DiagID, Loc,
Diag));
533DiagnosticIDs::getDiagnosticSeverity(
unsigned DiagID,
SourceLocation Loc,
535 return getDiagnosticListHighestSeverity({DiagID}, Loc,
Diag);
541 DiagnosticsEngine::DiagState *State =
Diag.GetDiagStateForLoc(Loc);
552 DiagnosticMapping Mapping = State->getOrAddMapping((
diag::kind)DiagID);
567 bool EnabledByDefault =
false;
569 if (
Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
575 if (IsExtensionDiag &&
594 if (State->IgnoreAllWarnings) {
596 CustomDiagInfo->getDescription(DiagID).GetGroup()) &&
619 DiagID != diag::fatal_too_many_errors &&
Diag.FatalsAsError)
624 if (!
Diag.hasSourceManager())
632 if (State->SuppressSystemWarnings && !
Diag.getForceSystemWarnings() &&
639 if (!Mapping.
isPragma() &&
Diag.isSuppressedViaMapping(DiagID, Loc))
647 CompositeResult = std::max(CompositeResult, checkSingleDiag(DiagID));
659 return CompositeResult;
668 const auto &SM =
Diag.getSourceManager();
671 if (SM.isInSystemHeader(SM.getExpansionLoc(Loc))) {
672 bool ShowInSystemHeader =
true;
675 CustomDiagInfo->getDescription(DiagID).ShouldShowInSystemHeader();
676 else if (
const StaticDiagInfoRec *Rec =
GetDiagInfo(DiagID))
677 ShowInSystemHeader = Rec->WarnShowInSystemHeader;
679 if (!ShowInSystemHeader)
684 bool ShowInSystemMacro =
true;
689 if (
const StaticDiagInfoRec *Rec =
GetDiagInfo(DiagID))
690 ShowInSystemMacro = Rec->WarnShowInSystemMacro;
692 if (!ShowInSystemMacro && SM.isInSystemMacro(Loc))
700 return Class(CustomDiagInfo->getDescription(DiagID).GetClass());
702 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
703 return Class(Info->Class);
707#define GET_DIAG_ARRAYS
708#include "clang/Basic/DiagnosticGroups.inc"
709#undef GET_DIAG_ARRAYS
712 struct WarningOption {
716 StringRef Documentation;
718 StringRef getName()
const {
return DiagGroupNames[NameOffset]; }
724#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
725 {FlagNameOffset, Members, SubGroups, Docs},
726#include "clang/Basic/DiagnosticGroups.inc"
732 return OptionTable[
static_cast<int>(Group)].Documentation;
736 return OptionTable[
static_cast<int>(Group)].getName();
739std::optional<diag::Group>
741 const auto *
Found = llvm::partition_point(
742 OptionTable, [=](
const WarningOption &O) {
return O.getName() < Name; });
748std::optional<diag::Group>
751 assert(CustomDiagInfo);
752 return CustomDiagInfo->getDescription(DiagID).GetGroup();
754 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
755 return static_cast<diag::Group>(Info->getOptionGroupIndex());
769 std::vector<std::string> Res{
"-W",
"-Wno-"};
770 for (StringRef Name : DiagGroupNames) {
774 Res.push_back((Twine(
"-W") + Name).str());
775 Res.push_back((Twine(
"-Wno-") + Name).str());
784 const WarningOption *Group,
789 if (!Group->Members && !Group->SubGroups)
804 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
805 for (; *SubGroups != (
int16_t)-1; ++SubGroups) {
809 std::back_inserter(Diags));
811 Diags, CustomDiagInfo);
822 llvm::copy(CustomDiagInfo->getDiagsInGroup(*G),
823 std::back_inserter(Diags));
824 return ::getDiagnosticsInGroup(Flavor,
826 Diags, CustomDiagInfo.get());
833 for (
const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
834 *SubGroups != -1; ++SubGroups) {
835 func(
static_cast<size_t>(*SubGroups));
842 const WarningOption *WarningOpt = &
OptionTable[
static_cast<size_t>(Group)];
843 func(
static_cast<size_t>(Group));
850 GroupInfos[SubGroup].Severity =
static_cast<unsigned>(Sev);
858 GroupInfos[
static_cast<size_t>(*G)].HasNoWarningAsError = Val;
864 std::vector<diag::kind> &Diags) {
866 if (StaticDiagInfo[i].getFlavor() == Flavor)
867 Diags.push_back(StaticDiagInfo[i].DiagID);
873 unsigned BestDistance = Group.size() + 1;
876 if (!O.Members && !O.SubGroups)
879 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
880 if (Distance > BestDistance)
888 if (Distance == BestDistance) {
891 }
else if (Distance < BestDistance) {
894 BestDistance = Distance;
902 unsigned CompatDiagId) {
920#define DIAG_COMPAT_IDS_BEGIN()
921#define DIAG_COMPAT_IDS_END()
922#define DIAG_COMPAT_ID(Value, Name, Std, Diag, DiagPre) \
923 {Std >= 98 ? 1900 + Std : 2000 + Std, diag::Diag, diag::DiagPre},
924 static constexpr CompatDiag Diags[]{
925#include "clang/Basic/DiagnosticAllCompatIDs.inc"
928#undef DIAG_COMPAT_IDS_BEGIN
929#undef DIAG_COMPAT_IDS_END
931 assert(CompatDiagId < std::size(Diags) &&
"Invalid compat diag id");
933 unsigned StdVer = [&] {
934 if (!LangOpts.CPlusPlus) {
948 if (LangOpts.CPlusPlus29)
950 if (LangOpts.CPlusPlus26)
952 if (LangOpts.CPlusPlus23)
954 if (LangOpts.CPlusPlus20)
956 if (LangOpts.CPlusPlus17)
958 if (LangOpts.CPlusPlus14)
960 if (LangOpts.CPlusPlus11)
965 const CompatDiag &D = Diags[CompatDiagId];
966 return StdVer >= D.StdVer ? D.DiagId : D.PreDiagId;
969bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
974 if (DiagID == diag::err_unavailable ||
975 DiagID == diag::err_unavailable_message)
988 if (
isARCDiagnostic(DiagID) && DiagID != diag::err_arc_may_not_respond &&
989 DiagID != diag::err_arc_atomic_ownership &&
990 DiagID != diag::err_arc_bridge_cast_incompatible)
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...
#define END_TWO_BYTE_PACK()
static DiagnosticIDs::Level toLevel(diag::Severity SV)
static void forEachSubGroupImpl(const WarningOption *Group, Func func)
#define BEGIN_TWO_BYTE_PACK()
#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.
Result
Implement __builtin_bit_cast and related operations.
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.
@ WarningOrError
A diagnostic that indicates a problem or potential problem.
@ 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.
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 __builtin_riscv_mqwacc_i64 __packed_splat4 uint16_t
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 __builtin_riscv_mqwacc_i64 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 int16_t
unsigned HasNoWarningAsError