summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-07-06 01:45:27 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-07-06 01:45:27 +0000
commit88fe69ce210ecbec9f4850aed2c56074ef310437 (patch)
treee4856ac18a5b883c9b935d133bda1ec4286d9b95
parenta60a6db73f36f72ed7ad1474b713630d938c42eb (diff)
downloadbcm5719-llvm-88fe69ce210ecbec9f4850aed2c56074ef310437.tar.gz
bcm5719-llvm-88fe69ce210ecbec9f4850aed2c56074ef310437.zip
DR1909: Diagnose all invalid cases of a class member sharing its name with the class.
llvm-svn: 241425
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp9
-rw-r--r--clang/lib/Sema/SemaDecl.cpp17
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp10
-rw-r--r--clang/test/CXX/class/class.mem/p13.cpp41
-rw-r--r--clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp6
-rw-r--r--clang/test/CXX/drs/dr19xx.cpp15
-rw-r--r--clang/test/CXX/drs/dr3xx.cpp12
-rw-r--r--clang/test/SemaCXX/alias-template.cpp6
-rw-r--r--clang/test/SemaCXX/struct-class-redecl.cpp4
-rw-r--r--clang/test/SemaTemplate/injected-class-name.cpp6
-rw-r--r--clang/www/cxx_dr_status.html4
11 files changed, 90 insertions, 40 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 568896db42b..d5360b54793 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -543,10 +543,11 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
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;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3c0e83c5a25..2618eb529af 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -11560,6 +11560,14 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
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, Decl *theEnumDecl, Decl *lastEnumConst,
// 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);
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index f4740a5cd85..79df1f210e6 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -893,6 +893,16 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
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);
}
diff --git a/clang/test/CXX/class/class.mem/p13.cpp b/clang/test/CXX/class/class.mem/p13.cpp
index 84885848870..1d7b9bc8155 100644
--- a/clang/test/CXX/class/class.mem/p13.cpp
+++ b/clang/test/CXX/class/class.mem/p13.cpp
@@ -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 {
};
};
};
-
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
index 865abb081a4..20b5104f83b 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp
@@ -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
diff --git a/clang/test/CXX/drs/dr19xx.cpp b/clang/test/CXX/drs/dr19xx.cpp
index 9c2d3e7c177..368e7b34165 100644
--- a/clang/test/CXX/drs/dr19xx.cpp
+++ b/clang/test/CXX/drs/dr19xx.cpp
@@ -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 {
diff --git a/clang/test/CXX/drs/dr3xx.cpp b/clang/test/CXX/drs/dr3xx.cpp
index 5ac4f013b7f..c438fccebd6 100644
--- a/clang/test/CXX/drs/dr3xx.cpp
+++ b/clang/test/CXX/drs/dr3xx.cpp
@@ -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@-2 {{ambiguous}}
- // expected-note@-6 {{here}}
- // expected-note@-6 {{here}}
-#endif
-
#if __cplusplus >= 201103L
struct Y {
template<typename T> using T1 = Y;
diff --git a/clang/test/SemaCXX/alias-template.cpp b/clang/test/SemaCXX/alias-template.cpp
index 89efc501d82..d5eb27a6613 100644
--- a/clang/test/SemaCXX/alias-template.cpp
+++ b/clang/test/SemaCXX/alias-template.cpp
@@ -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
diff --git a/clang/test/SemaCXX/struct-class-redecl.cpp b/clang/test/SemaCXX/struct-class-redecl.cpp
index 706ec5688ba..7375319186a 100644
--- a/clang/test/SemaCXX/struct-class-redecl.cpp
+++ b/clang/test/SemaCXX/struct-class-redecl.cpp
@@ -8,8 +8,8 @@ template<typename T> struct Y; // expected-note{{did you mean class here?}}
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}}
};
};
diff --git a/clang/test/SemaTemplate/injected-class-name.cpp b/clang/test/SemaTemplate/injected-class-name.cpp
index 4c21d2585d3..7349fdf392d 100644
--- a/clang/test/SemaTemplate/injected-class-name.cpp
+++ b/clang/test/SemaTemplate/injected-class-name.cpp
@@ -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}}
+ };
+}
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index a43e804a5ea..eaea88ca862 100644
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -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>
OpenPOWER on IntegriCloud