diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2012-08-28 20:55:40 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2012-08-28 20:55:40 +0000 |
commit | c828620a03b20835a376f6f456a72e44599f4f87 (patch) | |
tree | 58b4cb1bb4448d8661c99181be47c34f8cd4aa15 | |
parent | 827eeb63614309bafac9d77a5a3a7ca81f1e4751 (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.td | 1 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 5 | ||||
-rw-r--r-- | lib/Sema/DeclSpec.cpp | 22 | ||||
-rw-r--r-- | test/Misc/warning-flags.c | 2 | ||||
-rw-r--r-- | test/Parser/cxx-decl.cpp | 2 | ||||
-rw-r--r-- | test/Parser/cxx0x-decl.cpp | 4 |
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}} |