]> granicus.if.org Git - clang/commitdiff
Downgrade bogus ExtWarn on duplicate 'friend' specifier to a Warning, and add a
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 10 Jan 2014 21:27:55 +0000 (21:27 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 10 Jan 2014 21:27:55 +0000 (21:27 +0000)
Warning for a duplicate 'constexpr' specifier.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@198956 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/DeclSpec.cpp
test/Parser/cxx-decl.cpp
test/Parser/cxx0x-decl.cpp

index d23df82be50dbdf309c4ef19adddd75c3385fc90..214599c481b1957c6cb1ed18e63292c80c7c98cc 100644 (file)
@@ -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;
index 8c4c6175f5c5dab9b8d0e316620351f5757a6971..cc429f6070c095f6fbbe747cf4d6b6cea35a9d3a 100644 (file)
@@ -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}} \
index 257c56c9ce98146143956bf061583fcf2d18a519..f91ed311788e22abe5f2691ee6de96d9869efdae 100644 (file)
@@ -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}}
+  };
+}