diff options
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 15 | ||||
-rw-r--r-- | clang/test/Parser/cxx-decl.cpp | 19 | ||||
-rw-r--r-- | clang/test/Parser/cxx0x-decl.cpp | 11 |
3 files changed, 37 insertions, 8 deletions
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index d23df82be50..214599c481b 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -827,7 +827,12 @@ bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { if (Friend_specified) { PrevSpec = "friend"; - DiagID = diag::ext_duplicate_declspec; + // Keep the later location, so that we can later diagnose ill-formed + // declarations like 'friend class X friend;'. Per [class.friend]p3, + // 'friend' must be the first token in a friend declaration that is + // not a function declaration. + FriendLoc = Loc; + DiagID = diag::warn_duplicate_declspec; return true; } @@ -850,7 +855,13 @@ bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec, bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { - // 'constexpr constexpr' is ok. + // 'constexpr constexpr' is ok, but warn as this is likely not what the user + // intended. + if (Constexpr_specified) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "constexpr"; + return true; + } Constexpr_specified = true; ConstexprLoc = Loc; return false; diff --git a/clang/test/Parser/cxx-decl.cpp b/clang/test/Parser/cxx-decl.cpp index 8c4c6175f5c..cc429f6070c 100644 --- a/clang/test/Parser/cxx-decl.cpp +++ b/clang/test/Parser/cxx-decl.cpp @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -pedantic -fcxx-exceptions -fexceptions %s +// RUN: %clang_cc1 -verify -fsyntax-only -triple i386-linux -pedantic-errors -fcxx-exceptions -fexceptions %s -const char const *x10; // expected-warning {{duplicate 'const' declaration specifier}} +const char const *x10; // expected-error {{duplicate 'const' declaration specifier}} int x(*g); // expected-error {{use of undeclared identifier 'g'}} @@ -46,7 +46,7 @@ class asm_class_test { void foo() __asm__("baz"); }; -enum { fooenum = 1, }; // expected-warning {{commas at the end of enumerator lists are a C++11 extension}} +enum { fooenum = 1, }; // expected-error {{commas at the end of enumerator lists are a C++11 extension}} struct a { int Type : fooenum; @@ -81,7 +81,7 @@ namespace Commas { (global5), *global6, &global7 = global1, - &&global8 = static_cast<int&&>(global1), // expected-warning 2{{rvalue reference}} + &&global8 = static_cast<int&&>(global1), // expected-error 2{{rvalue reference}} S::a, global9, global10 = 0, @@ -212,14 +212,14 @@ namespace PR5066 { template<typename T> struct X {}; X<int N> x; // expected-error {{type-id cannot have a name}} - using T = int (*T)(); // expected-error {{type-id cannot have a name}} expected-warning {{C++11}} + using T = int (*T)(); // expected-error {{type-id cannot have a name}} expected-error {{C++11}} } namespace PR17255 { void foo() { typename A::template B<>; // expected-error {{use of undeclared identifier 'A'}} \ // expected-error {{expected a qualified name after 'typename'}} \ - // expected-warning {{'template' keyword outside of a template}} + // expected-error {{'template' keyword outside of a template}} } } @@ -232,6 +232,13 @@ namespace PR17567 { FooBar::~FooBar() {} // expected-error {{undeclared}} expected-error {{expected the class name}} } +namespace DuplicateFriend { + struct A { + friend void friend f(); // expected-warning {{duplicate 'friend' declaration specifier}} + friend struct B friend; // expected-warning {{duplicate 'friend' declaration specifier}} + }; +} + // PR8380 extern "" // expected-error {{unknown linkage language}} test6a { ;// expected-error {{C++ requires a type specifier for all declarations}} \ diff --git a/clang/test/Parser/cxx0x-decl.cpp b/clang/test/Parser/cxx0x-decl.cpp index 257c56c9ce9..f91ed311788 100644 --- a/clang/test/Parser/cxx0x-decl.cpp +++ b/clang/test/Parser/cxx0x-decl.cpp @@ -104,3 +104,14 @@ namespace UsingDeclAttrs { using [[gnu::aligned(1)]] T = int; // expected-error {{an attribute list cannot appear here}} using T = int [[gnu::aligned(1)]]; // expected-error {{'aligned' attribute cannot be applied to types}} } + +namespace DuplicateSpecifier { + constexpr constexpr int f(); // expected-warning {{duplicate 'constexpr' declaration specifier}} + constexpr int constexpr a = 0; // expected-warning {{duplicate 'constexpr' declaration specifier}} + + struct A { + friend constexpr int constexpr friend f(); // expected-warning {{duplicate 'friend' declaration specifier}} \ + // expected-warning {{duplicate 'constexpr' declaration specifier}} + friend struct A friend; // expected-warning {{duplicate 'friend'}} expected-error {{'friend' must appear first}} + }; +} |