]> granicus.if.org Git - clang/commitdiff
Implement DR85: Redeclaration of member is forbidden
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 11 Jun 2013 03:51:23 +0000 (03:51 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 11 Jun 2013 03:51:23 +0000 (03:51 +0000)
Disallow the existence of a declaration of a member class that isn't a
forward declaration before it's definition.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/CXX/drs/dr0xx.cpp
test/SemaCXX/access.cpp
test/SemaTemplate/dependent-names.cpp
test/SemaTemplate/instantiate-member-class.cpp
www/cxx_dr_status.html

index c476ac906eeef2c1b4bf64783553b7794dbf4de3..302ec8b08cde404dd649d494e6d4b5a05cfff6af 100644 (file)
@@ -4241,6 +4241,8 @@ def note_enum_specialized_here : Note<
   "enum %0 was explicitly specialized here">;
 
 def err_member_redeclared : Error<"class member cannot be redeclared">;
+def ext_member_redeclared : ExtWarn<"class member cannot be redeclared">,
+  InGroup<GNU>;
 def err_member_redeclared_in_instantiation : Error<
   "multiple overloads of %0 instantiate to the same signature %1">;
 def err_member_name_of_class : Error<"member %0 has the same name as its class">;
index c17328d9cff23a28011976e972ba435c20d1ac96..c519bfa9ca4eddbcd1ad6a3a385c3c57cb19d89c 100644 (file)
@@ -9885,6 +9885,16 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
             return TUK == TUK_Declaration ? PrevTagDecl : 0;
         }
 
+        // C++11 [class.mem]p1:
+        //   A member shall not be declared twice in the member-speciļ¬cation,
+        //   except that a nested class or member class template can be declared
+        //   and then later defined.
+        if (TUK == TUK_Declaration && PrevDecl->isCXXClassMember() &&
+            S->isDeclScope(PrevDecl)) {
+          Diag(NameLoc, diag::ext_member_redeclared);
+          Diag(PrevTagDecl->getLocation(), diag::note_previous_declaration);
+        }
+
         if (!Invalid) {
           // If this is a use, just return the declaration we found.
 
index 7ff199d0b1f362820ae42a86dbafd90475714393..5ffc7516f5d61ddf1f495e2734e014c01f13955e 100644 (file)
@@ -862,15 +862,31 @@ namespace dr84 { // dr84: yes
   B b = a; // expected-error {{no viable}}
 }
 
-namespace dr85 { // dr85: no
+namespace dr85 { // dr85: yes
   struct A {
     struct B;
-    struct B {};
-    // FIXME: This redeclaration is invalid. Per [class.mem]p1,
-    //   "A member shall not be declared twice in the member-specification,
-    //   except that a nested class [...] can be declared then later defined"
-    // This is not that case.
-    struct B;
+    struct B {}; // expected-note{{previous declaration is here}}
+    struct B; // expected-error{{class member cannot be redeclared}}
+
+    union U;
+    union U {}; // expected-note{{previous declaration is here}}
+    union U; // expected-error{{class member cannot be redeclared}}
+
+#if __cplusplus >= 201103L
+    enum E1 : int;
+    enum E1 : int { e1 }; // expected-note{{previous declaration is here}}
+    enum E1 : int; // expected-error{{class member cannot be redeclared}}
+
+    enum class E2;
+    enum class E2 { e2 }; // expected-note{{previous declaration is here}}
+    enum class E2; // expected-error{{class member cannot be redeclared}}
+#endif
+  };
+
+  template <typename T>
+  struct C {
+    struct B {}; // expected-note{{previous declaration is here}}
+    struct B; // expected-error{{class member cannot be redeclared}}
   };
 }
 
index 50f2eff87bfb46784932f6d19b127180269ac2d2..fa89ce6b13f4c0b9ce9a8700a2f7775164e5251c 100644 (file)
@@ -26,9 +26,11 @@ private:
 namespace test1 {
   class A {
   private:
-    class X; // expected-note {{previously declared 'private' here}}
+    class X; // expected-note {{previously declared 'private' here}} \
+             // expected-note {{previous declaration is here}}
   public:
-    class X; // expected-error {{'X' redeclared with 'public' access}}
+    class X; // expected-error {{'X' redeclared with 'public' access}} \
+             // expected-warning {{class member cannot be redeclared}}
     class X {};
   };
 }
index fa47ef535815fecb96133829f17ddc60d36f6ab0..769584d93caeeb40ab29db1368b5a5560ec32808 100644 (file)
@@ -354,7 +354,6 @@ namespace rdar12629723 {
     struct A : public B {  // expected-note{{'rdar12629723::X::A' declared here}}
       virtual void foo() { }
     };
-    struct B;
 
     struct D : T::foo { };
     struct E : D { };
index 7b42a27d6b2cac68e5f8e84b788256c0b0fdc810..3f49606b86e55932d281b1dbe25ccfc1beb19d40 100644 (file)
@@ -91,13 +91,11 @@ namespace test2 {
       typedef int X;
     };
     typename Foo::X x;
-    class Foo;
   };
   template class B<int>;
 
   template <typename T> class C {
     class Foo;
-    class Foo;
   };
   template <typename T> class C<T>::Foo {
     int x;
index e782181c77881f76f1e9b155fadfb18b8170cf37..7ec46ab8b042d69547e6d65f8240b265e6ffbe21 100644 (file)
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#85">85</a></td>
     <td>TC1</td>
     <td>Redeclaration of member class</td>
-    <td class="none" align="center">No</td>
+    <td class="full" align="center">Yes</td>
   </tr>
   <tr>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#86">86</a></td>