Basic/Diagnostics: Rewrite DiagnosticIDs::getDiagnosticLevel completely to be straighter line code, use the new DiagnosticMappingInfo flags, and eliminate the odd MAP_WARNING_NO_WERROR and friend mappings.

- This fixes a host of obscure bugs with regards to how warning mapping options composed with one another, and I believe makes the code substantially easier to read and reason about.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140770 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Daniel Dunbar 2011-09-29 01:58:05 +00:00
parent a5e41333b0
commit be1aa41027
7 changed files with 69 additions and 93 deletions

View File

@ -65,17 +65,7 @@ namespace clang {
MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
MAP_WARNING = 2, //< Map this diagnostic to a warning.
MAP_ERROR = 3, //< Map this diagnostic to an error.
MAP_FATAL = 4, //< Map this diagnostic to a fatal error.
/// Map this diagnostic to "warning", but make it immune to -Werror. This
/// happens when you specify -Wno-error=foo.
MAP_WARNING_NO_WERROR = 5,
/// Map this diagnostic to "warning", but make it immune to
/// -Wno-system-headers.
MAP_WARNING_SHOW_IN_SYSTEM_HEADER = 6,
/// Map this diagnostic to "error", but make it immune to -Wfatal-errors.
/// This happens for -Wno-fatal-errors=foo.
MAP_ERROR_NO_WFATAL = 7
MAP_FATAL = 4 //< Map this diagnostic to a fatal error.
};
}

View File

@ -257,7 +257,10 @@ bool DiagnosticsEngine::setDiagnosticGroupWarningAsError(StringRef Group,
DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo(
GroupDiags[i]);
Info.setMapping(diag::MAP_WARNING_NO_WERROR);
if (Info.getMapping() == diag::MAP_ERROR ||
Info.getMapping() == diag::MAP_FATAL)
Info.setMapping(diag::MAP_WARNING);
Info.setNoWarningAsError(true);
}
@ -284,7 +287,9 @@ bool DiagnosticsEngine::setDiagnosticGroupErrorAsFatal(StringRef Group,
DiagnosticMappingInfo &Info = GetCurDiagState()->getOrAddMappingInfo(
GroupDiags[i]);
Info.setMapping(diag::MAP_ERROR_NO_WFATAL);
if (Info.getMapping() == diag::MAP_FATAL)
Info.setMapping(diag::MAP_ERROR);
Info.setNoErrorAsFatal(true);
}

View File

@ -194,14 +194,12 @@ static DiagnosticMappingInfo GetDefaultDiagMappingInfo(unsigned DiagID) {
if (StaticInfo->WarnNoWerror) {
assert(Info.getMapping() == diag::MAP_WARNING &&
"Unexpected mapping with no-Werror bit!");
Info.setMapping(diag::MAP_WARNING_NO_WERROR);
Info.setNoWarningAsError(true);
}
if (StaticInfo->WarnShowInSystemHeader) {
assert(Info.getMapping() == diag::MAP_WARNING &&
"Unexpected mapping with show-in-system-header bit!");
Info.setMapping(diag::MAP_WARNING_SHOW_IN_SYSTEM_HEADER);
Info.setShowInSystemHeader(true);
}
}
@ -533,90 +531,73 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo(
(diag::kind)DiagID);
bool ShouldEmitInSystemHeader = false;
switch (MappingInfo.getMapping()) {
default: llvm_unreachable("Unknown mapping!");
case diag::MAP_IGNORE:
if (Diag.EnableAllWarnings) {
// Leave the warning disabled if it was explicitly ignored.
if (MappingInfo.isUser())
return DiagnosticIDs::Ignored;
Result = Diag.WarningsAsErrors ? DiagnosticIDs::Error
: DiagnosticIDs::Warning;
}
// Otherwise, ignore this diagnostic unless this is an extension diagnostic
// and we're mapping them onto warnings or errors.
else if (!isBuiltinExtensionDiag(DiagID) || // Not an extension
Diag.ExtBehavior == DiagnosticsEngine::Ext_Ignore || // Ext ignored
MappingInfo.isUser()) { // User explicitly mapped it.
return DiagnosticIDs::Ignored;
}
else {
Result = DiagnosticIDs::Warning;
}
if (Diag.ExtBehavior == DiagnosticsEngine::Ext_Error)
Result = DiagnosticIDs::Error;
if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
Result = DiagnosticIDs::Fatal;
Result = DiagnosticIDs::Ignored;
break;
case diag::MAP_WARNING:
Result = DiagnosticIDs::Warning;
break;
case diag::MAP_ERROR:
Result = DiagnosticIDs::Error;
if (Diag.ErrorsAsFatal)
Result = DiagnosticIDs::Fatal;
break;
case diag::MAP_FATAL:
Result = DiagnosticIDs::Fatal;
break;
case diag::MAP_WARNING_SHOW_IN_SYSTEM_HEADER:
ShouldEmitInSystemHeader = true;
// continue as MAP_WARNING.
case diag::MAP_WARNING:
// If warnings are globally mapped to ignore or error, do it.
if (Diag.IgnoreAllWarnings)
return DiagnosticIDs::Ignored;
Result = DiagnosticIDs::Warning;
// If this is an extension diagnostic and we're in -pedantic-error mode, and
// if the user didn't explicitly map it, upgrade to an error.
if (Diag.ExtBehavior == DiagnosticsEngine::Ext_Error &&
!MappingInfo.isUser() &&
isBuiltinExtensionDiag(DiagID))
Result = DiagnosticIDs::Error;
if (Diag.WarningsAsErrors)
Result = DiagnosticIDs::Error;
if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
Result = DiagnosticIDs::Fatal;
break;
case diag::MAP_WARNING_NO_WERROR:
// Diagnostics specified with -Wno-error=foo should be set to warnings, but
// not be adjusted by -Werror or -pedantic-errors.
Result = DiagnosticIDs::Warning;
// If warnings are globally mapped to ignore or error, do it.
if (Diag.IgnoreAllWarnings)
return DiagnosticIDs::Ignored;
break;
case diag::MAP_ERROR_NO_WFATAL:
// Diagnostics specified as -Wno-fatal-error=foo should be errors, but
// unaffected by -Wfatal-errors.
Result = DiagnosticIDs::Error;
break;
}
// Okay, we're about to return this as a "diagnostic to emit" one last check:
// if this is any sort of extension warning, and if we're in an __extension__
// block, silence it.
if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
// Upgrade ignored diagnostics if -Weverything is enabled.
if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored &&
!MappingInfo.isUser())
Result = DiagnosticIDs::Warning;
// Ignore any kind of extension diagnostics inside __extension__ blocks.
bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID);
if (Diag.AllExtensionsSilenced && IsExtensionDiag)
return DiagnosticIDs::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;
}
}
// At this point, ignored errors can no longer be upgraded.
if (Result == DiagnosticIDs::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 -Werror is enabled, map warnings to errors unless explicitly disabled.
if (Result == DiagnosticIDs::Warning) {
if (Diag.WarningsAsErrors && !MappingInfo.hasNoWarningAsError())
Result = DiagnosticIDs::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 we are in a system header, we ignore it.
// We also want to ignore extensions and warnings in -Werror and
// -pedantic-errors modes, which *map* warnings/extensions to errors.
@ -624,7 +605,7 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
DiagClass != CLASS_ERROR &&
// Custom diagnostics always are emitted in system headers.
DiagID < diag::DIAG_UPPER_LIMIT &&
!ShouldEmitInSystemHeader &&
!MappingInfo.hasShowInSystemHeader() &&
Diag.SuppressSystemWarnings &&
Loc.isValid() &&
Diag.getSourceManager().isInSystemHeader(

View File

@ -15,4 +15,4 @@ void tf() {
}
// Allowed by GNU extension
int a4[] = {}; // expected-warning {{zero size arrays}}
int a4[] = {}; // expected-error {{zero size arrays}}

View File

@ -2,9 +2,6 @@
// become errors.
//
// RUN: %clang_cc1 -verify -Weverything -pedantic-errors %s
//
// FIXME: This is currently broken.
// XFAIL: *
int f0(int, unsigned);
int f0(int x, unsigned y) {

View File

@ -1,8 +1,5 @@
// Check that -w has lower priority than -pedantic-errors.
// RUN: %clang_cc1 -verify -pedantic-errors -w %s
//
// FIXME: We currently get this wrong.
// XFAIL: *
void f0() { f1(); } // expected-error {{implicit declaration of function}}

View File

@ -0,0 +1,6 @@
// RUN: %clang_cc1 -verify -Wno-error=sign-compare %s
// RUN: %clang_cc1 -verify -Wsign-compare -w -Wno-error=sign-compare %s
int f0(int x, unsigned y) {
return x < y;
}