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}} +  }; +}  | 

