Splitting the duplicated decl spec extension warning into two: one is an ExtWarn and the other a vanilla warning.  This addresses PR13705, where const char const * wouldn't warn unless -pedantic was specified under the right conditions.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162793 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 4ce43e0..5f48cc7 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -197,6 +197,7 @@
 def StrncatSize : DiagGroup<"strncat-size">;
 def TautologicalCompare : DiagGroup<"tautological-compare">;
 def HeaderHygiene : DiagGroup<"header-hygiene">;
+def DuplicateDeclSpecifiers : DiagGroup<"duplicate-decl-specifiers">;
 
 // Preprocessor warnings.
 def : DiagGroup<"builtin-macro-redefined">;
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index a9c0a17..feae2d0 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -43,7 +43,10 @@
   "extra ';' after member function definition">,
   InGroup<ExtraSemi>, DefaultIgnore;
 
-def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">;
+def ext_duplicate_declspec : ExtWarn<"duplicate '%0' declaration specifier">,
+  InGroup<DuplicateDeclSpecifiers>;
+def warn_duplicate_declspec : Warning<"duplicate '%0' declaration specifier">,
+  InGroup<DuplicateDeclSpecifiers>;
 def ext_plain_complex : ExtWarn<
   "plain '_Complex' requires a type specifier; assuming '_Complex double'">;
 def ext_integer_complex : Extension<
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index d12ca78..e8ce9ac 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -325,10 +325,14 @@
 
 template <class T> static bool BadSpecifier(T TNew, T TPrev,
                                             const char *&PrevSpec,
-                                            unsigned &DiagID) {
+                                            unsigned &DiagID,
+                                            bool IsExtension = true) {
   PrevSpec = DeclSpec::getSpecifierName(TPrev);
-  DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec
-            : diag::err_invalid_decl_spec_combination);
+  if (TNew != TPrev)
+    DiagID = diag::err_invalid_decl_spec_combination;
+  else
+    DiagID = IsExtension ? diag::ext_duplicate_declspec : 
+                           diag::warn_duplicate_declspec;    
   return true;
 }
 
@@ -673,9 +677,15 @@
                            unsigned &DiagID, const LangOptions &Lang,
                            bool IsTypeSpec) {
   // Duplicates are permitted in C99, and are permitted in C++11 unless the
-  // cv-qualifier appears as a type-specifier.
-  if ((TypeQualifiers & T) && !Lang.C99 && (!Lang.CPlusPlus0x || IsTypeSpec))
-    return BadSpecifier(T, T, PrevSpec, DiagID);
+  // cv-qualifier appears as a type-specifier.  However, since this is likely 
+  // not what the user intended, we will always warn.  We do not need to set the
+  // qualifier's location since we already have it.
+  if (TypeQualifiers & T) {
+    bool IsExtension = false;
+    if (Lang.C99 || (Lang.CPlusPlus0x && !IsTypeSpec))
+      IsExtension = true;
+    return BadSpecifier(T, T, PrevSpec, DiagID, IsExtension);
+  }
   TypeQualifiers |= T;
 
   switch (T) {
diff --git a/test/Misc/warning-flags.c b/test/Misc/warning-flags.c
index 06c70eb..5968851 100644
--- a/test/Misc/warning-flags.c
+++ b/test/Misc/warning-flags.c
@@ -181,4 +181,4 @@
 
 The list of warnings in -Wpedantic should NEVER grow.
 
-CHECK: Number in -Wpedantic (not covered by other -W flags): 39
+CHECK: Number in -Wpedantic (not covered by other -W flags): 38
diff --git a/test/Parser/cxx-decl.cpp b/test/Parser/cxx-decl.cpp
index 30ac279..290b947 100644
--- a/test/Parser/cxx-decl.cpp
+++ b/test/Parser/cxx-decl.cpp
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -pedantic %s
 
+const char const *x10; // expected-warning {{duplicate 'const' declaration specifier}}
+
 int x(*g); // expected-error {{use of undeclared identifier 'g'}}
 
 struct Type {
diff --git a/test/Parser/cxx0x-decl.cpp b/test/Parser/cxx0x-decl.cpp
index a6fc49c..e97ba1e 100644
--- a/test/Parser/cxx0x-decl.cpp
+++ b/test/Parser/cxx0x-decl.cpp
@@ -26,5 +26,7 @@
   void i() = delete;;; // expected-warning {{extra ';' after member function definition}}
 };
 
-int *const const p = 0; // ok
+// This is technically okay, but not likely what the user expects, so we will
+// pedantically warn on it
+int *const const p = 0; // expected-warning {{duplicate 'const' declaration specifier}}
 const const int *q = 0; // expected-warning {{duplicate 'const' declaration specifier}}