17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/Support/ErrorHandling.h"
20#include "llvm/Support/Path.h"
31struct StaticDiagInfoRec;
36struct StaticDiagInfoDescriptionStringTable {
37#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
38 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
39 char ENUM##_desc[sizeof(DESC)];
41#include "clang/Basic/DiagnosticCommonKinds.inc"
42#include "clang/Basic/DiagnosticDriverKinds.inc"
43#include "clang/Basic/DiagnosticFrontendKinds.inc"
44#include "clang/Basic/DiagnosticSerializationKinds.inc"
45#include "clang/Basic/DiagnosticLexKinds.inc"
46#include "clang/Basic/DiagnosticParseKinds.inc"
47#include "clang/Basic/DiagnosticASTKinds.inc"
48#include "clang/Basic/DiagnosticCommentKinds.inc"
49#include "clang/Basic/DiagnosticCrossTUKinds.inc"
50#include "clang/Basic/DiagnosticSemaKinds.inc"
51#include "clang/Basic/DiagnosticAnalysisKinds.inc"
52#include "clang/Basic/DiagnosticRefactoringKinds.inc"
53#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
58const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions = {
59#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
60 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
63#include "clang/Basic/DiagnosticCommonKinds.inc"
64#include "clang/Basic/DiagnosticDriverKinds.inc"
65#include "clang/Basic/DiagnosticFrontendKinds.inc"
66#include "clang/Basic/DiagnosticSerializationKinds.inc"
67#include "clang/Basic/DiagnosticLexKinds.inc"
68#include "clang/Basic/DiagnosticParseKinds.inc"
69#include "clang/Basic/DiagnosticASTKinds.inc"
70#include "clang/Basic/DiagnosticCommentKinds.inc"
71#include "clang/Basic/DiagnosticCrossTUKinds.inc"
72#include "clang/Basic/DiagnosticSemaKinds.inc"
73#include "clang/Basic/DiagnosticAnalysisKinds.inc"
74#include "clang/Basic/DiagnosticRefactoringKinds.inc"
75#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
80extern const StaticDiagInfoRec StaticDiagInfo[];
84const uint32_t StaticDiagInfoDescriptionOffsets[] = {
85#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
86 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
87 offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc),
89#include "clang/Basic/DiagnosticCommonKinds.inc"
90#include "clang/Basic/DiagnosticDriverKinds.inc"
91#include "clang/Basic/DiagnosticFrontendKinds.inc"
92#include "clang/Basic/DiagnosticSerializationKinds.inc"
93#include "clang/Basic/DiagnosticLexKinds.inc"
94#include "clang/Basic/DiagnosticParseKinds.inc"
95#include "clang/Basic/DiagnosticASTKinds.inc"
96#include "clang/Basic/DiagnosticCommentKinds.inc"
97#include "clang/Basic/DiagnosticCrossTUKinds.inc"
98#include "clang/Basic/DiagnosticSemaKinds.inc"
99#include "clang/Basic/DiagnosticAnalysisKinds.inc"
100#include "clang/Basic/DiagnosticRefactoringKinds.inc"
101#include "clang/Basic/DiagnosticInstallAPIKinds.inc"
107enum DiagnosticClass {
110 CLASS_WARNING = 0x03,
111 CLASS_EXTENSION = 0x04,
115struct StaticDiagInfoRec {
118 uint8_t DefaultSeverity : 3;
119 LLVM_PREFERRED_TYPE(DiagnosticClass)
124 LLVM_PREFERRED_TYPE(
bool)
125 uint8_t WarnNoWerror : 1;
126 LLVM_PREFERRED_TYPE(
bool)
127 uint8_t WarnShowInSystemHeader : 1;
128 LLVM_PREFERRED_TYPE(
bool)
129 uint8_t WarnShowInSystemMacro : 1;
131 uint16_t OptionGroupIndex : 15;
132 LLVM_PREFERRED_TYPE(
bool)
133 uint16_t Deferrable : 1;
135 uint16_t DescriptionLen;
137 unsigned getOptionGroupIndex()
const {
138 return OptionGroupIndex;
141 StringRef getDescription()
const {
142 size_t MyIndex =
this - &StaticDiagInfo[0];
143 uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex];
144 const char* Table =
reinterpret_cast<const char*
>(&StaticDiagInfoDescriptions);
145 return StringRef(&Table[StringOffset], DescriptionLen);
149 return Class == CLASS_REMARK ? diag::Flavor::Remark
150 : diag::Flavor::WarningOrError;
153 bool operator<(
const StaticDiagInfoRec &RHS)
const {
154 return DiagID < RHS.DiagID;
158#define STRINGIFY_NAME(NAME) #NAME
159#define VALIDATE_DIAG_SIZE(NAME) \
161 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
162 static_cast<unsigned>(diag::DIAG_START_##NAME) + \
163 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
165 DIAG_SIZE_##NAME) " is insufficient to contain all " \
166 "diagnostics, it may need to be made larger in " \
181#undef VALIDATE_DIAG_SIZE
184const StaticDiagInfoRec StaticDiagInfo[] = {
186#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
187 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
192 DiagnosticIDs::SFINAE, \
199 STR_SIZE(DESC, uint16_t)},
200#include "clang/Basic/DiagnosticCommonKinds.inc"
201#include "clang/Basic/DiagnosticDriverKinds.inc"
202#include "clang/Basic/DiagnosticFrontendKinds.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"
225 using namespace diag;
226 if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
238 unsigned ID = DiagID - DIAG_START_COMMON - 1;
239#define CATEGORY(NAME, PREV) \
240 if (DiagID > DIAG_START_##NAME) { \
241 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
242 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
264 const StaticDiagInfoRec *
Found = &StaticDiagInfo[ID + Offset];
268 if (
Found->DiagID != DiagID)
277 if (
const StaticDiagInfoRec *StaticInfo =
GetDiagInfo(DiagID)) {
280 if (StaticInfo->WarnNoWerror) {
282 "Unexpected mapping with no-Werror bit!");
293 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
294 return Info->Category;
300 struct StaticDiagCategoryRec {
305 return StringRef(NameStr,
NameLen);
311#define GET_CATEGORY_TABLE
312#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
313#include "clang/Basic/DiagnosticGroups.inc"
314#undef GET_CATEGORY_TABLE
336 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
342 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
343 return Info->Deferrable;
350 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
362 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
363 std::vector<DiagDesc> DiagInfo;
364 std::map<DiagDesc, unsigned> DiagIDs;
371 "Invalid diagnostic ID");
378 "Invalid diagnostic ID");
384 DiagDesc
D(L, std::string(Message));
386 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(
D);
387 if (I != DiagIDs.end() && I->first ==
D)
392 DiagIDs.insert(std::make_pair(
D, ID));
393 DiagInfo.push_back(
D);
419 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *
this);
445 bool &EnabledByDefault) {
465 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
466 return Info->getDescription();
467 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
468 return CustomDiagInfo->getDescription(DiagID);
484 llvm_unreachable(
"unexpected severity");
495 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
496 return CustomDiagInfo->getLevel(DiagID);
520 DiagnosticsEngine::DiagState *State =
Diag.GetDiagStateForLoc(
Loc);
535 bool EnabledByDefault =
false;
537 if (
Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
542 if (IsExtensionDiag && !Mapping.
isUser())
554 if (State->IgnoreAllWarnings) {
576 DiagID != diag::fatal_too_many_errors &&
Diag.FatalsAsError)
581 if (!
Diag.hasSourceManager())
584 const auto &
SM =
Diag.getSourceManager();
586 bool ShowInSystemHeader =
592 if (State->SuppressSystemWarnings && !ShowInSystemHeader &&
Loc.
isValid() &&
593 SM.isInSystemHeader(
SM.getExpansionLoc(
Loc)))
597 bool ShowInSystemMacro =
599 if (State->SuppressSystemWarnings && !ShowInSystemMacro &&
Loc.
isValid() &&
600 SM.isInSystemMacro(
Loc))
610#define GET_DIAG_ARRAYS
611#include "clang/Basic/DiagnosticGroups.inc"
612#undef GET_DIAG_ARRAYS
615 struct WarningOption {
619 StringRef Documentation;
623 return StringRef(DiagGroupNames + NameOffset + 1,
624 DiagGroupNames[NameOffset]);
631#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
632 {FlagNameOffset, Members, SubGroups, Docs},
633#include "clang/Basic/DiagnosticGroups.inc"
639 return OptionTable[
static_cast<int>(Group)].Documentation;
646std::optional<diag::Group>
648 const auto *
Found = llvm::partition_point(
649 OptionTable, [=](
const WarningOption &O) {
return O.getName() < Name; });
656 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
657 return static_cast<diag::Group>(Info->getOptionGroupIndex());
671 std::vector<std::string> Res{
"-W",
"-Wno-"};
672 for (
size_t I = 1; DiagGroupNames[I] !=
'\0';) {
673 std::string
Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
674 I += DiagGroupNames[I] + 1;
675 Res.push_back(
"-W" +
Diag);
676 Res.push_back(
"-Wno-" +
Diag);
685 const WarningOption *Group,
689 if (!Group->Members && !Group->SubGroups)
695 const int16_t *
Member = DiagArrays + Group->Members;
704 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
705 for (; *SubGroups != (int16_t)-1; ++SubGroups)
716 return ::getDiagnosticsInGroup(
717 Flavor, &
OptionTable[
static_cast<unsigned>(*G)], Diags);
722 std::vector<diag::kind> &Diags) {
724 if (StaticDiagInfo[i].getFlavor() == Flavor)
725 Diags.push_back(StaticDiagInfo[i].DiagID);
731 unsigned BestDistance = Group.size() + 1;
734 if (!O.Members && !O.SubGroups)
737 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
738 if (Distance > BestDistance)
746 if (Distance == BestDistance) {
749 }
else if (Distance < BestDistance) {
752 BestDistance = Distance;
765 assert(
Diag.getClient() &&
"DiagnosticClient not set!");
768 unsigned DiagID = Info.getID();
770 = getDiagnosticLevel(DiagID, Info.getLocation(),
Diag);
775 ++
Diag.TrapNumErrorsOccurred;
776 if (isUnrecoverable(DiagID))
777 ++
Diag.TrapNumUnrecoverableErrorsOccurred;
780 if (
Diag.SuppressAllDiagnostics)
789 Diag.FatalErrorOccurred =
true;
791 Diag.LastDiagLevel = DiagLevel;
796 if (
Diag.FatalErrorOccurred) {
798 Diag.Client->IncludeInDiagnosticCounts()) {
813 if (isUnrecoverable(DiagID))
814 Diag.UnrecoverableErrorOccurred =
true;
818 Diag.UncompilableErrorOccurred =
true;
820 Diag.ErrorOccurred =
true;
821 if (
Diag.Client->IncludeInDiagnosticCounts()) {
827 if (
Diag.ErrorLimit &&
Diag.NumErrors >
Diag.ErrorLimit &&
829 Diag.Report(diag::fatal_too_many_errors);
836 if (Info.getID() == diag::fatal_too_many_errors)
837 Diag.FatalErrorOccurred =
true;
839 EmitDiag(
Diag, DiagBuilder, DiagLevel);
845 Level DiagLevel)
const {
850 if (
Diag.Client->IncludeInDiagnosticCounts()) {
856bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
858 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
867 if (DiagID == diag::err_unavailable ||
868 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.
A little helper class used to produce diagnostics.
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 a...
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.