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"
56const 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"
77extern const StaticDiagInfoRec StaticDiagInfo[];
81const 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"
106 CLASS_WARNING = 0x03,
107 CLASS_EXTENSION = 0x04,
111struct StaticDiagInfoRec {
113 uint8_t DefaultSeverity : 3;
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);
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 " \
169#undef VALIDATE_DIAG_SIZE
172const 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"
212 using namespace diag;
213 if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
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; \
250 const StaticDiagInfoRec *Found = &StaticDiagInfo[ID + Offset];
254 if (Found->DiagID != DiagID)
263 if (
const StaticDiagInfoRec *StaticInfo =
GetDiagInfo(DiagID)) {
266 if (StaticInfo->WarnNoWerror) {
268 "Unexpected mapping with no-Werror bit!");
279 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
280 return Info->Category;
286 struct StaticDiagCategoryRec {
291 return StringRef(NameStr,
NameLen);
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
322 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
328 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
329 return Info->Deferrable;
336 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
348 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
349 std::vector<DiagDesc> DiagInfo;
350 std::map<DiagDesc, unsigned> DiagIDs;
357 "Invalid diagnostic ID");
364 "Invalid diagnostic ID");
370 DiagDesc D(L, std::string(Message));
372 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
373 if (I != DiagIDs.end() && I->first == D)
378 DiagIDs.insert(std::make_pair(D, ID));
379 DiagInfo.push_back(D);
405 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *
this);
431 bool &EnabledByDefault) {
451 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
452 return Info->getDescription();
453 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
454 return CustomDiagInfo->getDescription(DiagID);
470 llvm_unreachable(
"unexpected severity");
477DiagnosticIDs::getDiagnosticLevel(
unsigned DiagID,
SourceLocation Loc,
481 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
482 return CustomDiagInfo->getLevel(DiagID);
487 return toLevel(getDiagnosticSeverity(DiagID, Loc,
Diag));
497DiagnosticIDs::getDiagnosticSeverity(
unsigned DiagID,
SourceLocation Loc,
506 DiagnosticsEngine::DiagState *State =
Diag.GetDiagStateForLoc(Loc);
521 bool EnabledByDefault =
false;
523 if (
Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
528 if (IsExtensionDiag && !Mapping.
isUser())
540 if (State->IgnoreAllWarnings) {
562 Diag.CurDiagID != diag::fatal_too_many_errors &&
Diag.FatalsAsError)
566 bool ShowInSystemHeader =
572 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.
isValid() &&
573 Diag.getSourceManager().isInSystemHeader(
574 Diag.getSourceManager().getExpansionLoc(Loc)))
578 bool ShowInSystemMacro =
580 if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.
isValid() &&
581 Diag.getSourceManager().isInSystemMacro(Loc))
587#define GET_DIAG_ARRAYS
588#include "clang/Basic/DiagnosticGroups.inc"
589#undef GET_DIAG_ARRAYS
592 struct WarningOption {
596 StringRef Documentation;
600 return StringRef(DiagGroupNames + NameOffset + 1,
601 DiagGroupNames[NameOffset]);
608#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
609 {FlagNameOffset, Members, SubGroups, Docs},
610#include "clang/Basic/DiagnosticGroups.inc"
616 return OptionTable[
static_cast<int>(Group)].Documentation;
623std::optional<diag::Group>
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)
633 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
634 return static_cast<diag::Group>(Info->getOptionGroupIndex());
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);
662 const WarningOption *Group,
666 if (!Group->Members && !Group->SubGroups)
669 bool NotFound =
true;
672 const int16_t *
Member = DiagArrays + Group->Members;
681 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
682 for (; *SubGroups != (int16_t)-1; ++SubGroups)
693 return ::getDiagnosticsInGroup(
694 Flavor, &
OptionTable[
static_cast<unsigned>(*G)], Diags);
699 std::vector<diag::kind> &Diags) {
701 if (StaticDiagInfo[i].getFlavor() == Flavor)
702 Diags.push_back(StaticDiagInfo[i].DiagID);
708 unsigned BestDistance = Group.size() + 1;
711 if (!O.Members && !O.SubGroups)
714 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
715 if (Distance > BestDistance)
723 if (Distance == BestDistance) {
726 }
else if (Distance < BestDistance) {
729 BestDistance = Distance;
741 assert(
Diag.getClient() &&
"DiagnosticClient not set!");
744 unsigned DiagID = Info.getID();
746 = getDiagnosticLevel(DiagID, Info.getLocation(),
Diag);
751 ++
Diag.TrapNumErrorsOccurred;
752 if (isUnrecoverable(DiagID))
753 ++
Diag.TrapNumUnrecoverableErrorsOccurred;
756 if (
Diag.SuppressAllDiagnostics)
765 Diag.FatalErrorOccurred =
true;
767 Diag.LastDiagLevel = DiagLevel;
772 if (
Diag.FatalErrorOccurred) {
774 Diag.Client->IncludeInDiagnosticCounts()) {
789 if (isUnrecoverable(DiagID))
790 Diag.UnrecoverableErrorOccurred =
true;
794 Diag.UncompilableErrorOccurred =
true;
796 Diag.ErrorOccurred =
true;
797 if (
Diag.Client->IncludeInDiagnosticCounts()) {
803 if (
Diag.ErrorLimit &&
Diag.NumErrors >
Diag.ErrorLimit &&
805 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
812 if (
Diag.CurDiagID == diag::fatal_too_many_errors)
813 Diag.FatalErrorOccurred =
true;
815 EmitDiag(
Diag, DiagLevel);
824 if (
Diag.Client->IncludeInDiagnosticCounts()) {
829 Diag.CurDiagID = ~0
U;
832bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
834 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
843 if (DiagID == diag::err_unavailable ||
844 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.
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.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ Result
The result type of a method or function.