17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/Support/ErrorHandling.h" 21 using namespace clang;
34 CLASS_EXTENSION = 0x04,
38 struct StaticDiagInfoRec {
40 unsigned DefaultSeverity : 3;
43 unsigned WarnNoWerror : 1;
44 unsigned WarnShowInSystemHeader : 1;
47 uint16_t OptionGroupIndex;
49 uint16_t DescriptionLen;
50 const char *DescriptionStr;
52 unsigned getOptionGroupIndex()
const {
53 return OptionGroupIndex;
56 StringRef getDescription()
const {
57 return StringRef(DescriptionStr, DescriptionLen);
65 bool operator<(
const StaticDiagInfoRec &RHS)
const {
66 return DiagID < RHS.DiagID;
70 #define STRINGIFY_NAME(NAME) #NAME 71 #define VALIDATE_DIAG_SIZE(NAME) \ 73 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \ 74 static_cast<unsigned>(diag::DIAG_START_##NAME) + \ 75 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \ 77 DIAG_SIZE_##NAME) " is insufficient to contain all " \ 78 "diagnostics, it may need to be made larger in " \ 91 #undef VALIDATE_DIAG_SIZE 97 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ 98 SHOWINSYSHEADER, CATEGORY) \ 100 diag::ENUM, DEFAULT_SEVERITY, CLASS, DiagnosticIDs::SFINAE, NOWERROR, \ 101 SHOWINSYSHEADER, CATEGORY, GROUP, STR_SIZE(DESC, uint16_t), DESC \ 104 #include "clang/Basic/DiagnosticCommonKinds.inc" 105 #include "clang/Basic/DiagnosticDriverKinds.inc" 106 #include "clang/Basic/DiagnosticFrontendKinds.inc" 107 #include "clang/Basic/DiagnosticSerializationKinds.inc" 108 #include "clang/Basic/DiagnosticLexKinds.inc" 109 #include "clang/Basic/DiagnosticParseKinds.inc" 110 #include "clang/Basic/DiagnosticASTKinds.inc" 111 #include "clang/Basic/DiagnosticCommentKinds.inc" 112 #include "clang/Basic/DiagnosticCrossTUKinds.inc" 113 #include "clang/Basic/DiagnosticSemaKinds.inc" 114 #include "clang/Basic/DiagnosticAnalysisKinds.inc" 115 #include "clang/Basic/DiagnosticRefactoringKinds.inc" 125 using namespace diag;
139 #define CATEGORY(NAME, PREV) \ 140 if (DiagID > DIAG_START_##NAME) { \ 141 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \ 142 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \ 158 if (ID + Offset >= StaticDiagInfoSize)
161 assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize);
163 const StaticDiagInfoRec *Found = &StaticDiagInfo[ID +
Offset];
167 if (Found->DiagID != DiagID)
176 if (
const StaticDiagInfoRec *StaticInfo =
GetDiagInfo(DiagID)) {
179 if (StaticInfo->WarnNoWerror) {
181 "Unexpected mapping with no-Werror bit!");
192 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
193 return Info->Category;
199 struct StaticDiagCategoryRec {
204 return StringRef(NameStr, NameLen);
214 std::pair<iterator, bool>
Result =
221 return Result.first->second;
225 #define GET_CATEGORY_TABLE 226 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, 227 #include "clang/Basic/DiagnosticGroups.inc" 228 #undef GET_CATEGORY_TABLE 234 return llvm::array_lengthof(CategoryNameTable) - 1;
241 if (CategoryID >= getNumberOfCategories())
243 return CategoryNameTable[CategoryID].getName();
250 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
252 return SFINAE_Report;
258 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
270 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
271 std::vector<DiagDesc> DiagInfo;
272 std::map<DiagDesc, unsigned> DiagIDs;
279 "Invalid diagnostic ID");
286 "Invalid diagnostic ID");
292 DiagDesc D(L, Message);
294 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
295 if (I != DiagIDs.end() && I->first == D)
300 DiagIDs.insert(std::make_pair(D,
ID));
301 DiagInfo.push_back(D);
327 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *
this);
353 bool &EnabledByDefault) {
373 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
374 return Info->getDescription();
375 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
376 return CustomDiagInfo->getDescription(DiagID);
392 llvm_unreachable(
"unexpected severity");
399 DiagnosticIDs::getDiagnosticLevel(
unsigned DiagID,
SourceLocation Loc,
403 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
404 return CustomDiagInfo->getLevel(DiagID);
409 return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
419 DiagnosticIDs::getDiagnosticSeverity(
unsigned DiagID,
SourceLocation Loc,
428 DiagnosticsEngine::DiagState *
State = Diag.GetDiagStateForLoc(Loc);
443 bool EnabledByDefault =
false;
444 bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
445 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
450 if (IsExtensionDiag && !Mapping.
isUser())
451 Result =
std::max(Result, State->ExtBehavior);
462 if (State->IgnoreAllWarnings) {
465 !isDefaultMappingAsError((
diag::kind)DiagID)))
484 Diag.CurDiagID != diag::fatal_too_many_errors && Diag.FatalsAsError)
488 bool ShowInSystemHeader =
494 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.
isValid() &&
502 #define GET_DIAG_ARRAYS 503 #include "clang/Basic/DiagnosticGroups.inc" 504 #undef GET_DIAG_ARRAYS 507 struct WarningOption {
514 return StringRef(DiagGroupNames + NameOffset + 1,
515 DiagGroupNames[NameOffset]);
522 #define GET_DIAG_TABLE 523 #include "clang/Basic/DiagnosticGroups.inc" 524 #undef GET_DIAG_TABLE 531 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
532 return OptionTable[Info->getOptionGroupIndex()].getName();
537 std::vector<std::string> Res;
538 for (
size_t I = 1; DiagGroupNames[I] !=
'\0';) {
539 std::string
Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
540 I += DiagGroupNames[I] + 1;
541 Res.push_back(
"-W" + Diag);
542 Res.push_back(
"-Wno-" + Diag);
551 const WarningOption *Group,
555 if (!Group->Members && !Group->SubGroups)
558 bool NotFound =
true;
561 const int16_t *Member = DiagArrays + Group->Members;
562 for (; *Member != -1; ++Member) {
565 Diags.push_back(*Member);
570 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
571 for (; *SubGroups != (int16_t)-1; ++SubGroups)
581 auto Found = llvm::partition_point(
582 OptionTable, [=](
const WarningOption &O) {
return O.getName() < Group; });
583 if (Found == std::end(OptionTable) || Found->getName() != Group)
590 std::vector<diag::kind> &Diags) {
592 if (StaticDiagInfo[i].getFlavor() == Flavor)
593 Diags.push_back(StaticDiagInfo[i].DiagID);
599 unsigned BestDistance = Group.size() + 1;
600 for (
const WarningOption &O : OptionTable) {
602 if (!O.Members && !O.SubGroups)
605 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
606 if (Distance > BestDistance)
614 if (Distance == BestDistance) {
617 }
else if (Distance < BestDistance) {
620 BestDistance = Distance;
632 assert(Diag.
getClient() &&
"DiagnosticClient not set!");
635 unsigned DiagID = Info.
getID();
642 ++Diag.TrapNumErrorsOccurred;
643 if (isUnrecoverable(DiagID))
644 ++Diag.TrapNumUnrecoverableErrorsOccurred;
647 if (Diag.SuppressAllDiagnostics)
656 Diag.FatalErrorOccurred =
true;
658 Diag.LastDiagLevel = DiagLevel;
663 if (Diag.FatalErrorOccurred) {
680 if (isUnrecoverable(DiagID))
681 Diag.UnrecoverableErrorOccurred =
true;
684 if (isDefaultMappingAsError(DiagID))
685 Diag.UncompilableErrorOccurred =
true;
687 Diag.ErrorOccurred =
true;
694 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
703 if (Diag.CurDiagID == diag::fatal_too_many_errors)
704 Diag.FatalErrorOccurred =
true;
706 EmitDiag(Diag, DiagLevel);
720 Diag.CurDiagID = ~0U;
723 bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
725 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
734 if (DiagID == diag::err_unavailable ||
735 DiagID == diag::err_unavailable_message)
739 if (isARCDiagnostic(DiagID))
746 unsigned cat = getCategoryNumberForDiag(DiagID);
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()
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID)
SourceManager & getSourceManager() const
DiagnosticIDs::Level getLevel(unsigned DiagID) const
getLevel - Return the level of the specified custom diagnostic.
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.
virtual bool IncludeInDiagnosticCounts() const
Indicates whether the diagnostics handled by this DiagnosticConsumer should be included in the number...
Severity
Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs to either Ignore (nothing)...
#define CATEGORY(NAME, PREV)
void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1="", StringRef Arg2="")
Set the "delayed" diagnostic that will be emitted once the current diagnostic completes.
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...
__DEVICE__ int max(int __a, int __b)
bool hasNoErrorAsFatal() 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. ...
const SourceLocation & getLocation() const
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID...
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...
diag::Severity getSeverity() const
Present this diagnostic as an error.
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.
#define VALIDATE_DIAG_SIZE(NAME)
static StringRef getWarningOptionForDiag(unsigned DiagID)
Return the lowest-level warning option that enables the specified diagnostic.
The result type of a method or function.
static void getAllDiagnostics(diag::Flavor Flavor, std::vector< diag::kind > &Diags)
Get the set of all diagnostic IDs.
Encodes a location in the source.
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.
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.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
static std::string getName(const CallEvent &Call)
Present this diagnostic as a remark.
StringRef getDescription(unsigned DiagID) const
getDescription - Return the description of the specified custom diagnostic.
Level
The level of the diagnostic, after it has been through mapping.
Used for handling and querying diagnostic IDs.
static const unsigned StaticDiagInfoSize
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)
StringRef getDescription(unsigned DiagID) const
Given a diagnostic ID, return a description of the issue.
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.
Do not present this diagnostic, ignore it.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
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.
Present this diagnostic as a fatal error.
void setNoWarningAsError(bool Value)
Present this diagnostic as a warning.
bool hasNoWarningAsError() const