[cfe-commits] r69154 - in /cfe/trunk: include/clang/Basic/Diagnostic.h lib/Basic/Diagnostic.cpp lib/Parse/ExtensionRAIIObject.h test/Misc/diag-mapping.c tools/clang-cc/Warnings.cpp

Chris Lattner sabre at nondot.org
Wed Apr 15 00:01:19 PDT 2009


Author: lattner
Date: Wed Apr 15 02:01:18 2009
New Revision: 69154

URL: http://llvm.org/viewvc/llvm-project?rev=69154&view=rev
Log:
Rejigger how -pedantic and -pedantic-errors work and their interaction
with other diagnostic mapping.  In the new scheme, -Wfoo or -Wno-foo or 
-Werror=foo all override the -pedantic options, and __extension__ 
robustly silences all extension diagnostics in their scope.

An added bonus of this change is that MAP_DEFAULT goes away, meaning that
per-diagnostic mapping information can now be stored in 2 bits, doubling
the density of the Diagnostic::DiagMapping array.  This also 
substantially simplifies Diagnostic::getDiagnosticLevel.

OTOH, this temporarily introduces some "macro intensive" code in 
Diagnostic.cpp.  This will be addressed in a later patch.


Added:
    cfe/trunk/test/Misc/diag-mapping.c
Modified:
    cfe/trunk/include/clang/Basic/Diagnostic.h
    cfe/trunk/lib/Basic/Diagnostic.cpp
    cfe/trunk/lib/Parse/ExtensionRAIIObject.h
    cfe/trunk/tools/clang-cc/Warnings.cpp

Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=69154&r1=69153&r2=69154&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Wed Apr 15 02:01:18 2009
@@ -57,15 +57,14 @@
       
     /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
     /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
-    /// (emit as an error), or MAP_DEFAULT (handle the default way).  It allows
-    /// clients to map errors to MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop
-    /// emitting diagnostics after this one).
+    /// (emit as an error).  It allows clients to map errors to
+    /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
+    /// one).
     enum Mapping {
-      MAP_DEFAULT = 0,     //< Do not map this diagnostic.
-      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_IGNORE  = 0,     //< Map this diagnostic to nothing, ignore it.
+      MAP_WARNING = 1,     //< Map this diagnostic to a warning.
+      MAP_ERROR   = 2,     //< Map this diagnostic to an error.
+      MAP_FATAL   = 3      //< Map this diagnostic to a fatal error.
     };
   }
   
@@ -147,17 +146,16 @@
     ak_nameddecl        // NamedDecl *
   };
 
-private:  
+private: 
+  unsigned char AllExtensionsSilenced; // Used by __extension__
   bool IgnoreAllWarnings;     // Ignore all warnings: -w
   bool WarningsAsErrors;      // Treat warnings like errors: 
-  bool WarnOnExtensions;      // Enables warnings for gcc extensions: -pedantic.
-  bool ErrorOnExtensions;     // Error on extensions: -pedantic-errors.
   bool SuppressSystemWarnings;// Suppress warnings in system headers.
   DiagnosticClient *Client;
 
   /// DiagMappings - Mapping information for diagnostics.  Mapping info is
-  /// packed into four bits per diagnostic.
-  unsigned char DiagMappings[diag::DIAG_UPPER_LIMIT/2];
+  /// packed into two bits per diagnostic.
+  unsigned char DiagMappings[diag::DIAG_UPPER_LIMIT/4];
   
   /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
   /// fatal error is emitted, and is sticky.
@@ -209,21 +207,17 @@
   void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
   bool getWarningsAsErrors() const { return WarningsAsErrors; }
   
-  /// setWarnOnExtensions - When set to true, issue warnings on GCC extensions,
-  /// the equivalent of GCC's -pedantic.
-  void setWarnOnExtensions(bool Val) { WarnOnExtensions = Val; }
-  bool getWarnOnExtensions() const { return WarnOnExtensions; }
-  
-  /// setErrorOnExtensions - When set to true issue errors for GCC extensions
-  /// instead of warnings.  This is the equivalent to GCC's -pedantic-errors.
-  void setErrorOnExtensions(bool Val) { ErrorOnExtensions = Val; }
-  bool getErrorOnExtensions() const { return ErrorOnExtensions; }
-
   /// setSuppressSystemWarnings - When set to true mask warnings that
   /// come from system headers.
   void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
   bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
 
+  /// 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.
+  void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
+  void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
+  
   /// setDiagnosticMapping - This allows the client to specify that certain
   /// warnings are ignored.  Only WARNINGs and EXTENSIONs can be mapped.
   void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) {
@@ -231,16 +225,19 @@
            "Can only map builtin diagnostics");
     assert((isBuiltinWarningOrExtension(Diag) || Map == diag::MAP_FATAL) &&
            "Cannot map errors!");
-    unsigned char &Slot = DiagMappings[Diag/2];
-    unsigned Bits = (Diag & 1)*4;
-    Slot &= ~(7 << Bits);
+    setDiagnosticMappingInternal(Diag, Map);
+  }
+  void setDiagnosticMappingInternal(unsigned Diag, unsigned Map) {
+    unsigned char &Slot = DiagMappings[Diag/4];
+    unsigned Bits = (Diag & 3)*2;
+    Slot &= ~(3 << Bits);
     Slot |= Map << Bits;
   }
 
   /// getDiagnosticMapping - Return the mapping currently set for the specified
   /// diagnostic.
   diag::Mapping getDiagnosticMapping(diag::kind Diag) const {
-    return (diag::Mapping)((DiagMappings[Diag/2] >> (Diag & 1)*4) & 7);
+    return (diag::Mapping)((DiagMappings[Diag/4] >> (Diag & 3)*2) & 3);
   }
   
   bool hasErrorOccurred() const { return ErrorOccurred; }
@@ -287,6 +284,12 @@
   /// \brief Determine whether the given built-in diagnostic ID is a
   /// Note.
   static bool isBuiltinNote(unsigned DiagID);
+  
+  /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+  /// ID is for an extension of some sort.
+  ///
+  static bool isBuiltinExtensionDiag(unsigned DiagID);
+  
 
   /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
   /// object, classify the specified diagnostic ID into a Level, consumable by

Modified: cfe/trunk/lib/Basic/Diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=69154&r1=69153&r2=69154&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Wed Apr 15 02:01:18 2009
@@ -12,6 +12,15 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Basic/Diagnostic.h"
+
+#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Parse/ParseDiagnostic.h"
+#include "clang/AST/ASTDiagnostic.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Analysis/AnalysisDiagnostic.h"
+#include "clang/Driver/DriverDiagnostic.h"
+
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/SmallVector.h"
@@ -25,50 +34,85 @@
 // Builtin Diagnostic information
 //===----------------------------------------------------------------------===//
 
-/// Flag values for diagnostics.
+// DefaultDiagnosticMappings - This specifies the default mapping for each diag,
+// based on its kind.   Yay for macros?
+
+struct DefaultMappingInfo {
+  unsigned DiagID : 14;
+  unsigned Mapping : 2;
+};
+
+#define NOTE      diag::MAP_IGNORE
+#define WARNING   diag::MAP_WARNING
+#define EXTENSION diag::MAP_IGNORE
+#define EXTWARN   diag::MAP_WARNING
+#define ERROR     diag::MAP_ERROR
+#define FATAL     diag::MAP_FATAL
+
+static const DefaultMappingInfo DefaultMappings[] = {
+#define DIAG(ENUM,CLASS,DESC) { diag::ENUM, CLASS },
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+{ 0, 0 }
+};
+
+#undef DIAG
+#undef NOTE
+#undef WARNING
+#undef EXTENSION
+#undef EXTWARN
+#undef ERROR
+#undef FATAL
+
+
+
+// Diagnostic classes.
 enum {
-  // Diagnostic classes.
   NOTE       = 0x01,
   WARNING    = 0x02,
   EXTENSION  = 0x03,
   EXTWARN    = 0x04,
   ERROR      = 0x05,
-  FATAL      = 0x06,
-  class_mask = 0x07
+  FATAL      = 0x06
 };
 
-/// DiagnosticFlags - A set of flags, or'd together, that describe the
-/// diagnostic.
-#define DIAG(ENUM,FLAGS,DESC) FLAGS,
-static unsigned char DiagnosticFlagsCommon[] = {
+/// DiagnosticClasses - The class for each diagnostic.
+#define DIAG(ENUM,CLASS,DESC) CLASS,
+static unsigned char DiagnosticClassesCommon[] = {
 #include "clang/Basic/DiagnosticCommonKinds.inc"
   0
 };
-static unsigned char DiagnosticFlagsDriver[] = {
+static unsigned char DiagnosticClassesDriver[] = {
 #include "clang/Basic/DiagnosticDriverKinds.inc"
   0
 };
-static unsigned char DiagnosticFlagsFrontend[] = {
+static unsigned char DiagnosticClassesFrontend[] = {
 #include "clang/Basic/DiagnosticFrontendKinds.inc"
   0
 };
-static unsigned char DiagnosticFlagsLex[] = {
+static unsigned char DiagnosticClassesLex[] = {
 #include "clang/Basic/DiagnosticLexKinds.inc"
   0
 };
-static unsigned char DiagnosticFlagsParse[] = {
+static unsigned char DiagnosticClassesParse[] = {
 #include "clang/Basic/DiagnosticParseKinds.inc"
   0
 };
-static unsigned char DiagnosticFlagsAST[] = {
+static unsigned char DiagnosticClassesAST[] = {
 #include "clang/Basic/DiagnosticASTKinds.inc"
   0
 };
-static unsigned char DiagnosticFlagsSema[] = {
+static unsigned char DiagnosticClassesSema[] = {
 #include "clang/Basic/DiagnosticSemaKinds.inc"
   0
 };
-static unsigned char DiagnosticFlagsAnalysis[] = {
+static unsigned char DiagnosticClassesAnalysis[] = {
 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
   0
 };
@@ -81,27 +125,27 @@
          "Diagnostic ID out of range!");
   unsigned res;
   if (DiagID < diag::DIAG_START_DRIVER)
-    res = DiagnosticFlagsCommon[DiagID];
+    res = DiagnosticClassesCommon[DiagID];
   else if (DiagID < diag::DIAG_START_FRONTEND)
-    res = DiagnosticFlagsDriver[DiagID - diag::DIAG_START_DRIVER - 1];
+    res = DiagnosticClassesDriver[DiagID - diag::DIAG_START_DRIVER - 1];
   else if (DiagID < diag::DIAG_START_LEX)
-    res = DiagnosticFlagsFrontend[DiagID - diag::DIAG_START_FRONTEND - 1];
+    res = DiagnosticClassesFrontend[DiagID - diag::DIAG_START_FRONTEND - 1];
   else if (DiagID < diag::DIAG_START_PARSE)
-    res = DiagnosticFlagsLex[DiagID - diag::DIAG_START_LEX - 1];
+    res = DiagnosticClassesLex[DiagID - diag::DIAG_START_LEX - 1];
   else if (DiagID < diag::DIAG_START_AST)
-    res = DiagnosticFlagsParse[DiagID - diag::DIAG_START_PARSE - 1];
+    res = DiagnosticClassesParse[DiagID - diag::DIAG_START_PARSE - 1];
   else if (DiagID < diag::DIAG_START_SEMA)
-    res = DiagnosticFlagsAST[DiagID - diag::DIAG_START_AST - 1];
+    res = DiagnosticClassesAST[DiagID - diag::DIAG_START_AST - 1];
   else if (DiagID < diag::DIAG_START_ANALYSIS)
-    res = DiagnosticFlagsSema[DiagID - diag::DIAG_START_SEMA - 1];
+    res = DiagnosticClassesSema[DiagID - diag::DIAG_START_SEMA - 1];
   else
-    res = DiagnosticFlagsAnalysis[DiagID - diag::DIAG_START_ANALYSIS - 1];
-  return res & class_mask;
+    res = DiagnosticClassesAnalysis[DiagID - diag::DIAG_START_ANALYSIS - 1];
+  return res;
 }
 
 /// DiagnosticText - An english message to print for the diagnostic.  These
 /// should be localized.
-#define DIAG(ENUM,FLAGS,DESC) DESC,
+#define DIAG(ENUM,CLASS,DESC) DESC,
 static const char * const DiagnosticTextCommon[] = {
 #include "clang/Basic/DiagnosticCommonKinds.inc"
   0
@@ -203,13 +247,10 @@
 
 
 Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
+  AllExtensionsSilenced = 0;
   IgnoreAllWarnings = false;
   WarningsAsErrors = false;
-  WarnOnExtensions = false;
-  ErrorOnExtensions = false;
   SuppressSystemWarnings = false;
-  // Clear all mappings, setting them to MAP_DEFAULT.
-  memset(DiagMappings, 0, sizeof(DiagMappings));
   
   ErrorOccurred = false;
   FatalErrorOccurred = false;
@@ -221,6 +262,12 @@
   
   ArgToStringFn = DummyArgToStringFn;
   ArgToStringCookie = 0;
+  
+  // Set all mappings to their default.
+  for (unsigned i = 0, e = sizeof(DefaultMappings)/sizeof(DefaultMappings[0]);
+       i != e; ++i)
+    setDiagnosticMappingInternal(DefaultMappings[i].DiagID,
+                                 DefaultMappings[i].Mapping);
 }
 
 Diagnostic::~Diagnostic() {
@@ -251,6 +298,17 @@
   return DiagID < diag::DIAG_UPPER_LIMIT && getBuiltinDiagClass(DiagID) == NOTE;
 }
 
+/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
+/// ID is for an extension of some sort.
+///
+bool Diagnostic::isBuiltinExtensionDiag(unsigned DiagID) {
+  if (DiagID < diag::DIAG_UPPER_LIMIT) {
+    unsigned Class = getBuiltinDiagClass(DiagID);
+    return Class == EXTENSION || Class == EXTWARN;
+  }
+  return false;
+}
+
 
 /// getDescription - Given a diagnostic ID, return a description of the
 /// issue.
@@ -294,40 +352,31 @@
 Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
   // Specific non-error diagnostics may be mapped to various levels from ignored
   // to error.  Errors can only be mapped to fatal.
+  Diagnostic::Level Result = Diagnostic::Fatal;
   switch (getDiagnosticMapping((diag::kind)DiagID)) {
-  case diag::MAP_DEFAULT: break;
-  case diag::MAP_IGNORE:  return Diagnostic::Ignored;
-  case diag::MAP_WARNING: DiagClass = WARNING; break;
-  case diag::MAP_ERROR:   DiagClass = ERROR; break;
-  case diag::MAP_FATAL:   DiagClass = FATAL; break;
-  }
-  
-  // Map diagnostic classes based on command line argument settings.
-  if (DiagClass == EXTENSION) {
-    if (ErrorOnExtensions)
-      DiagClass = ERROR;
-    else if (WarnOnExtensions)
-      DiagClass = WARNING;
-    else
-      return Ignored;
-  } else if (DiagClass == EXTWARN) {
-    DiagClass = ErrorOnExtensions ? ERROR : WARNING;
-  }
-  
-  // If warnings are globally mapped to ignore or error, do it.
-  if (DiagClass == WARNING) {
+  case diag::MAP_IGNORE:
+    return Diagnostic::Ignored;
+  case diag::MAP_ERROR:
+    Result = Diagnostic::Error;
+    break;
+  case diag::MAP_FATAL:
+    Result = Diagnostic::Fatal;
+    break;
+  case diag::MAP_WARNING:
+    // If warnings are globally mapped to ignore or error, do it.
     if (IgnoreAllWarnings)
       return Diagnostic::Ignored;
-    if (WarningsAsErrors)
-      DiagClass = ERROR;
+    Result = WarningsAsErrors ? Diagnostic::Error : Diagnostic::Warning;
+    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 (AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
+    return Diagnostic::Ignored;
   
-  switch (DiagClass) {
-  default: assert(0 && "Unknown diagnostic class!");
-  case WARNING:     return Diagnostic::Warning;
-  case ERROR:       return Diagnostic::Error;
-  case FATAL:       return Diagnostic::Fatal;
-  }
+  return Result;
 }
 
 /// ProcessDiag - This is the method used to report a diagnostic that is

Modified: cfe/trunk/lib/Parse/ExtensionRAIIObject.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ExtensionRAIIObject.h?rev=69154&r1=69153&r2=69154&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ExtensionRAIIObject.h (original)
+++ cfe/trunk/lib/Parse/ExtensionRAIIObject.h Wed Apr 15 02:01:18 2009
@@ -26,15 +26,13 @@
     void operator=(const ExtensionRAIIObject &);     // DO NOT IMPLEMENT
     ExtensionRAIIObject(const ExtensionRAIIObject&); // DO NOT IMPLEMENT
     Diagnostic &Diags;
-    bool OldState;
   public:
     ExtensionRAIIObject(Diagnostic &diags) : Diags(diags) {
-      OldState = Diags.getWarnOnExtensions();
-      Diags.setWarnOnExtensions(false);
+      Diags.IncrementAllExtensionsSilenced();
     }
     
     ~ExtensionRAIIObject() {
-      Diags.setWarnOnExtensions(OldState);
+      Diags.DecrementAllExtensionsSilenced();
     }
   };
 }

Added: cfe/trunk/test/Misc/diag-mapping.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-mapping.c?rev=69154&view=auto

==============================================================================
--- cfe/trunk/test/Misc/diag-mapping.c (added)
+++ cfe/trunk/test/Misc/diag-mapping.c Wed Apr 15 02:01:18 2009
@@ -0,0 +1,27 @@
+// This should warn by default.
+// RUN: clang-cc %s 2>&1 | grep "warning:" &&
+// This should not emit anything.
+// RUN: clang-cc %s -Wno-extra-tokens 2>&1 | not grep diagnostic
+
+// -Werror can map all warnings to error.
+// RUN: clang-cc %s -Werror 2>&1 | grep "error:" &&
+
+// -Werror can map this one warning to error.
+// RUN: clang-cc %s -Werror=extra-tokens 2>&1 | grep "error:" &&
+
+// This should stay a warning with -pedantic.
+// RUN: clang-cc %s -pedantic 2>&1 | grep "warning:" &&
+
+// This should emit an error with -pedantic-errors.
+// RUN: clang-cc %s -pedantic-errors 2>&1 | grep "error:" &&
+
+// This should emit a warning, because -Wfoo overrides -pedantic*.
+// RUN: clang-cc %s -pedantic-errors -Wextra_tokens 2>&1 | grep "error:" &&
+
+// This should emit nothing, because -Wno-extra-tokens overrides -pedantic*
+// RUN: clang-cc %s -pedantic-errors -Wno-extra-tokens 2>&1 | not grep diagnostic
+
+#ifdef foo
+#endif bad // extension!
+
+int x;

Modified: cfe/trunk/tools/clang-cc/Warnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/Warnings.cpp?rev=69154&r1=69153&r2=69154&view=diff

==============================================================================
--- cfe/trunk/tools/clang-cc/Warnings.cpp (original)
+++ cfe/trunk/tools/clang-cc/Warnings.cpp Wed Apr 15 02:01:18 2009
@@ -101,11 +101,10 @@
 }
 
 bool clang::ProcessWarningOptions(Diagnostic &Diags) {
+  Diags.setSuppressSystemWarnings(true);  // Default to -Wno-system-headers
+  
   // FIXME: These should be mapped to group options.
   Diags.setIgnoreAllWarnings(OptNoWarnings);
-  Diags.setWarnOnExtensions(OptPedantic);
-  Diags.setErrorOnExtensions(OptPedanticErrors);
-  Diags.setSuppressSystemWarnings(true);  // Default to -Wno-system-headers
 
   // Set some defaults that are currently set manually. This, too, should
   // be in the tablegen stuff later.
@@ -125,6 +124,10 @@
   // FIXME: -fdiagnostics-show-option
   // FIXME: -Wfatal-errors / -Wfatal-errors=foo
 
+  /// ControlledOptions - 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];
@@ -183,8 +186,53 @@
     }
     
     // Option exists, poke all the members of its diagnostic set.
-    for (unsigned i = 0, e = Found->NumMembers; i != e; ++i)
-      Diags.setDiagnosticMapping(Found->Members[i], Mapping);
+    for (const diag::kind *Member = Found->Members,
+         *E = Found->Members+Found->NumMembers; Member != E; ++Member) {
+      Diags.setDiagnosticMapping(*Member, Mapping);
+      assert(*Member < 65536 && "ControlledOptions element too small");
+      ControlledDiags.push_back(*Member);
+    }
+  }
+
+  // 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
+    // ControlledOptions 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);
+    }
   }
+  
   return false;
 }





More information about the cfe-commits mailing list