aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Basic/DiagnosticIDs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Basic/DiagnosticIDs.cpp')
-rw-r--r--clang/lib/Basic/DiagnosticIDs.cpp280
1 files changed, 117 insertions, 163 deletions
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index 031d9d7..d45bb0f 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -102,12 +102,13 @@ const uint32_t StaticDiagInfoDescriptionOffsets[] = {
#undef DIAG
};
+// Diagnostic classes.
enum DiagnosticClass {
- CLASS_NOTE = DiagnosticIDs::CLASS_NOTE,
- CLASS_REMARK = DiagnosticIDs::CLASS_REMARK,
- CLASS_WARNING = DiagnosticIDs::CLASS_WARNING,
- CLASS_EXTENSION = DiagnosticIDs::CLASS_EXTENSION,
- CLASS_ERROR = DiagnosticIDs::CLASS_ERROR,
+ CLASS_NOTE = 0x01,
+ CLASS_REMARK = 0x02,
+ CLASS_WARNING = 0x03,
+ CLASS_EXTENSION = 0x04,
+ CLASS_ERROR = 0x05
};
struct StaticDiagInfoRec {
@@ -268,60 +269,11 @@ CATEGORY(INSTALLAPI, REFACTORING)
return Found;
}
-//===----------------------------------------------------------------------===//
-// Custom Diagnostic information
-//===----------------------------------------------------------------------===//
-
-namespace clang {
-namespace diag {
-using CustomDiagDesc = DiagnosticIDs::CustomDiagDesc;
-class CustomDiagInfo {
- std::vector<CustomDiagDesc> DiagInfo;
- std::map<CustomDiagDesc, unsigned> DiagIDs;
- std::map<diag::Group, std::vector<unsigned>> GroupToDiags;
-
-public:
- /// getDescription - Return the description of the specified custom
- /// diagnostic.
- const CustomDiagDesc &getDescription(unsigned DiagID) const {
- assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
- "Invalid diagnostic ID");
- return DiagInfo[DiagID - DIAG_UPPER_LIMIT];
- }
-
- unsigned getOrCreateDiagID(DiagnosticIDs::CustomDiagDesc D) {
- // Check to see if it already exists.
- std::map<CustomDiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
- if (I != DiagIDs.end() && I->first == D)
- return I->second;
-
- // If not, assign a new ID.
- unsigned ID = DiagInfo.size() + DIAG_UPPER_LIMIT;
- DiagIDs.insert(std::make_pair(D, ID));
- DiagInfo.push_back(D);
- if (auto Group = D.GetGroup())
- GroupToDiags[*Group].emplace_back(ID);
- return ID;
- }
-
- ArrayRef<unsigned> getDiagsInGroup(diag::Group G) const {
- if (auto Diags = GroupToDiags.find(G); Diags != GroupToDiags.end())
- return Diags->second;
- return {};
- }
-};
-
-} // namespace diag
-} // namespace clang
-
-DiagnosticMapping DiagnosticIDs::getDefaultMapping(unsigned DiagID) const {
+DiagnosticMapping DiagnosticIDs::getDefaultMapping(unsigned DiagID) {
DiagnosticMapping Info = DiagnosticMapping::Make(
diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false);
- if (IsCustomDiag(DiagID)) {
- Info.setSeverity(
- CustomDiagInfo->getDescription(DiagID).GetDefaultSeverity());
- } else if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) {
+ if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) {
Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity);
if (StaticInfo->WarnNoWerror) {
@@ -334,18 +286,6 @@ DiagnosticMapping DiagnosticIDs::getDefaultMapping(unsigned DiagID) const {
return Info;
}
-void DiagnosticIDs::initCustomDiagMapping(DiagnosticMapping &Mapping,
- unsigned DiagID) {
- assert(IsCustomDiag(DiagID));
- const auto &Diag = CustomDiagInfo->getDescription(DiagID);
- if (auto Group = Diag.GetGroup()) {
- GroupInfo GroupInfo = GroupInfos[static_cast<size_t>(*Group)];
- if (static_cast<diag::Severity>(GroupInfo.Severity) != diag::Severity())
- Mapping.setSeverity(static_cast<diag::Severity>(GroupInfo.Severity));
- Mapping.setNoWarningAsError(GroupInfo.HasNoWarningAsError);
- }
-}
-
/// getCategoryNumberForDiag - Return the category number that a specified
/// DiagID belongs to, or 0 if no category.
unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
@@ -403,6 +343,61 @@ bool DiagnosticIDs::isDeferrable(unsigned DiagID) {
return false;
}
+/// getBuiltinDiagClass - Return the class field of the diagnostic.
+///
+static unsigned getBuiltinDiagClass(unsigned DiagID) {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->Class;
+ return ~0U;
+}
+
+//===----------------------------------------------------------------------===//
+// Custom Diagnostic information
+//===----------------------------------------------------------------------===//
+
+namespace clang {
+ namespace diag {
+ class CustomDiagInfo {
+ typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
+ std::vector<DiagDesc> DiagInfo;
+ std::map<DiagDesc, unsigned> DiagIDs;
+ public:
+
+ /// getDescription - Return the description of the specified custom
+ /// diagnostic.
+ StringRef getDescription(unsigned DiagID) const {
+ assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
+ "Invalid diagnostic ID");
+ return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
+ }
+
+ /// getLevel - Return the level of the specified custom diagnostic.
+ DiagnosticIDs::Level getLevel(unsigned DiagID) const {
+ assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
+ "Invalid diagnostic ID");
+ return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
+ }
+
+ unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
+ DiagnosticIDs &Diags) {
+ DiagDesc D(L, std::string(Message));
+ // Check to see if it already exists.
+ std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
+ if (I != DiagIDs.end() && I->first == D)
+ return I->second;
+
+ // If not, assign a new ID.
+ unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
+ DiagIDs.insert(std::make_pair(D, ID));
+ DiagInfo.push_back(D);
+ return ID;
+ }
+ };
+
+ } // end diag namespace
+} // end clang namespace
+
+
//===----------------------------------------------------------------------===//
// Common Diagnostic implementation
//===----------------------------------------------------------------------===//
@@ -417,32 +412,38 @@ DiagnosticIDs::~DiagnosticIDs() {}
///
/// \param FormatString A fixed diagnostic format string that will be hashed and
/// mapped to a unique DiagID.
-unsigned DiagnosticIDs::getCustomDiagID(CustomDiagDesc Diag) {
+unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
if (!CustomDiagInfo)
CustomDiagInfo.reset(new diag::CustomDiagInfo());
- return CustomDiagInfo->getOrCreateDiagID(Diag);
+ return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
}
-bool DiagnosticIDs::isWarningOrExtension(unsigned DiagID) const {
- return DiagID < diag::DIAG_UPPER_LIMIT
- ? getDiagClass(DiagID) != CLASS_ERROR
- : CustomDiagInfo->getDescription(DiagID).GetClass() != CLASS_ERROR;
+
+/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
+/// level of the specified diagnostic ID is a Warning or Extension.
+/// This only works on builtin diagnostics, not custom ones, and is not legal to
+/// call on NOTEs.
+bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
+ return DiagID < diag::DIAG_UPPER_LIMIT &&
+ getBuiltinDiagClass(DiagID) != CLASS_ERROR;
}
/// Determine whether the given built-in diagnostic ID is a
/// Note.
-bool DiagnosticIDs::isNote(unsigned DiagID) const {
- return DiagID < diag::DIAG_UPPER_LIMIT && getDiagClass(DiagID) == CLASS_NOTE;
+bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
+ return DiagID < diag::DIAG_UPPER_LIMIT &&
+ getBuiltinDiagClass(DiagID) == CLASS_NOTE;
}
-/// isExtensionDiag - Determine whether the given built-in diagnostic
+/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
/// ID is for an extension of some sort. This also returns EnabledByDefault,
/// which is set to indicate whether the diagnostic is ignored by default (in
/// which case -pedantic enables it) or treated as a warning/error by default.
///
-bool DiagnosticIDs::isExtensionDiag(unsigned DiagID,
- bool &EnabledByDefault) const {
- if (IsCustomDiag(DiagID) || getDiagClass(DiagID) != CLASS_EXTENSION)
+bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
+ bool &EnabledByDefault) {
+ if (DiagID >= diag::DIAG_UPPER_LIMIT ||
+ getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
return false;
EnabledByDefault =
@@ -450,7 +451,10 @@ bool DiagnosticIDs::isExtensionDiag(unsigned DiagID,
return true;
}
-bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) const {
+bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
+ if (DiagID >= diag::DIAG_UPPER_LIMIT)
+ return false;
+
return getDefaultMapping(DiagID).getSeverity() >= diag::Severity::Error;
}
@@ -460,7 +464,7 @@ StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->getDescription();
assert(CustomDiagInfo && "Invalid CustomDiagInfo");
- return CustomDiagInfo->getDescription(DiagID).GetDescription();
+ return CustomDiagInfo->getDescription(DiagID);
}
static DiagnosticIDs::Level toLevel(diag::Severity SV) {
@@ -485,7 +489,13 @@ static DiagnosticIDs::Level toLevel(diag::Severity SV) {
DiagnosticIDs::Level
DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
const DiagnosticsEngine &Diag) const {
- unsigned DiagClass = getDiagClass(DiagID);
+ // Handle custom diagnostics, which cannot be mapped.
+ if (DiagID >= diag::DIAG_UPPER_LIMIT) {
+ assert(CustomDiagInfo && "Invalid CustomDiagInfo");
+ return CustomDiagInfo->getLevel(DiagID);
+ }
+
+ unsigned DiagClass = getBuiltinDiagClass(DiagID);
if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note;
return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
}
@@ -499,8 +509,7 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
diag::Severity
DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
const DiagnosticsEngine &Diag) const {
- bool IsCustomDiag = DiagnosticIDs::IsCustomDiag(DiagID);
- assert(getDiagClass(DiagID) != CLASS_NOTE);
+ assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE);
// Specific non-error diagnostics may be mapped to various levels from ignored
// to error. Errors can only be mapped to fatal.
@@ -508,7 +517,7 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
// Get the mapping information, or compute it lazily.
DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc);
- DiagnosticMapping Mapping = State->getOrAddMapping((diag::kind)DiagID);
+ DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID);
// TODO: Can a null severity really get here?
if (Mapping.getSeverity() != diag::Severity())
@@ -516,15 +525,14 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
// Upgrade ignored diagnostics if -Weverything is enabled.
if (State->EnableAllWarnings && Result == diag::Severity::Ignored &&
- !Mapping.isUser() &&
- (IsCustomDiag || getDiagClass(DiagID) != CLASS_REMARK))
+ !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK)
Result = diag::Severity::Warning;
// Ignore -pedantic diagnostics inside __extension__ blocks.
// (The diagnostics controlled by -pedantic are the extension diagnostics
// that are not enabled by default.)
bool EnabledByDefault = false;
- bool IsExtensionDiag = isExtensionDiag(DiagID, EnabledByDefault);
+ bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
return diag::Severity::Ignored;
@@ -542,12 +550,10 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
// as well as disabling all messages which are currently mapped to Warning
// (whether by default or downgraded from Error via e.g. -Wno-error or #pragma
// diagnostic.)
- // FIXME: Should -w be ignored for custom warnings without a group?
if (State->IgnoreAllWarnings) {
- if ((!IsCustomDiag || CustomDiagInfo->getDescription(DiagID).GetGroup()) &&
- (Result == diag::Severity::Warning ||
- (Result >= diag::Severity::Error &&
- !isDefaultMappingAsError((diag::kind)DiagID))))
+ if (Result == diag::Severity::Warning ||
+ (Result >= diag::Severity::Error &&
+ !isDefaultMappingAsError((diag::kind)DiagID)))
return diag::Severity::Ignored;
}
@@ -569,10 +575,9 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
DiagID != diag::fatal_too_many_errors && Diag.FatalsAsError)
Result = diag::Severity::Error;
+ // Custom diagnostics always are emitted in system headers.
bool ShowInSystemHeader =
- IsCustomDiag
- ? CustomDiagInfo->getDescription(DiagID).ShouldShowInSystemHeader()
- : !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
+ !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
// If we are in a system header, we ignore it. We look at the diagnostic class
// because we also want to ignore extensions and warnings in -Werror and
@@ -592,15 +597,6 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
return Result;
}
-DiagnosticIDs::Class DiagnosticIDs::getDiagClass(unsigned DiagID) const {
- if (IsCustomDiag(DiagID))
- return Class(CustomDiagInfo->getDescription(DiagID).GetClass());
-
- if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
- return Class(Info->Class);
- return CLASS_INVALID;
-}
-
#define GET_DIAG_ARRAYS
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_DIAG_ARRAYS
@@ -646,12 +642,7 @@ DiagnosticIDs::getGroupForWarningOption(StringRef Name) {
return static_cast<diag::Group>(Found - OptionTable);
}
-std::optional<diag::Group>
-DiagnosticIDs::getGroupForDiag(unsigned DiagID) const {
- if (IsCustomDiag(DiagID)) {
- assert(CustomDiagInfo);
- return CustomDiagInfo->getDescription(DiagID).GetGroup();
- }
+std::optional<diag::Group> DiagnosticIDs::getGroupForDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return static_cast<diag::Group>(Info->getOptionGroupIndex());
return std::nullopt;
@@ -682,8 +673,7 @@ std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() {
/// were filtered out due to having the wrong flavor.
static bool getDiagnosticsInGroup(diag::Flavor Flavor,
const WarningOption *Group,
- SmallVectorImpl<diag::kind> &Diags,
- diag::CustomDiagInfo *CustomDiagInfo) {
+ SmallVectorImpl<diag::kind> &Diags) {
// An empty group is considered to be a warning group: we have empty groups
// for GCC compatibility, and GCC does not have remarks.
if (!Group->Members && !Group->SubGroups)
@@ -702,14 +692,9 @@ static bool getDiagnosticsInGroup(diag::Flavor Flavor,
// Add the members of the subgroups.
const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
- for (; *SubGroups != (int16_t)-1; ++SubGroups) {
- if (CustomDiagInfo)
- llvm::copy(
- CustomDiagInfo->getDiagsInGroup(static_cast<diag::Group>(*SubGroups)),
- std::back_inserter(Diags));
+ for (; *SubGroups != (int16_t)-1; ++SubGroups)
NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
- Diags, CustomDiagInfo);
- }
+ Diags);
return NotFound;
}
@@ -717,49 +702,12 @@ static bool getDiagnosticsInGroup(diag::Flavor Flavor,
bool
DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
SmallVectorImpl<diag::kind> &Diags) const {
- if (std::optional<diag::Group> G = getGroupForWarningOption(Group)) {
- if (CustomDiagInfo)
- llvm::copy(CustomDiagInfo->getDiagsInGroup(*G),
- std::back_inserter(Diags));
- return ::getDiagnosticsInGroup(Flavor,
- &OptionTable[static_cast<unsigned>(*G)],
- Diags, CustomDiagInfo.get());
- }
+ if (std::optional<diag::Group> G = getGroupForWarningOption(Group))
+ return ::getDiagnosticsInGroup(
+ Flavor, &OptionTable[static_cast<unsigned>(*G)], Diags);
return true;
}
-template <class Func>
-static void forEachSubGroupImpl(const WarningOption *Group, Func func) {
- for (const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
- *SubGroups != -1; ++SubGroups) {
- func(static_cast<size_t>(*SubGroups));
- forEachSubGroupImpl(&OptionTable[*SubGroups], std::move(func));
- }
-}
-
-template <class Func>
-static void forEachSubGroup(diag::Group Group, Func func) {
- const WarningOption *WarningOpt = &OptionTable[static_cast<size_t>(Group)];
- func(static_cast<size_t>(Group));
- ::forEachSubGroupImpl(WarningOpt, std::move(func));
-}
-
-void DiagnosticIDs::setGroupSeverity(StringRef Group, diag::Severity Sev) {
- if (std::optional<diag::Group> G = getGroupForWarningOption(Group)) {
- ::forEachSubGroup(*G, [&](size_t SubGroup) {
- GroupInfos[SubGroup].Severity = static_cast<unsigned>(Sev);
- });
- }
-}
-
-void DiagnosticIDs::setGroupNoWarningsAsError(StringRef Group, bool Val) {
- if (std::optional<diag::Group> G = getGroupForWarningOption(Group)) {
- ::forEachSubGroup(*G, [&](size_t SubGroup) {
- GroupInfos[static_cast<size_t>(*G)].HasNoWarningAsError = Val;
- });
- }
-}
-
void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
std::vector<diag::kind> &Diags) {
for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
@@ -782,7 +730,7 @@ StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
// Don't suggest groups that are not of this kind.
llvm::SmallVector<diag::kind, 8> Diags;
- if (::getDiagnosticsInGroup(Flavor, &O, Diags, nullptr) || Diags.empty())
+ if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty())
continue;
if (Distance == BestDistance) {
@@ -896,8 +844,14 @@ void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag,
}
bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
+ if (DiagID >= diag::DIAG_UPPER_LIMIT) {
+ assert(CustomDiagInfo && "Invalid CustomDiagInfo");
+ // Custom diagnostics.
+ return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
+ }
+
// Only errors may be unrecoverable.
- if (getDiagClass(DiagID) < CLASS_ERROR)
+ if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
return false;
if (DiagID == diag::err_unavailable ||