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);
467 if (Diag.FatalsAsError)
472 bool ShowInSystemHeader =
478 if (Diag.SuppressSystemWarnings && !ShowInSystemHeader && Loc.
isValid() &&
486 #define GET_DIAG_ARRAYS
487 #include "clang/Basic/DiagnosticGroups.inc"
488 #undef GET_DIAG_ARRAYS
491 struct WarningOption {
497 StringRef getName()
const {
498 return StringRef(DiagGroupNames + NameOffset + 1,
499 DiagGroupNames[NameOffset]);
506 #define GET_DIAG_TABLE
507 #include "clang/Basic/DiagnosticGroups.inc"
508 #undef GET_DIAG_TABLE
515 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
516 return OptionTable[Info->getOptionGroupIndex()].getName();
523 const WarningOption *Group,
527 if (!Group->Members && !Group->SubGroups)
530 bool NotFound =
true;
533 const int16_t *Member = DiagArrays + Group->Members;
534 for (; *Member != -1; ++Member) {
537 Diags.push_back(*Member);
542 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
543 for (; *SubGroups != (int16_t)-1; ++SubGroups)
555 [](
const WarningOption &LHS, StringRef RHS) {
556 return LHS.getName() < RHS;
558 if (Found ==
std::end(OptionTable) || Found->getName() != Group)
574 unsigned BestDistance = Group.size() + 1;
575 for (
const WarningOption &O : OptionTable) {
577 if (!O.Members && !O.SubGroups)
580 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
581 if (Distance > BestDistance)
589 if (Distance == BestDistance) {
592 }
else if (Distance < BestDistance) {
595 BestDistance = Distance;
607 assert(Diag.
getClient() &&
"DiagnosticClient not set!");
610 unsigned DiagID = Info.getID();
612 = getDiagnosticLevel(DiagID, Info.getLocation(),
Diag);
617 ++Diag.TrapNumErrorsOccurred;
618 if (isUnrecoverable(DiagID))
619 ++Diag.TrapNumUnrecoverableErrorsOccurred;
622 if (Diag.SuppressAllDiagnostics)
631 Diag.FatalErrorOccurred =
true;
633 Diag.LastDiagLevel = DiagLevel;
638 if (Diag.FatalErrorOccurred) {
655 if (isUnrecoverable(DiagID))
656 Diag.UnrecoverableErrorOccurred =
true;
660 Diag.UncompilableErrorOccurred =
true;
662 Diag.ErrorOccurred =
true;
669 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
677 EmitDiag(Diag, DiagLevel);
691 Diag.CurDiagID = ~0U;
694 bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
696 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
705 if (DiagID == diag::err_unavailable ||
706 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...
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)
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
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...