From: David Majnemer Date: Tue, 11 Jun 2013 03:51:23 +0000 (+0000) Subject: Implement DR85: Redeclaration of member is forbidden X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2ec2b8459392f3f2f00d816b40e73113d444d838;p=clang Implement DR85: Redeclaration of member is forbidden 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 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index c476ac906e..302ec8b08c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; 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">; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c17328d9cf..c519bfa9ca 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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-specification, + // 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. diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp index 7ff199d0b1..5ffc7516f5 100644 --- a/test/CXX/drs/dr0xx.cpp +++ b/test/CXX/drs/dr0xx.cpp @@ -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 + struct C { + struct B {}; // expected-note{{previous declaration is here}} + struct B; // expected-error{{class member cannot be redeclared}} }; } diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp index 50f2eff87b..fa89ce6b13 100644 --- a/test/SemaCXX/access.cpp +++ b/test/SemaCXX/access.cpp @@ -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 {}; }; } diff --git a/test/SemaTemplate/dependent-names.cpp b/test/SemaTemplate/dependent-names.cpp index fa47ef5358..769584d93c 100644 --- a/test/SemaTemplate/dependent-names.cpp +++ b/test/SemaTemplate/dependent-names.cpp @@ -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 { }; diff --git a/test/SemaTemplate/instantiate-member-class.cpp b/test/SemaTemplate/instantiate-member-class.cpp index 7b42a27d6b..3f49606b86 100644 --- a/test/SemaTemplate/instantiate-member-class.cpp +++ b/test/SemaTemplate/instantiate-member-class.cpp @@ -91,13 +91,11 @@ namespace test2 { typedef int X; }; typename Foo::X x; - class Foo; }; template class B; template class C { class Foo; - class Foo; }; template class C::Foo { int x; diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html index e782181c77..7ec46ab8b0 100644 --- a/www/cxx_dr_status.html +++ b/www/cxx_dr_status.html @@ -548,7 +548,7 @@ 85 TC1 Redeclaration of member class - No + Yes 86