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);
279 std::map<DiagDesc, unsigned>::iterator
I = DiagIDs.lower_bound(D);
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 DiagnosticsEngine::DiagState *
State = Diag.GetDiagStateForLoc(Loc);
430 bool EnabledByDefault =
false;
432 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
437 if (IsExtensionDiag && !Mapping.
isUser())
438 Result =
std::max(Result, State->ExtBehavior);
465 bool ShowInSystemHeader =
471 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.
isValid() &&
479 #define GET_DIAG_ARRAYS
480 #include "clang/Basic/DiagnosticGroups.inc"
481 #undef GET_DIAG_ARRAYS
484 struct WarningOption {
490 StringRef getName()
const {
491 return StringRef(DiagGroupNames + NameOffset + 1,
492 DiagGroupNames[NameOffset]);
499 #define GET_DIAG_TABLE
500 #include "clang/Basic/DiagnosticGroups.inc"
501 #undef GET_DIAG_TABLE
508 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
509 return OptionTable[Info->getOptionGroupIndex()].getName();
514 std::vector<std::string> Res;
515 for (
size_t I = 1; DiagGroupNames[
I] !=
'\0';) {
516 std::string
Diag(DiagGroupNames +
I + 1, DiagGroupNames[
I]);
517 I += DiagGroupNames[
I] + 1;
518 Res.push_back(
"-W" + Diag);
519 Res.push_back(
"-Wno-" + Diag);
528 const WarningOption *Group,
532 if (!Group->Members && !Group->SubGroups)
535 bool NotFound =
true;
538 const int16_t *Member = DiagArrays + Group->Members;
539 for (; *Member != -1; ++Member) {
542 Diags.push_back(*Member);
547 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
548 for (; *SubGroups != (int16_t)-1; ++SubGroups)
558 auto Found = std::lower_bound(std::begin(OptionTable), std::end(OptionTable),
560 [](
const WarningOption &LHS, StringRef RHS) {
561 return LHS.getName() < RHS;
563 if (Found == std::end(OptionTable) || Found->getName() != Group)
579 unsigned BestDistance = Group.size() + 1;
580 for (
const WarningOption &O : OptionTable) {
582 if (!O.Members && !O.SubGroups)
585 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
586 if (Distance > BestDistance)
594 if (Distance == BestDistance) {
597 }
else if (Distance < BestDistance) {
600 BestDistance = Distance;
612 assert(Diag.
getClient() &&
"DiagnosticClient not set!");
615 unsigned DiagID = Info.getID();
617 = getDiagnosticLevel(DiagID, Info.getLocation(),
Diag);
622 ++Diag.TrapNumErrorsOccurred;
623 if (isUnrecoverable(DiagID))
624 ++Diag.TrapNumUnrecoverableErrorsOccurred;
627 if (Diag.SuppressAllDiagnostics)
636 Diag.FatalErrorOccurred =
true;
638 Diag.LastDiagLevel = DiagLevel;
643 if (Diag.FatalErrorOccurred && Diag.SuppressAfterFatalError) {
660 if (isUnrecoverable(DiagID))
661 Diag.UnrecoverableErrorOccurred =
true;
665 Diag.UncompilableErrorOccurred =
true;
667 Diag.ErrorOccurred =
true;
674 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
683 if (Diag.CurDiagID == diag::fatal_too_many_errors)
684 Diag.FatalErrorOccurred =
true;
686 EmitDiag(Diag, DiagLevel);
700 Diag.CurDiagID = ~0U;
703 bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
705 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
714 if (DiagID == diag::err_unavailable ||
715 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.
bool isValid() const
Return true if this is a valid SourceLocation object.
static const WarningOption OptionTable[]
static std::vector< std::string > getDiagnosticFlags()
Get the string of all diagnostic flags.
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...