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_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
MAP_WARNING = 2, //< Map this diagnostic to a warning. MAP_WARNING = 2, //< Map this diagnostic to a warning.
MAP_ERROR = 3, //< Map this diagnostic to an error. MAP_ERROR = 3, //< Map this diagnostic to an error.
MAP_FATAL = 4, //< Map this diagnostic to a fatal 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
}; };
} }

View File

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

View File

@ -194,14 +194,12 @@ static DiagnosticMappingInfo GetDefaultDiagMappingInfo(unsigned DiagID) {
if (StaticInfo->WarnNoWerror) { if (StaticInfo->WarnNoWerror) {
assert(Info.getMapping() == diag::MAP_WARNING && assert(Info.getMapping() == diag::MAP_WARNING &&
"Unexpected mapping with no-Werror bit!"); "Unexpected mapping with no-Werror bit!");
Info.setMapping(diag::MAP_WARNING_NO_WERROR);
Info.setNoWarningAsError(true); Info.setNoWarningAsError(true);
} }
if (StaticInfo->WarnShowInSystemHeader) { if (StaticInfo->WarnShowInSystemHeader) {
assert(Info.getMapping() == diag::MAP_WARNING && assert(Info.getMapping() == diag::MAP_WARNING &&
"Unexpected mapping with show-in-system-header bit!"); "Unexpected mapping with show-in-system-header bit!");
Info.setMapping(diag::MAP_WARNING_SHOW_IN_SYSTEM_HEADER);
Info.setShowInSystemHeader(true); Info.setShowInSystemHeader(true);
} }
} }
@ -533,90 +531,73 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo( DiagnosticMappingInfo &MappingInfo = State->getOrAddMappingInfo(
(diag::kind)DiagID); (diag::kind)DiagID);
bool ShouldEmitInSystemHeader = false;
switch (MappingInfo.getMapping()) { switch (MappingInfo.getMapping()) {
default: llvm_unreachable("Unknown mapping!"); default: llvm_unreachable("Unknown mapping!");
case diag::MAP_IGNORE: case diag::MAP_IGNORE:
if (Diag.EnableAllWarnings) { Result = DiagnosticIDs::Ignored;
// Leave the warning disabled if it was explicitly ignored. break;
if (MappingInfo.isUser()) case diag::MAP_WARNING:
return DiagnosticIDs::Ignored; Result = DiagnosticIDs::Warning;
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;
break; break;
case diag::MAP_ERROR: case diag::MAP_ERROR:
Result = DiagnosticIDs::Error; Result = DiagnosticIDs::Error;
if (Diag.ErrorsAsFatal)
Result = DiagnosticIDs::Fatal;
break; break;
case diag::MAP_FATAL: case diag::MAP_FATAL:
Result = DiagnosticIDs::Fatal; Result = DiagnosticIDs::Fatal;
break; 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: // Upgrade ignored diagnostics if -Weverything is enabled.
// if this is any sort of extension warning, and if we're in an __extension__ if (Diag.EnableAllWarnings && Result == DiagnosticIDs::Ignored &&
// block, silence it. !MappingInfo.isUser())
if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID)) Result = DiagnosticIDs::Warning;
// Ignore any kind of extension diagnostics inside __extension__ blocks.
bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID);
if (Diag.AllExtensionsSilenced && IsExtensionDiag)
return DiagnosticIDs::Ignored; 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. // If we are in a system header, we ignore it.
// We also want to ignore extensions and warnings in -Werror and // We also want to ignore extensions and warnings in -Werror and
// -pedantic-errors modes, which *map* warnings/extensions to errors. // -pedantic-errors modes, which *map* warnings/extensions to errors.
@ -624,7 +605,7 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
DiagClass != CLASS_ERROR && DiagClass != CLASS_ERROR &&
// Custom diagnostics always are emitted in system headers. // Custom diagnostics always are emitted in system headers.
DiagID < diag::DIAG_UPPER_LIMIT && DiagID < diag::DIAG_UPPER_LIMIT &&
!ShouldEmitInSystemHeader && !MappingInfo.hasShowInSystemHeader() &&
Diag.SuppressSystemWarnings && Diag.SuppressSystemWarnings &&
Loc.isValid() && Loc.isValid() &&
Diag.getSourceManager().isInSystemHeader( Diag.getSourceManager().isInSystemHeader(

View File

@ -15,4 +15,4 @@ void tf() {
} }
// Allowed by GNU extension // 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. // become errors.
// //
// RUN: %clang_cc1 -verify -Weverything -pedantic-errors %s // RUN: %clang_cc1 -verify -Weverything -pedantic-errors %s
//
// FIXME: This is currently broken.
// XFAIL: *
int f0(int, unsigned); int f0(int, unsigned);
int f0(int x, unsigned y) { int f0(int x, unsigned y) {

View File

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