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;
71 #define STRINGIFY_NAME(NAME) #NAME 72 #define VALIDATE_DIAG_SIZE(NAME) \ 74 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \ 75 static_cast<unsigned>(diag::DIAG_START_##NAME) + \ 76 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \ 78 DIAG_SIZE_##NAME) " is insufficient to contain all " \ 79 "diagnostics, it may need to be made larger in " \ 92 #undef VALIDATE_DIAG_SIZE 98 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ 99 SHOWINSYSHEADER, CATEGORY) \ 101 diag::ENUM, DEFAULT_SEVERITY, CLASS, DiagnosticIDs::SFINAE, NOWERROR, \ 102 SHOWINSYSHEADER, CATEGORY, GROUP, STR_SIZE(DESC, uint16_t), DESC \ 105 #include "clang/Basic/DiagnosticCommonKinds.inc" 106 #include "clang/Basic/DiagnosticDriverKinds.inc" 107 #include "clang/Basic/DiagnosticFrontendKinds.inc" 108 #include "clang/Basic/DiagnosticSerializationKinds.inc" 109 #include "clang/Basic/DiagnosticLexKinds.inc" 110 #include "clang/Basic/DiagnosticParseKinds.inc" 111 #include "clang/Basic/DiagnosticASTKinds.inc" 112 #include "clang/Basic/DiagnosticCommentKinds.inc" 113 #include "clang/Basic/DiagnosticCrossTUKinds.inc" 114 #include "clang/Basic/DiagnosticSemaKinds.inc" 115 #include "clang/Basic/DiagnosticAnalysisKinds.inc" 116 #include "clang/Basic/DiagnosticRefactoringKinds.inc" 126 using namespace diag;
140 #define CATEGORY(NAME, PREV) \ 141 if (DiagID > DIAG_START_##NAME) { \ 142 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \ 143 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \ 159 if (ID + Offset >= StaticDiagInfoSize)
162 assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize);
164 const StaticDiagInfoRec *Found = &StaticDiagInfo[ID +
Offset];
168 if (Found->DiagID != DiagID)
177 if (
const StaticDiagInfoRec *StaticInfo =
GetDiagInfo(DiagID)) {
180 if (StaticInfo->WarnNoWerror) {
182 "Unexpected mapping with no-Werror bit!");
193 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
194 return Info->Category;
200 struct StaticDiagCategoryRec {
204 StringRef getName()
const {
205 return StringRef(NameStr, NameLen);
215 std::pair<iterator, bool>
Result =
222 return Result.first->second;
226 #define GET_CATEGORY_TABLE 227 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, 228 #include "clang/Basic/DiagnosticGroups.inc" 229 #undef GET_CATEGORY_TABLE 235 return llvm::array_lengthof(CategoryNameTable) - 1;
242 if (CategoryID >= getNumberOfCategories())
244 return CategoryNameTable[CategoryID].getName();
251 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
253 return SFINAE_Report;
259 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
271 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
272 std::vector<DiagDesc> DiagInfo;
273 std::map<DiagDesc, unsigned> DiagIDs;
280 "Invalid diagnostic ID");
287 "Invalid diagnostic ID");
293 DiagDesc D(L, Message);
295 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
296 if (I != DiagIDs.end() && I->first == D)
301 DiagIDs.insert(std::make_pair(D,
ID));
302 DiagInfo.push_back(D);
318 delete CustomDiagInfo;
330 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *
this);
356 bool &EnabledByDefault) {
376 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
377 return Info->getDescription();
378 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
379 return CustomDiagInfo->getDescription(DiagID);
395 llvm_unreachable(
"unexpected severity");
402 DiagnosticIDs::getDiagnosticLevel(
unsigned DiagID,
SourceLocation Loc,
406 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
407 return CustomDiagInfo->getLevel(DiagID);
412 return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
422 DiagnosticIDs::getDiagnosticSeverity(
unsigned DiagID,
SourceLocation Loc,
431 DiagnosticsEngine::DiagState *
State = Diag.GetDiagStateForLoc(Loc);
446 bool EnabledByDefault =
false;
447 bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
448 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
453 if (IsExtensionDiag && !Mapping.
isUser())
454 Result =
std::max(Result, State->ExtBehavior);
481 bool ShowInSystemHeader =
487 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.
isValid() &&
495 #define GET_DIAG_ARRAYS 496 #include "clang/Basic/DiagnosticGroups.inc" 497 #undef GET_DIAG_ARRAYS 500 struct WarningOption {
506 StringRef getName()
const {
507 return StringRef(DiagGroupNames + NameOffset + 1,
508 DiagGroupNames[NameOffset]);
515 #define GET_DIAG_TABLE 516 #include "clang/Basic/DiagnosticGroups.inc" 517 #undef GET_DIAG_TABLE 524 if (
const StaticDiagInfoRec *Info =
GetDiagInfo(DiagID))
525 return OptionTable[Info->getOptionGroupIndex()].getName();
530 std::vector<std::string> Res;
531 for (
size_t I = 1; DiagGroupNames[I] !=
'\0';) {
532 std::string
Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
533 I += DiagGroupNames[I] + 1;
534 Res.push_back(
"-W" + Diag);
535 Res.push_back(
"-Wno-" + Diag);
544 const WarningOption *Group,
548 if (!Group->Members && !Group->SubGroups)
551 bool NotFound =
true;
554 const int16_t *Member = DiagArrays + Group->Members;
555 for (; *Member != -1; ++Member) {
558 Diags.push_back(*Member);
563 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
564 for (; *SubGroups != (int16_t)-1; ++SubGroups)
574 auto Found = std::lower_bound(std::begin(OptionTable), std::end(OptionTable),
576 [](
const WarningOption &LHS, StringRef RHS) {
577 return LHS.getName() < RHS;
579 if (Found == std::end(OptionTable) || Found->getName() != Group)
586 std::vector<diag::kind> &Diags) {
588 if (StaticDiagInfo[i].getFlavor() == Flavor)
589 Diags.push_back(StaticDiagInfo[i].DiagID);
595 unsigned BestDistance = Group.size() + 1;
596 for (
const WarningOption &O : OptionTable) {
598 if (!O.Members && !O.SubGroups)
601 unsigned Distance = O.getName().edit_distance(Group,
true, BestDistance);
602 if (Distance > BestDistance)
610 if (Distance == BestDistance) {
613 }
else if (Distance < BestDistance) {
616 BestDistance = Distance;
628 assert(Diag.
getClient() &&
"DiagnosticClient not set!");
631 unsigned DiagID = Info.
getID();
638 ++Diag.TrapNumErrorsOccurred;
639 if (isUnrecoverable(DiagID))
640 ++Diag.TrapNumUnrecoverableErrorsOccurred;
643 if (Diag.SuppressAllDiagnostics)
652 Diag.FatalErrorOccurred =
true;
654 Diag.LastDiagLevel = DiagLevel;
659 if (Diag.FatalErrorOccurred && Diag.SuppressAfterFatalError) {
676 if (isUnrecoverable(DiagID))
677 Diag.UnrecoverableErrorOccurred =
true;
680 if (isDefaultMappingAsError(DiagID))
681 Diag.UncompilableErrorOccurred =
true;
683 Diag.ErrorOccurred =
true;
690 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
699 if (Diag.CurDiagID == diag::fatal_too_many_errors)
700 Diag.FatalErrorOccurred =
true;
702 EmitDiag(Diag, DiagLevel);
716 Diag.CurDiagID = ~0U;
719 bool DiagnosticIDs::isUnrecoverable(
unsigned DiagID)
const {
721 assert(CustomDiagInfo &&
"Invalid CustomDiagInfo");
730 if (DiagID == diag::err_unavailable ||
731 DiagID == diag::err_unavailable_message)
735 if (isARCDiagnostic(DiagID))
742 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...
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.
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)
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
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