summaryrefslogtreecommitdiffstats
path: root/clang/lib/Basic/DiagnosticIDs.cpp
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2010-12-15 18:44:22 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2010-12-15 18:44:22 +0000
commit1cb0de1d4cf4fd537e41524ce416fe11dce27812 (patch)
tree1abc5819382600405d63c3c9f56ae3f331ce85e2 /clang/lib/Basic/DiagnosticIDs.cpp
parent1066ef6b24ff46428fd67d7713f825a8d1d5bc87 (diff)
downloadbcm5719-llvm-1cb0de1d4cf4fd537e41524ce416fe11dce27812.tar.gz
bcm5719-llvm-1cb0de1d4cf4fd537e41524ce416fe11dce27812.zip
Fix diagnostic pragmas.
Diagnostic pragmas are broken because we don't keep track of the diagnostic state changes and we only check the current/latest state. Problems manifest if a diagnostic is emitted for a source line that has different diagnostic state than the current state; this can affect a lot of places, like C++ inline methods, template instantiations, the lexer, etc. Fix the issue by having the Diagnostic object keep track of the source location of the pragmas so that it is able to know what is the diagnostic state at any given source location. Fixes rdar://8365684. llvm-svn: 121873
Diffstat (limited to 'clang/lib/Basic/DiagnosticIDs.cpp')
-rw-r--r--clang/lib/Basic/DiagnosticIDs.cpp46
1 files changed, 34 insertions, 12 deletions
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index 5d5bf7b72a2..29a8d9270a9 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -282,32 +282,42 @@ const char *DiagnosticIDs::getDescription(unsigned DiagID) const {
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
-DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID,
- const Diagnostic &Diag) const {
+DiagnosticIDs::Level
+DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
+ const Diagnostic &Diag) const {
// Handle custom diagnostics, which cannot be mapped.
if (DiagID >= diag::DIAG_UPPER_LIMIT)
return CustomDiagInfo->getLevel(DiagID);
unsigned DiagClass = getBuiltinDiagClass(DiagID);
assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
- return getDiagnosticLevel(DiagID, DiagClass, Diag);
+ return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag);
}
-/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
+/// \brief Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
+///
+/// \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,
- const Diagnostic &Diag) const {
+ SourceLocation Loc,
+ const Diagnostic &Diag) const {
// 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;
+ Diagnostic::DiagStatePointsTy::iterator
+ Pos = Diag.GetDiagStatePointForLoc(Loc);
+ Diagnostic::DiagState *State = Pos->State;
+
// Get the mapping information, if unset, compute it lazily.
- unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID);
+ unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID,
+ State);
if (MappingInfo == 0) {
MappingInfo = GetDefaultDiagMapping(DiagID);
- Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, false);
+ Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, State, false);
}
switch (MappingInfo & 7) {
@@ -404,17 +414,17 @@ static bool WarningOptionCompare(const WarningOption &LHS,
}
static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
- Diagnostic &Diag) {
+ SourceLocation Loc, Diagnostic &Diag) {
// Option exists, poke all the members of its diagnostic set.
if (const short *Member = Group->Members) {
for (; *Member != -1; ++Member)
- Diag.setDiagnosticMapping(*Member, Mapping);
+ Diag.setDiagnosticMapping(*Member, Mapping, Loc);
}
// Enable/disable all subgroups along with this one.
if (const short *SubGroups = Group->SubGroups) {
for (; *SubGroups != (short)-1; ++SubGroups)
- MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Diag);
+ MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Loc, Diag);
}
}
@@ -423,7 +433,18 @@ static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
/// ignores the request if "Group" was unknown, false otherwise.
bool DiagnosticIDs::setDiagnosticGroupMapping(const char *Group,
diag::Mapping Map,
+ SourceLocation Loc,
Diagnostic &Diag) const {
+ assert((Loc.isValid() ||
+ Diag.DiagStatePoints.empty() ||
+ Diag.DiagStatePoints.back().Loc.isInvalid()) &&
+ "Loc should be invalid only when the mapping comes from command-line");
+ assert((Loc.isInvalid() || Diag.DiagStatePoints.empty() ||
+ Diag.DiagStatePoints.back().Loc.isInvalid() ||
+ !Diag.SourceMgr->isBeforeInTranslationUnit(Loc,
+ Diag.DiagStatePoints.back().Loc)) &&
+ "Source location of new mapping is before the previous one!");
+
WarningOption Key = { Group, 0, 0 };
const WarningOption *Found =
std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
@@ -432,7 +453,7 @@ bool DiagnosticIDs::setDiagnosticGroupMapping(const char *Group,
strcmp(Found->Name, Group) != 0)
return true; // Option not found.
- MapGroupMembers(Found, Map, Diag);
+ MapGroupMembers(Found, Map, Loc, Diag);
return false;
}
@@ -475,7 +496,8 @@ bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const {
// *map* warnings/extensions to errors.
ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR;
- DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Diag);
+ DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(),
+ Diag);
}
}
OpenPOWER on IntegriCloud