18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/Support/ErrorHandling.h"
22 using namespace clang;
35 CLASS_EXTENSION = 0x04,
39 struct StaticDiagInfoRec {
41 unsigned DefaultSeverity : 3;
44 unsigned WarnNoWerror : 1;
45 unsigned WarnShowInSystemHeader : 1;
48 uint16_t OptionGroupIndex;
50 uint16_t DescriptionLen;
51 const char *DescriptionStr;
53 unsigned getOptionGroupIndex()
const {
54 return OptionGroupIndex;
57 StringRef getDescription()
const {
58 return StringRef(DescriptionStr, DescriptionLen);
66 bool operator<(
const StaticDiagInfoRec &RHS)
const {
67 return DiagID < RHS.DiagID;
74 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
75 SHOWINSYSHEADER, CATEGORY) \
77 diag::ENUM, DEFAULT_SEVERITY, CLASS, DiagnosticIDs::SFINAE, NOWERROR, \
78 SHOWINSYSHEADER, CATEGORY, GROUP, STR_SIZE(DESC, uint16_t), DESC \
81 #include "clang/Basic/DiagnosticCommonKinds.inc"
82 #include "clang/Basic/DiagnosticDriverKinds.inc"
83 #include "clang/Basic/DiagnosticFrontendKinds.inc"
84 #include "clang/Basic/DiagnosticSerializationKinds.inc"
85 #include "clang/Basic/DiagnosticLexKinds.inc"
86 #include "clang/Basic/DiagnosticParseKinds.inc"
87 #include "clang/Basic/DiagnosticASTKinds.inc"
88 #include "clang/Basic/DiagnosticCommentKinds.inc"
89 #include "clang/Basic/DiagnosticSemaKinds.inc"
90 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
98 static const StaticDiagInfoRec *
GetDiagInfo(
unsigned DiagID) {
101 static bool IsFirst =
true;
105 "Diag ID conflict, the enums at the start of clang::diag (in "
106 "DiagnosticIDs.h) probably need to be increased");
112 using namespace diag;
126 #define CATEGORY(NAME, PREV) \
127 if (DiagID > DIAG_START_##NAME) { \
128 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
129 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
152 if (Found->DiagID != DiagID)
161 if (
const StaticDiagInfoRec *StaticInfo =
GetDiagInfo(DiagID)) {
164 if (StaticInfo->WarnNoWerror) {
166 "Unexpected mapping with no-Werror bit!");
177 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
178 return Info->Category;
184 struct StaticDiagCategoryRec {
188 StringRef getName()
const {
189 return StringRef(NameStr, NameLen);
199 std::pair<iterator, bool>
Result =
206 return Result.first->second;
210 #define GET_CATEGORY_TABLE
211 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
212 #include "clang/Basic/DiagnosticGroups.inc"
213 #undef GET_CATEGORY_TABLE
219 return llvm::array_lengthof(CategoryNameTable) - 1;
228 return CategoryNameTable[CategoryID].getName();
235 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
243 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
255 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
256 std::vector<DiagDesc> DiagInfo;
257 std::map<DiagDesc, unsigned> DiagIDs;
264 "Invalid diagnostic ID");
271 "Invalid diagnostic ID");
277 DiagDesc D(L, Message);
280 if (I != DiagIDs.end() && I->first == D)
285 DiagIDs.insert(std::make_pair(D,
ID));
286 DiagInfo.push_back(D);
302 delete CustomDiagInfo;
340 bool &EnabledByDefault) {
360 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
361 return Info->getDescription();
362 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
379 llvm_unreachable(
"unexpected severity");
386 DiagnosticIDs::getDiagnosticLevel(
unsigned DiagID,
SourceLocation Loc,
390 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
391 return CustomDiagInfo->
getLevel(DiagID);
396 return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
406 DiagnosticIDs::getDiagnosticSeverity(
unsigned DiagID,
SourceLocation Loc,
415 Pos = Diag.GetDiagStatePointForLoc(Loc);
416 DiagnosticsEngine::DiagState *
State = Pos->State;
433 bool EnabledByDefault =
false;
435 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
440 if (IsExtensionDiag && !Mapping.
isUser())
441 Result = std::max(Result, Diag.ExtBehavior);
466 bool ShowInSystemHeader =
472 if (Diag.SuppressSystemWarnings && !ShowInSystemHeader && Loc.
isValid() &&
480 #define GET_DIAG_ARRAYS
481 #include "clang/Basic/DiagnosticGroups.inc"
482 #undef GET_DIAG_ARRAYS
485 struct WarningOption {
491 StringRef getName()
const {
492 return StringRef(DiagGroupNames + NameOffset + 1,
493 DiagGroupNames[NameOffset]);
500 #define GET_DIAG_TABLE
501 #include "clang/Basic/DiagnosticGroups.inc"
502 #undef GET_DIAG_TABLE
509 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
510 return OptionTable[Info->getOptionGroupIndex()].getName();
517 const WarningOption *Group,
521 if (!Group->Members && !Group->SubGroups)
524 bool NotFound =
true;
527 const int16_t *Member = DiagArrays + Group->Members;
528 for (; *Member != -1; ++Member) {
531 Diags.push_back(*Member);
536 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
537 for (; *SubGroups != (int16_t)-1; ++SubGroups)
549 [](
const WarningOption &LHS, StringRef RHS) {
550 return LHS.getName() < RHS;
552 if (Found ==
std::end(OptionTable) || Found->getName() != Group)
568 unsigned BestDistance = Group.size() + 1;
569 for (
const WarningOption &O : OptionTable) {
571 if (!O.Members && !O.SubGroups)
574 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
575 if (Distance > BestDistance)
583 if (Distance == BestDistance) {
586 }
else if (Distance < BestDistance) {
589 BestDistance = Distance;
601 assert(Diag.
getClient() &&
"DiagnosticClient not set!");
604 unsigned DiagID = Info.getID();
606 = getDiagnosticLevel(DiagID, Info.getLocation(),
Diag);
611 ++Diag.TrapNumErrorsOccurred;
612 if (isUnrecoverable(DiagID))
613 ++Diag.TrapNumUnrecoverableErrorsOccurred;
616 if (Diag.SuppressAllDiagnostics)
625 Diag.FatalErrorOccurred =
true;
627 Diag.LastDiagLevel = DiagLevel;
632 if (Diag.FatalErrorOccurred) {
649 if (isUnrecoverable(DiagID))
650 Diag.UnrecoverableErrorOccurred =
true;
654 Diag.UncompilableErrorOccurred =
true;
656 Diag.ErrorOccurred =
true;
663 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
671 EmitDiag(Diag, DiagLevel);
685 Diag.CurDiagID = ~0U;
688 bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
690 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
699 if (DiagID == diag::err_unavailable ||
700 DiagID == diag::err_unavailable_message)
static unsigned getCategoryNumberForDiag(unsigned DiagID)
Return the category number that a specified DiagID belongs to, or 0 if no category.
A diagnostic that indicates a problem or potential problem.
unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message, DiagnosticIDs &Diags)
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.
DiagnosticConsumer * getClient()
static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID)
Defines the SourceManager interface.
static unsigned getBuiltinDiagClass(unsigned DiagID)
getBuiltinDiagClass - Return the class field of the diagnostic.
static DiagnosticIDs::Level toLevel(diag::Severity SV)
static StringRef getCategoryNameFromID(unsigned CategoryID)
Given a category ID, return the name of the category.
Severity
Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs to either Ignore (nothing)...
#define CATEGORY(NAME, PREV)
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.
void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1="", StringRef Arg2="")
Set the "delayed" diagnostic that will be emitted once the current diagnostic completes.
void getAllDiagnostics(diag::Flavor Flavor, SmallVectorImpl< diag::kind > &Diags) const
Get the set of all diagnostic IDs.
StringRef getDescription(unsigned DiagID) const
getDescription - Return the description of the specified custom diagnostic.
bool hasNoErrorAsFatal() const
Includes all the separate Diagnostic headers & some related helpers.
static const StaticDiagInfoRec StaticDiagInfo[]
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...
SourceManager & getSourceManager() const
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. ...
virtual bool IncludeInDiagnosticCounts() const
Indicates whether the diagnostics handled by this DiagnosticConsumer should be included in the number...
Concrete class used by the front-end to report problems and issues.
static bool isBuiltinWarningOrExtension(unsigned DiagID)
Return true if the unmapped diagnostic levelof the specified diagnostic ID is a Warning or Extension...
Present this diagnostic as an error.
detail::InMemoryDirectory::const_iterator I
static const StaticDiagInfoRec * GetDiagInfo(unsigned DiagID)
GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, or null if the ID is inval...
ID
Defines the set of possible language-specific address spaces.
static bool isBuiltinExtensionDiag(unsigned DiagID)
Determine whether the given built-in diagnostic ID is for an extension of some sort.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
static StringRef getWarningOptionForDiag(unsigned DiagID)
Return the lowest-level warning option that enables the specified diagnostic.
diag::Severity getSeverity() const
The result type of a method or function.
Encodes a location in the source.
const TemplateArgument * iterator
bool isValid() const
Return true if this is a valid SourceLocation object.
static const WarningOption OptionTable[]
virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info)
Handle this diagnostic, reporting it to the user or capturing it to a log as needed.
Flavor
Flavors of diagnostics we can emit.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
static DiagnosticMapping Make(diag::Severity Severity, bool IsUser, bool IsPragma)
static bool isBuiltinNote(unsigned DiagID)
Determine whether the given built-in diagnostic ID is a Note.
unsigned getCustomDiagID(Level L, StringRef FormatString)
Return an ID for a diagnostic with the specified format string and level.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T-> getSizeExpr()))
Present this diagnostic as a remark.
Level
The level of the diagnostic, after it has been through mapping.
Used for handling and querying diagnostic IDs.
bool hasNoWarningAsError() const
static const unsigned StaticDiagInfoSize
StringRef getDescription(unsigned DiagID) const
Given a diagnostic ID, return a description of the issue.
static bool isDefaultMappingAsError(unsigned DiagID)
Return true if the specified diagnostic is mapped to errors by default.
static const StaticDiagCategoryRec CategoryNameTable[]
void setSeverity(diag::Severity Value)
static bool isARCDiagnostic(unsigned DiagID)
Return true if a given diagnostic falls into an ARC diagnostic category.
static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID)
Determines whether the given built-in diagnostic ID is for an error that is suppressed if it occurs d...
SFINAEResponse
Enumeration describing how the emission of a diagnostic should be treated when it occurs during C++ t...
#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)
Level
The level of the diagnostic, after it has been through mapping.
DiagnosticIDs::Level getLevel(unsigned DiagID) const
getLevel - Return the level of the specified custom diagnostic.
Do not present this diagnostic, ignore it.
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
A diagnostic that indicates normal progress through compilation.
Defines the Diagnostic IDs-related interfaces.
The diagnostic should be reported.
Present this diagnostic as a fatal error.
void setNoWarningAsError(bool Value)
Present this diagnostic as a warning.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...