r241425 - DR1909: Diagnose all invalid cases of a class member sharing its name with the class.

Richard Smith richard-llvm at metafoo.co.uk
Sun Jul 5 18:45:27 PDT 2015


Author: rsmith
Date: Sun Jul  5 20:45:27 2015
New Revision: 241425

URL: http://llvm.org/viewvc/llvm-project?rev=241425&view=rev
Log:
DR1909: Diagnose all invalid cases of a class member sharing its name with the class.

Modified:
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/class/class.mem/p13.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
    cfe/trunk/test/CXX/drs/dr19xx.cpp
    cfe/trunk/test/CXX/drs/dr3xx.cpp
    cfe/trunk/test/SemaCXX/alias-template.cpp
    cfe/trunk/test/SemaCXX/struct-class-redecl.cpp
    cfe/trunk/test/SemaTemplate/injected-class-name.cpp
    cfe/trunk/www/cxx_dr_status.html

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sun Jul  5 20:45:27 2015
@@ -543,10 +543,11 @@ Decl *Parser::ParseUsingDeclaration(unsi
     SourceLocation IdLoc = ConsumeToken();
     ParsedType Type = Actions.getInheritingConstructorName(SS, IdLoc, *LastII);
     Name.setConstructorName(Type, IdLoc, IdLoc);
-  } else if (ParseUnqualifiedId(SS, /*EnteringContext=*/ false,
-                                /*AllowDestructorName=*/ true,
-                                /*AllowConstructorName=*/ true, ParsedType(),
-                                TemplateKWLoc, Name)) {
+  } else if (ParseUnqualifiedId(
+                 SS, /*EnteringContext=*/false,
+                 /*AllowDestructorName=*/true,
+                 /*AllowConstructorName=*/NextToken().isNot(tok::equal),
+                 ParsedType(), TemplateKWLoc, Name)) {
     SkipUntil(tok::semi);
     return nullptr;
   }

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Jul  5 20:45:27 2015
@@ -11560,6 +11560,14 @@ Decl *Sema::ActOnTag(Scope *S, unsigned
       goto CreateNewDecl;
     }
   } else if (Name) {
+    // C++14 [class.mem]p14:
+    //   If T is the name of a class, then each of the following shall have a
+    //   name different from T:
+    //    -- every member of class T that is itself a type
+    if (TUK != TUK_Reference && TUK != TUK_Friend &&
+        DiagnoseClassNameShadow(SearchDC, DeclarationNameInfo(Name, NameLoc)))
+      return nullptr;
+
     // If this is a named struct, check to see if there was a previous forward
     // declaration or definition.
     // FIXME: We're looking into outer scopes here, even when we
@@ -13620,12 +13628,9 @@ Decl *Sema::ActOnEnumConstant(Scope *S,
   // different from T:
   // - every enumerator of every member of class T that is an unscoped 
   // enumerated type
-  if (CXXRecordDecl *Record
-                      = dyn_cast<CXXRecordDecl>(
-                             TheEnumDecl->getDeclContext()->getRedeclContext()))
-    if (!TheEnumDecl->isScoped() && 
-        Record->getIdentifier() && Record->getIdentifier() == Id)
-      Diag(IdLoc, diag::err_member_name_of_class) << Id;
+  if (!TheEnumDecl->isScoped())
+    DiagnoseClassNameShadow(TheEnumDecl->getDeclContext(),
+                            DeclarationNameInfo(Id, IdLoc));
   
   EnumConstantDecl *New =
     CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val);

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sun Jul  5 20:45:27 2015
@@ -893,6 +893,16 @@ Sema::CheckClassTemplate(Scope *S, unsig
     LookupQualifiedName(Previous, SemanticContext);
   } else {
     SemanticContext = CurContext;
+
+    // C++14 [class.mem]p14:
+    //   If T is the name of a class, then each of the following shall have a
+    //   name different from T:
+    //    -- every member template of class T
+    if (TUK != TUK_Friend &&
+        DiagnoseClassNameShadow(SemanticContext,
+                                DeclarationNameInfo(Name, NameLoc)))
+      return true;
+
     LookupName(Previous, S);
   }
 

Modified: cfe/trunk/test/CXX/class/class.mem/p13.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.mem/p13.cpp?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class/class.mem/p13.cpp (original)
+++ cfe/trunk/test/CXX/class/class.mem/p13.cpp Sun Jul  5 20:45:27 2015
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s
 
 // If T is the name of a class, then each of the following shall have
 // a name different from T:
@@ -9,23 +9,53 @@ struct X0 {
 };
 
 // - every member function of class T
-// (Cannot be tested)
+struct Xa {
+  int Xa() {} // expected-error{{constructor cannot have a return type}}
+};
 
 // - every member of class T that is itself a type;
-struct X1 { // expected-note{{previous use is here}}
-  enum X1 { }; // expected-error{{use of 'X1' with tag type that does not match previous declaration}}
+struct X1 {
+  enum X1 { }; // expected-error{{member 'X1' has the same name as its class}}
+};
+
+struct X1a {
+  struct X1a; // expected-error{{member 'X1a' has the same name as its class}}
 };
 
 struct X2 {
   typedef int X2; // expected-error{{member 'X2' has the same name as its class}}
 };
 
-// - every enumerator of every member of class T that is an enumerated type; and
+struct X2a {
+  using X2a = int; // expected-error{{member 'X2a' has the same name as its class}}
+};
+
+// - every member template of class T
+
+struct X2b {
+  template<typename T> struct X2b; // expected-error{{member 'X2b' has the same name as its class}}
+};
+struct X2c {
+  template<typename T> void X2c(); // expected-error{{constructor cannot have a return type}}
+};
+struct X2d {
+  template<typename T> static int X2d; // expected-error{{member 'X2d' has the same name as its class}}
+};
+struct X2e {
+  template<typename T> using X2e = int; // expected-error{{member 'X2e' has the same name as its class}}
+};
+
+// - every enumerator of every member of class T that is an unscoped enumerated type; and
 struct X3 {
   enum E {
     X3 // expected-error{{member 'X3' has the same name as its class}}
   };
 };
+struct X3a {
+  enum class E {
+    X3a // ok
+  };
+};
 
 // - every member of every anonymous union that is a member of class T.
 struct X4 {
@@ -37,4 +67,3 @@ struct X4 {
     };
   };
 };
-

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp Sun Jul  5 20:45:27 2015
@@ -83,12 +83,10 @@ namespace InFunctions {
 
 namespace ClassNameRedecl {
   class C0 {
-    // FIXME: this diagnostic is pretty poor
-    using C0 = int; // expected-error {{name defined in alias declaration must be an identifier}}
+    using C0 = int; // expected-error {{member 'C0' has the same name as its class}}
   };
   class C1 {
-    // FIXME: this diagnostic is pretty poor
-    using C1 = C1; // expected-error {{name defined in alias declaration must be an identifier}}
+    using C1 = C1; // expected-error {{member 'C1' has the same name as its class}}
   };
   class C2 {
     using C0 = C1; // ok

Modified: cfe/trunk/test/CXX/drs/dr19xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr19xx.cpp?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr19xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr19xx.cpp Sun Jul  5 20:45:27 2015
@@ -39,6 +39,21 @@ namespace dr1902 { // dr1902: 3.7
 #endif
 }
 
+namespace dr1909 { // dr1909: yes
+  struct A {
+    template<typename T> struct A {}; // expected-error {{member 'A' has the same name as its class}}
+  };
+  struct B {
+    template<typename T> void B() {} // expected-error {{constructor cannot have a return type}}
+  };
+  struct C {
+    template<typename T> static int C; // expected-error {{member 'C' has the same name as its class}} expected-error 0-1{{extension}}
+  };
+  struct D {
+    template<typename T> using D = int; // expected-error {{member 'D' has the same name as its class}} expected-error 0-1{{extension}}
+  };
+}
+
 #if __cplusplus >= 201103L
 namespace dr1940 { // dr1940: yes
 static union {

Modified: cfe/trunk/test/CXX/drs/dr3xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr3xx.cpp?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr3xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr3xx.cpp Sun Jul  5 20:45:27 2015
@@ -110,18 +110,6 @@ namespace dr305 { // dr305: no
     x->~X<char>(); // expected-error {{no member named}}
   }
 
-  // FIXME: This appears to be valid (but allowing the nested types might be a
-  // defect).
-  template<typename> struct Nested {
-    template<typename> struct Nested {};
-  };
-  void testNested(Nested<int> n) { n.~Nested<int>(); } // expected-error {{no member named}}
-#if __cplusplus < 201103L
-  // expected-error at -2 {{ambiguous}}
-  // expected-note at -6 {{here}}
-  // expected-note at -6 {{here}}
-#endif
-
 #if __cplusplus >= 201103L
   struct Y {
     template<typename T> using T1 = Y;

Modified: cfe/trunk/test/SemaCXX/alias-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/alias-template.cpp?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/alias-template.cpp (original)
+++ cfe/trunk/test/SemaCXX/alias-template.cpp Sun Jul  5 20:45:27 2015
@@ -68,12 +68,10 @@ namespace InFunctions {
 
 namespace ClassNameRedecl {
   class C0 {
-    // FIXME: this diagnostic is pretty poor
-    template<typename U> using C0 = int; // expected-error {{name defined in alias declaration must be an identifier}}
+    template<typename U> using C0 = int; // expected-error {{member 'C0' has the same name as its class}}
   };
   class C1 {
-    // FIXME: this diagnostic is pretty poor
-    template<typename U> using C1 = C1; // expected-error {{name defined in alias declaration must be an identifier}}
+    template<typename U> using C1 = C1; // expected-error {{member 'C1' has the same name as its class}}
   };
   class C2 {
     template<typename U> using C0 = C1; // ok

Modified: cfe/trunk/test/SemaCXX/struct-class-redecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/struct-class-redecl.cpp?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/struct-class-redecl.cpp (original)
+++ cfe/trunk/test/SemaCXX/struct-class-redecl.cpp Sun Jul  5 20:45:27 2015
@@ -8,8 +8,8 @@ template<typename T> struct Y; // expect
 template<class U> class Y { }; // expected-warning{{previously declared}}
 
 template <typename>
-struct Z {   // expected-note{{previous definition is here}}
-  struct Z { // expected-error{{nested redefinition of 'Z'}}
+struct Z {
+  struct Z { // expected-error{{member 'Z' has the same name as its class}}
   };
 };
 

Modified: cfe/trunk/test/SemaTemplate/injected-class-name.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/injected-class-name.cpp?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/injected-class-name.cpp (original)
+++ cfe/trunk/test/SemaTemplate/injected-class-name.cpp Sun Jul  5 20:45:27 2015
@@ -60,3 +60,9 @@ namespace ForwardDecls {
     typename xt::foo *t;
   };
 }
+
+namespace ConflictingRedecl {
+  template<typename> struct Nested {
+    template<typename> struct Nested; // expected-error {{member 'Nested' has the same name as its class}}
+  };
+}

Modified: cfe/trunk/www/cxx_dr_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_status.html?rev=241425&r1=241424&r2=241425&view=diff
==============================================================================
--- cfe/trunk/www/cxx_dr_status.html (original)
+++ cfe/trunk/www/cxx_dr_status.html Sun Jul  5 20:45:27 2015
@@ -5503,7 +5503,7 @@ and <I>POD class</I></td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#948">948</a></td>
     <td>C++11</td>
     <td><TT>constexpr</TT> in <I>condition</I>s</td>
-    <td class="none" align="center">Unknown</td>
+    <td class="svn" align="center">SVN</td>
   </tr>
   <tr class="open" id="949">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#949">949</a></td>
@@ -11269,7 +11269,7 @@ and <I>POD class</I></td>
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1909">1909</a></td>
     <td>DR</td>
     <td>Member class template with the same name as the class</td>
-    <td class="none" align="center">Unknown</td>
+    <td class="full" align="center">Yes</td>
   </tr>
   <tr class="open" id="1910">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1910">1910</a></td>





More information about the cfe-commits mailing list