r256985 - PR26048, PR26050: put non-type template parameters and indirect field decls
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 6 14:49:11 PST 2016
Author: rsmith
Date: Wed Jan 6 16:49:11 2016
New Revision: 256985
URL: http://llvm.org/viewvc/llvm-project?rev=256985&view=rev
Log:
PR26048, PR26050: put non-type template parameters and indirect field decls
into IDNS_Tag in C++, because they conflict with redeclarations of tags. (This
doesn't affect elaborated-type-specifier lookup, which looks for IDNS_Type in
C++).
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/DeclBase.cpp
cfe/trunk/test/CXX/class/class.union/class.union.anon/p1.cpp
cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=256985&r1=256984&r2=256985&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Jan 6 16:49:11 2016
@@ -2440,10 +2440,9 @@ class IndirectFieldDecl : public ValueDe
NamedDecl **Chaining;
unsigned ChainingSize;
- IndirectFieldDecl(DeclContext *DC, SourceLocation L,
+ IndirectFieldDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T,
- NamedDecl **CH, unsigned CHS)
- : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {}
+ NamedDecl **CH, unsigned CHS);
public:
static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=256985&r1=256984&r2=256985&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Jan 6 16:49:11 2016
@@ -4024,16 +4024,26 @@ EnumConstantDecl::CreateDeserialized(AST
void IndirectFieldDecl::anchor() { }
+IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC,
+ SourceLocation L, DeclarationName N,
+ QualType T, NamedDecl **CH, unsigned CHS)
+ : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {
+ // In C++, indirect field declarations conflict with tag declarations in the
+ // same scope, so add them to IDNS_Tag so that tag redeclaration finds them.
+ if (C.getLangOpts().CPlusPlus)
+ IdentifierNamespace |= IDNS_Tag;
+}
+
IndirectFieldDecl *
IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, NamedDecl **CH,
unsigned CHS) {
- return new (C, DC) IndirectFieldDecl(DC, L, Id, T, CH, CHS);
+ return new (C, DC) IndirectFieldDecl(C, DC, L, Id, T, CH, CHS);
}
IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
unsigned ID) {
- return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(),
+ return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(),
DeclarationName(), QualType(), nullptr,
0);
}
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=256985&r1=256984&r2=256985&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Wed Jan 6 16:49:11 2016
@@ -569,7 +569,6 @@ unsigned Decl::getIdentifierNamespaceFor
case Var:
case ImplicitParam:
case ParmVar:
- case NonTypeTemplateParm:
case ObjCMethod:
case ObjCProperty:
case MSProperty:
@@ -579,6 +578,12 @@ unsigned Decl::getIdentifierNamespaceFor
case IndirectField:
return IDNS_Ordinary | IDNS_Member;
+ case NonTypeTemplateParm:
+ // Non-type template parameters are not found by lookups that ignore
+ // non-types, but they are found by redeclaration lookups for tag types,
+ // so we include them in the tag namespace.
+ return IDNS_Ordinary | IDNS_Tag;
+
case ObjCCompatibleAlias:
case ObjCInterface:
return IDNS_Ordinary | IDNS_Type;
Modified: cfe/trunk/test/CXX/class/class.union/class.union.anon/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.union/class.union.anon/p1.cpp?rev=256985&r1=256984&r2=256985&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class/class.union/class.union.anon/p1.cpp (original)
+++ cfe/trunk/test/CXX/class/class.union/class.union.anon/p1.cpp Wed Jan 6 16:49:11 2016
@@ -13,14 +13,12 @@ struct X {
int d; // expected-error {{member of anonymous union redeclares}}
int e; // expected-note {{previous}}
int f; // expected-note {{previous}}
- int g;
+ int g; // expected-note {{previous}}
int h; // expected-note {{previous}}
};
int e; // expected-error {{duplicate member}}
void f(); // expected-error {{redefinition}}
- // FIXME: This is ill-formed, even though one name is a tag and the other is
- // an anonymous union member. Reject this.
- struct g;
+ struct g; // expected-error {{redefinition}}
typedef int h; // expected-error {{redefinition}}
};
Modified: cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp?rev=256985&r1=256984&r2=256985&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.res/temp.local/p6.cpp Wed Jan 6 16:49:11 2016
@@ -5,7 +5,7 @@ namespace N {}
template<typename T, // expected-note {{declared here}}
typename T> struct X {}; // expected-error {{declaration of 'T' shadows template parameter}}
-template<typename T> struct Y { // expected-note 16{{declared here}}
+template<typename T> struct Y { // expected-note 17{{declared here}}
template<typename T> struct A {}; // expected-error {{declaration of 'T' shadows template parameter}}
struct B {
@@ -56,9 +56,74 @@ template<typename T> struct Y { // expec
namespace T = N; // expected-error {{declaration of 'T' shadows template parameter}}
}
+ // FIXME: These diagnostics are poorly worded. Lookup for the elaborated type
+ // specifier finds the template parameter in this case, which is ill-formed
+ // because it's not a struct.
+ void f() {
+ struct T *p; // expected-error {{declaration of 'T' shadows template parameter}}
+ }
friend struct T; // expected-error {{declaration of 'T' shadows template parameter}}
};
+template<int T> struct Z { // expected-note 15{{declared here}}
+ template<typename T> struct A {}; // expected-error {{declaration of 'T' shadows template parameter}}
+
+ struct B {
+ template<typename> struct T {}; // FIXME: desired-error {{declaration of 'T' shadows template parameter}}
+ };
+ struct C {
+ template<typename> void T(); // expected-error {{declaration of 'T' shadows template parameter}}
+ };
+ struct D {
+ struct T {}; // expected-error {{declaration of 'T' shadows template parameter}}
+ };
+ struct E {
+ typedef int T; // expected-error {{declaration of 'T' shadows template parameter}}
+ };
+ struct F {
+ using T = int; // expected-error {{declaration of 'T' shadows template parameter}}
+ };
+ struct G {
+ int T; // expected-error {{declaration of 'T' shadows template parameter}}
+ };
+ struct H {
+ static int T; // expected-error {{declaration of 'T' shadows template parameter}}
+ };
+ struct I {
+ void T(); // expected-error {{declaration of 'T' shadows template parameter}}
+ };
+ struct J {
+ enum T { e }; // expected-error {{declaration of 'T' shadows template parameter}}
+ };
+ struct K {
+ enum E { T }; // expected-error {{declaration of 'T' shadows template parameter}}
+ };
+
+ void a() {
+ extern int T; // expected-error {{declaration of 'T' shadows template parameter}}
+ }
+ void b() {
+ int T; // expected-error {{declaration of 'T' shadows template parameter}}
+ }
+ void c() {
+ try {}
+ catch (int T) {} // expected-error {{declaration of 'T' shadows template parameter}}
+ }
+ void d() {
+ void T(); // expected-error {{declaration of 'T' shadows template parameter}}
+ }
+ void e() {
+ namespace T = N; // expected-error {{declaration of 'T' shadows template parameter}}
+ }
+
+ // These cases are valid when 'T' is a non-type template parameter, as T
+ // names an injected struct ::T, which doesn't shadow the template parameter.
+ void f() {
+ struct T *p;
+ }
+ friend struct T;
+};
+
template<typename T> // expected-note {{declared here}}
void f(int T) {} // expected-error {{declaration of 'T' shadows template parameter}}
More information about the cfe-commits
mailing list