aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2012-08-28 20:55:40 +0000
committerAaron Ballman <aaron@aaronballman.com>2012-08-28 20:55:40 +0000
commitc828620a03b20835a376f6f456a72e44599f4f87 (patch)
tree58b4cb1bb4448d8661c99181be47c34f8cd4aa15
parent827eeb63614309bafac9d77a5a3a7ca81f1e4751 (diff)
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
-rw-r--r--include/clang/Basic/DiagnosticGroups.td1
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td5
-rw-r--r--lib/Sema/DeclSpec.cpp22
-rw-r--r--test/Misc/warning-flags.c2
-rw-r--r--test/Parser/cxx-decl.cpp2
-rw-r--r--test/Parser/cxx0x-decl.cpp4
6 files changed, 27 insertions, 9 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 4ce43e0d62..5f48cc7e12 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -197,6 +197,7 @@ def StringPlusInt : DiagGroup<"string-plus-int">;
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 a9c0a1752c..feae2d0a5e 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -43,7 +43,10 @@ def warn_extra_semi_after_mem_fn_def : Warning<
"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 d12ca78390..e8ce9ac01c 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -325,10 +325,14 @@ unsigned DeclSpec::getParsedSpecifiers() const {
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 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
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 06c70eb57c..5968851d09 100644
--- a/test/Misc/warning-flags.c
+++ b/test/Misc/warning-flags.c
@@ -181,4 +181,4 @@ CHECK-NEXT: warn_weak_import
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 30ac2794ab..290b947de2 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 a6fc49cb9e..e97ba1ec90 100644
--- a/test/Parser/cxx0x-decl.cpp
+++ b/test/Parser/cxx0x-decl.cpp
@@ -26,5 +26,7 @@ class ExtraSemiAfterMemFn {
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}}