diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index 99251709aa9f..b877366520dc 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -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. diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index 6b7f732b3f08..31f56e99bf4f 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -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 &OutStr) -{ + llvm::SmallVectorImpl &OutStr) { const char *ArgumentEnd = Argument + ArgumentLen; while (1) { assert(Argument < ArgumentEnd && "Plural expression didn't match."); diff --git a/clang/tools/clang-cc/Warnings.cpp b/clang/tools/clang-cc/Warnings.cpp index 818e7743d87b..bab2ab7a140e 100644 --- a/clang/tools/clang-cc/Warnings.cpp +++ b/clang/tools/clang-cc/Warnings.cpp @@ -65,21 +65,17 @@ static bool WarningOptionCompare(const WarningOption &LHS, } static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping, - Diagnostic &Diags, - llvm::SmallVectorImpl &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 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::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;