summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp268
1 files changed, 147 insertions, 121 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
index 9d99fbe..ec244cc 100644
--- a/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/contrib/llvm/tools/clang/lib/Basic/DiagnosticIDs.cpp
@@ -15,8 +15,8 @@
#include "clang/Basic/AllDiagnostics.h"
#include "clang/Basic/DiagnosticCategories.h"
#include "clang/Basic/SourceManager.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ErrorHandling.h"
#include <map>
using namespace clang;
@@ -30,14 +30,15 @@ namespace {
// Diagnostic classes.
enum {
CLASS_NOTE = 0x01,
- CLASS_WARNING = 0x02,
- CLASS_EXTENSION = 0x03,
- CLASS_ERROR = 0x04
+ CLASS_REMARK = 0x02,
+ CLASS_WARNING = 0x03,
+ CLASS_EXTENSION = 0x04,
+ CLASS_ERROR = 0x05
};
struct StaticDiagInfoRec {
uint16_t DiagID;
- unsigned Mapping : 3;
+ unsigned DefaultSeverity : 3;
unsigned Class : 3;
unsigned SFINAE : 2;
unsigned WarnNoWerror : 1;
@@ -57,6 +58,11 @@ struct StaticDiagInfoRec {
return StringRef(DescriptionStr, DescriptionLen);
}
+ diag::Flavor getFlavor() const {
+ return Class == CLASS_REMARK ? diag::Flavor::Remark
+ : diag::Flavor::WarningOrError;
+ }
+
bool operator<(const StaticDiagInfoRec &RHS) const {
return DiagID < RHS.DiagID;
}
@@ -65,12 +71,13 @@ struct StaticDiagInfoRec {
} // namespace anonymous
static const StaticDiagInfoRec StaticDiagInfo[] = {
-#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP, \
- SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) \
- { diag::ENUM, DEFAULT_MAPPING, CLASS, \
- DiagnosticIDs::SFINAE, \
- NOWERROR, SHOWINSYSHEADER, CATEGORY, GROUP, \
- STR_SIZE(DESC, uint16_t), DESC },
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY) \
+ { \
+ diag::ENUM, DEFAULT_SEVERITY, CLASS, DiagnosticIDs::SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, CATEGORY, GROUP, STR_SIZE(DESC, uint16_t), DESC \
+ } \
+ ,
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticDriverKinds.inc"
#include "clang/Basic/DiagnosticFrontendKinds.inc"
@@ -108,10 +115,10 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
// Out of bounds diag. Can't be in the table.
using namespace diag;
if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
- return 0;
+ return nullptr;
// Compute the index of the requested diagnostic in the static table.
- // 1. Add the number of diagnostics in each category preceeding the
+ // 1. Add the number of diagnostics in each category preceding the
// diagnostic and of the category the diagnostic is in. This gives us
// the offset of the category in the table.
// 2. Subtract the number of IDs in each category from our ID. This gives us
@@ -138,7 +145,7 @@ CATEGORY(ANALYSIS, SEMA)
// Avoid out of bounds reads.
if (ID + Offset >= StaticDiagInfoSize)
- return 0;
+ return nullptr;
assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize);
@@ -147,28 +154,22 @@ CATEGORY(ANALYSIS, SEMA)
// happen when this function is called with an ID that points into a hole in
// the diagID space.
if (Found->DiagID != DiagID)
- return 0;
+ return nullptr;
return Found;
}
-static DiagnosticMappingInfo GetDefaultDiagMappingInfo(unsigned DiagID) {
- DiagnosticMappingInfo Info = DiagnosticMappingInfo::Make(
- diag::MAP_FATAL, /*IsUser=*/false, /*IsPragma=*/false);
+static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID) {
+ DiagnosticMapping Info = DiagnosticMapping::Make(
+ diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false);
if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) {
- Info.setMapping((diag::Mapping) StaticInfo->Mapping);
+ Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity);
if (StaticInfo->WarnNoWerror) {
- assert(Info.getMapping() == diag::MAP_WARNING &&
+ assert(Info.getSeverity() == diag::Severity::Warning &&
"Unexpected mapping with no-Werror bit!");
Info.setNoWarningAsError(true);
}
-
- if (StaticInfo->WarnShowInSystemHeader) {
- assert(Info.getMapping() == diag::MAP_WARNING &&
- "Unexpected mapping with show-in-system-header bit!");
- Info.setShowInSystemHeader(true);
- }
}
return Info;
@@ -197,15 +198,14 @@ namespace {
// Unfortunately, the split between DiagnosticIDs and Diagnostic is not
// particularly clean, but for now we just implement this method here so we can
// access GetDefaultDiagMapping.
-DiagnosticMappingInfo &DiagnosticsEngine::DiagState::getOrAddMappingInfo(
- diag::kind Diag)
-{
- std::pair<iterator, bool> Result = DiagMap.insert(
- std::make_pair(Diag, DiagnosticMappingInfo()));
+DiagnosticMapping &
+DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) {
+ std::pair<iterator, bool> Result =
+ DiagMap.insert(std::make_pair(Diag, DiagnosticMapping()));
// Initialize the entry if we added it.
if (Result.second)
- Result.first->second = GetDefaultDiagMappingInfo(Diag);
+ Result.first->second = GetDefaultDiagMapping(Diag);
return Result.first->second;
}
@@ -215,7 +215,7 @@ static const StaticDiagCategoryRec CategoryNameTable[] = {
#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_CATEGORY_TABLE
- { 0, 0 }
+ { nullptr, 0 }
};
/// getNumberOfCategories - Return the number of categories
@@ -264,14 +264,14 @@ namespace clang {
/// getDescription - Return the description of the specified custom
/// diagnostic.
StringRef getDescription(unsigned DiagID) const {
- assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
+ 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(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
+ assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnostic ID");
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
}
@@ -300,9 +300,7 @@ namespace clang {
// Common Diagnostic implementation
//===----------------------------------------------------------------------===//
-DiagnosticIDs::DiagnosticIDs() {
- CustomDiagInfo = 0;
-}
+DiagnosticIDs::DiagnosticIDs() { CustomDiagInfo = nullptr; }
DiagnosticIDs::~DiagnosticIDs() {
delete CustomDiagInfo;
@@ -311,10 +309,13 @@ DiagnosticIDs::~DiagnosticIDs() {
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnostic, it is
/// registered and created, otherwise the existing ID is returned.
-unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef Message) {
- if (CustomDiagInfo == 0)
+///
+/// \param FormatString A fixed diagnostic format string that will be hashed and
+/// mapped to a unique DiagID.
+unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
+ if (!CustomDiagInfo)
CustomDiagInfo = new diag::CustomDiagInfo();
- return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
+ return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
}
@@ -344,9 +345,9 @@ bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
if (DiagID >= diag::DIAG_UPPER_LIMIT ||
getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
return false;
-
+
EnabledByDefault =
- GetDefaultDiagMappingInfo(DiagID).getMapping() != diag::MAP_IGNORE;
+ GetDefaultDiagMapping(DiagID).getSeverity() != diag::Severity::Ignored;
return true;
}
@@ -354,7 +355,7 @@ bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
if (DiagID >= diag::DIAG_UPPER_LIMIT)
return false;
- return GetDefaultDiagMappingInfo(DiagID).getMapping() == diag::MAP_ERROR;
+ return GetDefaultDiagMapping(DiagID).getSeverity() == diag::Severity::Error;
}
/// getDescription - Given a diagnostic ID, return a description of the
@@ -362,9 +363,26 @@ bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->getDescription();
+ assert(CustomDiagInfo && "Invalid CustomDiagInfo");
return CustomDiagInfo->getDescription(DiagID);
}
+static DiagnosticIDs::Level toLevel(diag::Severity SV) {
+ switch (SV) {
+ case diag::Severity::Ignored:
+ return DiagnosticIDs::Ignored;
+ case diag::Severity::Remark:
+ return DiagnosticIDs::Remark;
+ case diag::Severity::Warning:
+ return DiagnosticIDs::Warning;
+ case diag::Severity::Error:
+ return DiagnosticIDs::Error;
+ case diag::Severity::Fatal:
+ return DiagnosticIDs::Fatal;
+ }
+ llvm_unreachable("unexpected severity");
+}
+
/// getDiagnosticLevel - Based on the way the client configured the
/// DiagnosticsEngine object, classify the specified diagnostic ID into a Level,
/// by consumable the DiagnosticClient.
@@ -372,12 +390,14 @@ DiagnosticIDs::Level
DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
const DiagnosticsEngine &Diag) const {
// Handle custom diagnostics, which cannot be mapped.
- if (DiagID >= diag::DIAG_UPPER_LIMIT)
+ 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 getDiagnosticLevel(DiagID, DiagClass, Loc, Diag);
+ return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
}
/// \brief Based on the way the client configured the Diagnostic
@@ -386,41 +406,37 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
///
/// \param Loc The source location we are interested in finding out the
/// diagnostic state. Can be null in order to query the latest state.
-DiagnosticIDs::Level
-DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
- SourceLocation Loc,
- const DiagnosticsEngine &Diag) const {
+diag::Severity
+DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
+ const DiagnosticsEngine &Diag) const {
+ 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.
- DiagnosticIDs::Level Result = DiagnosticIDs::Fatal;
+ diag::Severity Result = diag::Severity::Fatal;
DiagnosticsEngine::DiagStatePointsTy::iterator
Pos = Diag.GetDiagStatePointForLoc(Loc);
DiagnosticsEngine::DiagState *State = Pos->State;
// Get the mapping information, or compute it lazily.
- DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo(
- (diag::kind)DiagID);
-
- switch (MappingInfo.getMapping()) {
- case diag::MAP_IGNORE:
- Result = DiagnosticIDs::Ignored;
- break;
- case diag::MAP_WARNING:
- Result = DiagnosticIDs::Warning;
- break;
- case diag::MAP_ERROR:
- Result = DiagnosticIDs::Error;
- break;
- case diag::MAP_FATAL:
- Result = DiagnosticIDs::Fatal;
- break;
- }
+ DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID);
+
+ // TODO: Can a null severity really get here?
+ if (Mapping.getSeverity() != diag::Severity())
+ Result = Mapping.getSeverity();
// Upgrade ignored diagnostics if -Weverything is enabled.
- if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored &&
- !MappingInfo.isUser())
- Result = DiagnosticIDs::Warning;
+ if (Diag.EnableAllWarnings && Result == diag::Severity::Ignored &&
+ !Mapping.isUser())
+ Result = diag::Severity::Warning;
+
+ // Diagnostics of class REMARK are either printed as remarks or in case they
+ // have been added to -Werror they are printed as errors.
+ // FIXME: Disregarding user-requested remark mappings like this is bogus.
+ if (Result == diag::Severity::Warning &&
+ getBuiltinDiagClass(DiagID) == CLASS_REMARK)
+ Result = diag::Severity::Remark;
// Ignore -pedantic diagnostics inside __extension__ blocks.
// (The diagnostics controlled by -pedantic are the extension diagnostics
@@ -428,62 +444,46 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
bool EnabledByDefault = false;
bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
- return DiagnosticIDs::Ignored;
+ return diag::Severity::Ignored;
// For extension diagnostics that haven't been explicitly mapped, check if we
// should upgrade the diagnostic.
- if (IsExtensionDiag && !MappingInfo.isUser()) {
- switch (Diag.ExtBehavior) {
- case DiagnosticsEngine::Ext_Ignore:
- break;
- case DiagnosticsEngine::Ext_Warn:
- // Upgrade ignored diagnostics to warnings.
- if (Result == DiagnosticIDs::Ignored)
- Result = DiagnosticIDs::Warning;
- break;
- case DiagnosticsEngine::Ext_Error:
- // Upgrade ignored or warning diagnostics to errors.
- if (Result == DiagnosticIDs::Ignored || Result == DiagnosticIDs::Warning)
- Result = DiagnosticIDs::Error;
- break;
- }
- }
+ if (IsExtensionDiag && !Mapping.isUser())
+ Result = std::max(Result, Diag.ExtBehavior);
// At this point, ignored errors can no longer be upgraded.
- if (Result == DiagnosticIDs::Ignored)
+ if (Result == diag::Severity::Ignored)
return Result;
// Honor -w, which is lower in priority than pedantic-errors, but higher than
// -Werror.
- if (Result == DiagnosticIDs::Warning && Diag.IgnoreAllWarnings)
- return DiagnosticIDs::Ignored;
+ if (Result == diag::Severity::Warning && Diag.IgnoreAllWarnings)
+ return diag::Severity::Ignored;
// If -Werror is enabled, map warnings to errors unless explicitly disabled.
- if (Result == DiagnosticIDs::Warning) {
- if (Diag.WarningsAsErrors && !MappingInfo.hasNoWarningAsError())
- Result = DiagnosticIDs::Error;
+ if (Result == diag::Severity::Warning) {
+ if (Diag.WarningsAsErrors && !Mapping.hasNoWarningAsError())
+ Result = diag::Severity::Error;
}
// If -Wfatal-errors is enabled, map errors to fatal unless explicity
// disabled.
- if (Result == DiagnosticIDs::Error) {
- if (Diag.ErrorsAsFatal && !MappingInfo.hasNoErrorAsFatal())
- Result = DiagnosticIDs::Fatal;
+ if (Result == diag::Severity::Error) {
+ if (Diag.ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())
+ Result = diag::Severity::Fatal;
}
+ // Custom diagnostics always are emitted in system headers.
+ bool ShowInSystemHeader =
+ !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
// -pedantic-errors modes, which *map* warnings/extensions to errors.
- if (Result >= DiagnosticIDs::Warning &&
- DiagClass != CLASS_ERROR &&
- // Custom diagnostics always are emitted in system headers.
- DiagID < diag::DIAG_UPPER_LIMIT &&
- !MappingInfo.hasShowInSystemHeader() &&
- Diag.SuppressSystemWarnings &&
- Loc.isValid() &&
+ if (Diag.SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&
Diag.getSourceManager().isInSystemHeader(
Diag.getSourceManager().getExpansionLoc(Loc)))
- return DiagnosticIDs::Ignored;
+ return diag::Severity::Ignored;
return Result;
}
@@ -527,40 +527,57 @@ StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
return StringRef();
}
-static void getDiagnosticsInGroup(const WarningOption *Group,
+/// Return \c true if any diagnostics were found in this group, even if they
+/// were filtered out due to having the wrong flavor.
+static bool getDiagnosticsInGroup(diag::Flavor Flavor,
+ const WarningOption *Group,
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)
+ return Flavor == diag::Flavor::Remark ? true : false;
+
+ bool NotFound = true;
+
// Add the members of the option diagnostic set.
const int16_t *Member = DiagArrays + Group->Members;
- for (; *Member != -1; ++Member)
- Diags.push_back(*Member);
+ for (; *Member != -1; ++Member) {
+ if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
+ NotFound = false;
+ Diags.push_back(*Member);
+ }
+ }
// Add the members of the subgroups.
const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
for (; *SubGroups != (int16_t)-1; ++SubGroups)
- getDiagnosticsInGroup(&OptionTable[(short)*SubGroups], Diags);
+ NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
+ Diags);
+
+ return NotFound;
}
-bool DiagnosticIDs::getDiagnosticsInGroup(
- StringRef Group,
- SmallVectorImpl<diag::kind> &Diags) const {
- const WarningOption *Found =
- std::lower_bound(OptionTable, OptionTable + OptionTableSize, Group,
- WarningOptionCompare);
+bool
+DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
+ SmallVectorImpl<diag::kind> &Diags) const {
+ const WarningOption *Found = std::lower_bound(
+ OptionTable, OptionTable + OptionTableSize, Group, WarningOptionCompare);
if (Found == OptionTable + OptionTableSize ||
Found->getName() != Group)
return true; // Option not found.
- ::getDiagnosticsInGroup(Found, Diags);
- return false;
+ return ::getDiagnosticsInGroup(Flavor, Found, Diags);
}
-void DiagnosticIDs::getAllDiagnostics(
- SmallVectorImpl<diag::kind> &Diags) const {
+void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
+ SmallVectorImpl<diag::kind> &Diags) const {
for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
- Diags.push_back(StaticDiagInfo[i].DiagID);
+ if (StaticDiagInfo[i].getFlavor() == Flavor)
+ Diags.push_back(StaticDiagInfo[i].DiagID);
}
-StringRef DiagnosticIDs::getNearestWarningOption(StringRef Group) {
+StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
+ StringRef Group) {
StringRef Best;
unsigned BestDistance = Group.size() + 1; // Sanity threshold.
for (const WarningOption *i = OptionTable, *e = OptionTable + OptionTableSize;
@@ -570,6 +587,14 @@ StringRef DiagnosticIDs::getNearestWarningOption(StringRef Group) {
continue;
unsigned Distance = i->getName().edit_distance(Group, true, BestDistance);
+ if (Distance > BestDistance)
+ continue;
+
+ // Don't suggest groups that are not of this kind.
+ llvm::SmallVector<diag::kind, 8> Diags;
+ if (::getDiagnosticsInGroup(Flavor, i, Diags) || Diags.empty())
+ continue;
+
if (Distance == BestDistance) {
// Two matches with the same distance, don't prefer one over the other.
Best = "";
@@ -677,6 +702,7 @@ void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
if (DiagID >= diag::DIAG_UPPER_LIMIT) {
+ assert(CustomDiagInfo && "Invalid CustomDiagInfo");
// Custom diagnostics.
return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
}
OpenPOWER on IntegriCloud