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)
261 diag::Severity::Fatal,
false,
false);
263 if (
const StaticDiagInfoRec *StaticInfo =
GetDiagInfo(DiagID)) {
266 if (StaticInfo->WarnNoWerror) {
267 assert(Info.
getSeverity() == diag::Severity::Warning &&
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);
301 std::pair<iterator, bool>
Result =
308 return Result.first->second;
312#define GET_CATEGORY_TABLE
313#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
314#include "clang/Basic/DiagnosticGroups.inc"
315#undef GET_CATEGORY_TABLE
337 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
343 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
344 return Info->Deferrable;
351 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
363 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
364 std::vector<DiagDesc> DiagInfo;
365 std::map<DiagDesc, unsigned> DiagIDs;
372 "Invalid diagnostic ID");
379 "Invalid diagnostic ID");
385 DiagDesc D(L, std::string(Message));
387 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
388 if (I != DiagIDs.end() && I->first == D)
393 DiagIDs.insert(std::make_pair(D, ID));
394 DiagInfo.push_back(D);
420 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *
this);
446 bool &EnabledByDefault) {
466 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
467 return Info->getDescription();
468 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
469 return CustomDiagInfo->getDescription(DiagID);
485 llvm_unreachable(
"unexpected severity");
492DiagnosticIDs::getDiagnosticLevel(
unsigned DiagID,
SourceLocation Loc,
496 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
497 return CustomDiagInfo->getLevel(DiagID);
502 return toLevel(getDiagnosticSeverity(DiagID, Loc,
Diag));
512DiagnosticIDs::getDiagnosticSeverity(
unsigned DiagID,
SourceLocation Loc,
521 DiagnosticsEngine::DiagState *State =
Diag.GetDiagStateForLoc(Loc);
536 bool EnabledByDefault =
false;
538 if (
Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
543 if (IsExtensionDiag && !Mapping.
isUser())
555 if (State->IgnoreAllWarnings) {
577 Diag.CurDiagID != diag::fatal_too_many_errors &&
Diag.FatalsAsError)
581 bool ShowInSystemHeader =
587 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.
isValid() &&
588 Diag.getSourceManager().isInSystemHeader(
589 Diag.getSourceManager().getExpansionLoc(Loc)))
593 bool ShowInSystemMacro =
595 if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.
isValid() &&
596 Diag.getSourceManager().isInSystemMacro(Loc))
602#define GET_DIAG_ARRAYS
603#include "clang/Basic/DiagnosticGroups.inc"
604#undef GET_DIAG_ARRAYS
607 struct WarningOption {
611 StringRef Documentation;
615 return StringRef(DiagGroupNames + NameOffset + 1,
616 DiagGroupNames[NameOffset]);
623#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
624 {FlagNameOffset, Members, SubGroups, Docs},
625#include "clang/Basic/DiagnosticGroups.inc"
631 return OptionTable[
static_cast<int>(Group)].Documentation;
638std::optional<diag::Group>
640 const auto *Found = llvm::partition_point(
641 OptionTable, [=](
const WarningOption &O) {
return O.getName() < Name; });
642 if (Found == std::end(
OptionTable) || Found->getName() != Name)
648 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
649 return static_cast<diag::Group>(Info->getOptionGroupIndex());
663 std::vector<std::string> Res{
"-W",
"-Wno-"};
664 for (
size_t I = 1; DiagGroupNames[I] !=
'\0';) {
665 std::string
Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
666 I += DiagGroupNames[I] + 1;
667 Res.push_back(
"-W" +
Diag);
668 Res.push_back(
"-Wno-" +
Diag);
677 const WarningOption *Group,
681 if (!Group->Members && !Group->SubGroups)
684 bool NotFound =
true;
687 const int16_t *
Member = DiagArrays + Group->Members;
696 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
697 for (; *SubGroups != (int16_t)-1; ++SubGroups)
708 return ::getDiagnosticsInGroup(
709 Flavor, &
OptionTable[
static_cast<unsigned>(*G)], Diags);
714 std::vector<diag::kind> &Diags) {
716 if (StaticDiagInfo[i].getFlavor() == Flavor)
717 Diags.push_back(StaticDiagInfo[i].DiagID);
723 unsigned BestDistance = Group.size() + 1;
726 if (!O.Members && !O.SubGroups)
729 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
730 if (Distance > BestDistance)
738 if (Distance == BestDistance) {
741 }
else if (Distance < BestDistance) {
744 BestDistance = Distance;
756 assert(
Diag.getClient() &&
"DiagnosticClient not set!");
759 unsigned DiagID = Info.getID();
761 = getDiagnosticLevel(DiagID, Info.getLocation(),
Diag);
766 ++
Diag.TrapNumErrorsOccurred;
767 if (isUnrecoverable(DiagID))
768 ++
Diag.TrapNumUnrecoverableErrorsOccurred;
771 if (
Diag.SuppressAllDiagnostics)
780 Diag.FatalErrorOccurred =
true;
782 Diag.LastDiagLevel = DiagLevel;
787 if (
Diag.FatalErrorOccurred) {
789 Diag.Client->IncludeInDiagnosticCounts()) {
804 if (isUnrecoverable(DiagID))
805 Diag.UnrecoverableErrorOccurred =
true;
809 Diag.UncompilableErrorOccurred =
true;
811 Diag.ErrorOccurred =
true;
812 if (
Diag.Client->IncludeInDiagnosticCounts()) {
818 if (
Diag.ErrorLimit &&
Diag.NumErrors >
Diag.ErrorLimit &&
820 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
827 if (
Diag.CurDiagID == diag::fatal_too_many_errors)
828 Diag.FatalErrorOccurred =
true;
830 EmitDiag(
Diag, DiagLevel);
839 if (
Diag.Client->IncludeInDiagnosticCounts()) {
844 Diag.CurDiagID = ~0
U;
847bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
849 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
858 if (DiagID == diag::err_unavailable ||
859 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 DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID)
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.
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.