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;
46 unsigned Category : 5;
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");
109 "Improperly sorted diag info");
116 using namespace diag;
130 #define CATEGORY(NAME, PREV) \
131 if (DiagID > DIAG_START_##NAME) { \
132 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
133 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
156 if (Found->DiagID != DiagID)
165 if (
const StaticDiagInfoRec *StaticInfo =
GetDiagInfo(DiagID)) {
168 if (StaticInfo->WarnNoWerror) {
170 "Unexpected mapping with no-Werror bit!");
181 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
182 return Info->Category;
188 struct StaticDiagCategoryRec {
192 StringRef getName()
const {
193 return StringRef(NameStr, NameLen);
203 std::pair<iterator, bool>
Result =
210 return Result.first->second;
214 #define GET_CATEGORY_TABLE
215 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
216 #include "clang/Basic/DiagnosticGroups.inc"
217 #undef GET_CATEGORY_TABLE
223 return llvm::array_lengthof(CategoryNameTable) - 1;
232 return CategoryNameTable[CategoryID].getName();
239 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
247 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
259 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
260 std::vector<DiagDesc> DiagInfo;
261 std::map<DiagDesc, unsigned> DiagIDs;
268 "Invalid diagnostic ID");
275 "Invalid diagnostic ID");
281 DiagDesc D(L, Message);
283 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
284 if (I != DiagIDs.end() && I->first == D)
289 DiagIDs.insert(std::make_pair(D,
ID));
290 DiagInfo.push_back(D);
306 delete CustomDiagInfo;
344 bool &EnabledByDefault) {
364 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
365 return Info->getDescription();
366 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
383 llvm_unreachable(
"unexpected severity");
390 DiagnosticIDs::getDiagnosticLevel(
unsigned DiagID,
SourceLocation Loc,
394 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
395 return CustomDiagInfo->
getLevel(DiagID);
400 return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
410 DiagnosticIDs::getDiagnosticSeverity(
unsigned DiagID,
SourceLocation Loc,
418 DiagnosticsEngine::DiagStatePointsTy::iterator
419 Pos = Diag.GetDiagStatePointForLoc(Loc);
420 DiagnosticsEngine::DiagState *
State = Pos->State;
437 bool EnabledByDefault =
false;
439 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
444 if (IsExtensionDiag && !Mapping.
isUser())
445 Result = std::max(Result, Diag.ExtBehavior);
470 bool ShowInSystemHeader =
476 if (Diag.SuppressSystemWarnings && !ShowInSystemHeader && Loc.
isValid() &&
484 #define GET_DIAG_ARRAYS
485 #include "clang/Basic/DiagnosticGroups.inc"
486 #undef GET_DIAG_ARRAYS
489 struct WarningOption {
495 StringRef getName()
const {
496 return StringRef(DiagGroupNames + NameOffset + 1,
497 DiagGroupNames[NameOffset]);
504 #define GET_DIAG_TABLE
505 #include "clang/Basic/DiagnosticGroups.inc"
506 #undef GET_DIAG_TABLE
511 return LHS.getName() < RHS;
518 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
519 return OptionTable[Info->getOptionGroupIndex()].getName();
526 const WarningOption *Group,
530 if (!Group->Members && !Group->SubGroups)
533 bool NotFound =
true;
536 const int16_t *Member = DiagArrays + Group->Members;
537 for (; *Member != -1; ++Member) {
540 Diags.push_back(*Member);
545 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
546 for (; *SubGroups != (int16_t)-1; ++SubGroups)
556 const WarningOption *Found = std::lower_bound(
558 if (Found == OptionTable + OptionTableSize ||
559 Found->getName() != Group)
575 unsigned BestDistance = Group.size() + 1;
576 for (
const WarningOption *i = OptionTable, *e = OptionTable + OptionTableSize;
579 if (!i->Members && !i->SubGroups)
582 unsigned Distance = i->getName().edit_distance(Group,
true, BestDistance);
583 if (Distance > BestDistance)
591 if (Distance == BestDistance) {
594 }
else if (Distance < BestDistance) {
597 BestDistance = Distance;
609 assert(Diag.
getClient() &&
"DiagnosticClient not set!");
612 unsigned DiagID = Info.getID();
614 = getDiagnosticLevel(DiagID, Info.getLocation(),
Diag);
619 ++Diag.TrapNumErrorsOccurred;
620 if (isUnrecoverable(DiagID))
621 ++Diag.TrapNumUnrecoverableErrorsOccurred;
624 if (Diag.SuppressAllDiagnostics)
633 Diag.FatalErrorOccurred =
true;
635 Diag.LastDiagLevel = DiagLevel;
640 if (Diag.FatalErrorOccurred) {
657 if (isUnrecoverable(DiagID))
658 Diag.UnrecoverableErrorOccurred =
true;
662 Diag.UncompilableErrorOccurred =
true;
664 Diag.ErrorOccurred =
true;
671 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
679 EmitDiag(Diag, DiagLevel);
693 Diag.CurDiagID = ~0U;
696 bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
698 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
707 if (DiagID == diag::err_unavailable ||
708 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.
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 bool WarningOptionCompare(const WarningOption &LHS, StringRef RHS)
static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID)
Defines the SourceManager interface.
static unsigned getBuiltinDiagClass(unsigned DiagID)
static DiagnosticIDs::Level toLevel(diag::Severity SV)
static StringRef getCategoryNameFromID(unsigned CategoryID)
Given a category ID, return the name of the category.
#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
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)
SourceManager & getSourceManager() const
static const size_t OptionTableSize
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.
static const StaticDiagInfoRec * GetDiagInfo(unsigned DiagID)
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. The SourceManager can decode this to get at the full include stack...
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.
bool operator<(DeclarationName LHS, DeclarationName RHS)
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.
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...