move handling of -pedantic and -pedantic-errors into Diagnostics,

out of Warnings.cpp.  This simplifies warnings.cpp and makes it more
efficient.

llvm-svn: 69266
This commit is contained in:
Chris Lattner 2009-04-16 05:04:32 +00:00
parent f9150bac01
commit b8e73158e1
3 changed files with 54 additions and 66 deletions

View File

@ -67,14 +67,9 @@ namespace clang {
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
/// -pedantic-errors. This happens when you specify -Wfoo for an
/// extension warning.
MAP_WARNING_NO_PEDANTIC_ERROR = 5,
/// Map this diagnostic to "warning", but make it immune to -Werror and
/// -pedantic-errors. This happens when you specify -Wno-error=foo.
MAP_WARNING_NO_WERROR = 6
/// Map this diagnostic to "warning", but make it immune to -Werror. This
/// happens when you specify -Wno-error=foo.
MAP_WARNING_NO_WERROR = 5
};
}
@ -145,6 +140,12 @@ public:
Ignored, Note, Warning, Error, Fatal
};
/// ExtensionHandling - How do we handle otherwise-unmapped extension? This
/// is controlled by -pedantic and -pedantic-errors.
enum ExtensionHandling {
Ext_Ignore, Ext_Warn, Ext_Error
};
enum ArgumentKind {
ak_std_string, // std::string
ak_c_string, // const char *
@ -158,9 +159,10 @@ public:
private:
unsigned char AllExtensionsSilenced; // Used by __extension__
bool IgnoreAllWarnings; // Ignore all warnings: -w
bool WarningsAsErrors; // Treat warnings like errors:
bool SuppressSystemWarnings;// Suppress warnings in system headers.
bool IgnoreAllWarnings; // Ignore all warnings: -w
bool WarningsAsErrors; // Treat warnings like errors:
bool SuppressSystemWarnings; // Suppress warnings in system headers.
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
DiagnosticClient *Client;
/// DiagMappings - Mapping information for diagnostics. Mapping info is
@ -226,6 +228,13 @@ public:
void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
/// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
/// extension diagnostics are mapped onto ignore/warning/error. This
/// corresponds to the GCC -pedantic and -pedantic-errors option.
void setExtensionHandlingBehavior(ExtensionHandling H) {
ExtBehavior = H;
}
/// AllExtensionsSilenced - This is a counter bumped when an __extension__
/// block is encountered. When non-zero, all extension diagnostics are
/// entirely silenced, no matter how they are mapped.

View File

@ -262,6 +262,7 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
IgnoreAllWarnings = false;
WarningsAsErrors = false;
SuppressSystemWarnings = false;
ExtBehavior = Ext_Ignore;
ErrorOccurred = false;
FatalErrorOccurred = false;
@ -371,7 +372,15 @@ Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
switch (MappingInfo & 7) {
default: assert(0 && "Unknown mapping!");
case diag::MAP_IGNORE:
return Diagnostic::Ignored;
// Ignore this, unless this is an extension diagnostic and we're mapping
// them onto warnings or errors.
if (!isBuiltinExtensionDiag(DiagID) || // Not an extension
ExtBehavior == Ext_Ignore || // Extensions ignored anyway
(MappingInfo & 8) != 0) // User explicitly mapped it.
return Diagnostic::Ignored;
Result = Diagnostic::Warning;
if (ExtBehavior == Ext_Error) Result = Diagnostic::Error;
break;
case diag::MAP_ERROR:
Result = Diagnostic::Error;
break;
@ -384,9 +393,18 @@ Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
return Diagnostic::Ignored;
Result = Diagnostic::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 (ExtBehavior == Ext_Error &&
(MappingInfo & 8) == 0 &&
isBuiltinExtensionDiag(DiagID))
Result = Diagnostic::Error;
if (WarningsAsErrors)
Result = Diagnostic::Error;
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.
@ -634,8 +652,7 @@ static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) {
/// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2}
static void HandlePluralModifier(unsigned ValNo,
const char *Argument, unsigned ArgumentLen,
llvm::SmallVectorImpl<char> &OutStr)
{
llvm::SmallVectorImpl<char> &OutStr) {
const char *ArgumentEnd = Argument + ArgumentLen;
while (1) {
assert(Argument < ArgumentEnd && "Plural expression didn't match.");

View File

@ -65,21 +65,17 @@ static bool WarningOptionCompare(const WarningOption &LHS,
}
static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
Diagnostic &Diags,
llvm::SmallVectorImpl<unsigned short> &ControlledDiags) {
Diagnostic &Diags) {
// Option exists, poke all the members of its diagnostic set.
if (const short *Member = Group->Members) {
for (; *Member != -1; ++Member) {
for (; *Member != -1; ++Member)
Diags.setDiagnosticMapping(*Member, Mapping);
ControlledDiags.push_back(*Member);
}
}
// Enable/disable all subgroups along with this one.
if (const char *SubGroups = Group->SubGroups) {
for (; *SubGroups != (char)-1; ++SubGroups)
MapGroupMembers(&OptionTable[(unsigned char)*SubGroups], Mapping,
Diags, ControlledDiags);
MapGroupMembers(&OptionTable[(unsigned char)*SubGroups], Mapping, Diags);
}
}
@ -87,13 +83,19 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags) {
Diags.setSuppressSystemWarnings(true); // Default to -Wno-system-headers
Diags.setIgnoreAllWarnings(OptNoWarnings);
// If -pedantic or -pedantic-errors was specified, then we want to map all
// extension diagnostics onto WARNING or ERROR unless the user has futz'd
// around with them explicitly.
if (OptPedanticErrors)
Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Error);
else if (OptPedantic)
Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Warn);
else
Diags.setExtensionHandlingBehavior(Diagnostic::Ext_Ignore);
// FIXME: -fdiagnostics-show-option
// FIXME: -Wfatal-errors / -Wfatal-errors=foo
/// ControlledDiags - Keep track of the options that the user explicitly
/// poked with -Wfoo, -Wno-foo, or -Werror=foo.
llvm::SmallVector<unsigned short, 256> ControlledDiags;
for (unsigned i = 0, e = OptWarnings.size(); i != e; ++i) {
const std::string &Opt = OptWarnings[i];
const char *OptStart = &Opt[0];
@ -152,47 +154,7 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags) {
continue;
}
MapGroupMembers(Found, Mapping, Diags, ControlledDiags);
}
// If -pedantic or -pedantic-errors was specified, then we want to map all
// extension diagnostics onto WARNING or ERROR unless the user has futz'd
// around with them explicitly.
if (OptPedantic || OptPedanticErrors) {
// Sort the array of options that has been poked at directly so we can do
// efficient queries.
std::sort(ControlledDiags.begin(), ControlledDiags.end());
// Don't worry about iteration off the end down below.
ControlledDiags.push_back(diag::DIAG_UPPER_LIMIT);
diag::Mapping Mapping =
OptPedanticErrors ? diag::MAP_ERROR : diag::MAP_WARNING;
// Loop over all of the extension diagnostics. Unless they were explicitly
// controlled, reset their mapping to Mapping. We walk through the
// ControlledDiags in parallel with this walk, which is faster than
// repeatedly binary searching it.
//
llvm::SmallVectorImpl<unsigned short>::iterator ControlledDiagsIt =
ControlledDiags.begin();
// TODO: if it matters, we could make tblgen produce a list of just the
// extension diags to avoid skipping ones that don't matter.
for (unsigned short i = 0; i != diag::DIAG_UPPER_LIMIT; ++i) {
// If this diagnostic was controlled, ignore it.
if (i == *ControlledDiagsIt) {
++ControlledDiagsIt;
while (i == *ControlledDiagsIt) // ControlledDiags can have dupes.
++ControlledDiagsIt;
// Do not map this diagnostic ID#.
continue;
}
// Okay, the user didn't control this ID. If it is an example, map it.
if (Diagnostic::isBuiltinExtensionDiag(i))
Diags.setDiagnosticMapping(i, Mapping);
}
MapGroupMembers(Found, Mapping, Diags);
}
return false;