diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 046ce70a343b..029c1182f26e 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2440,10 +2440,9 @@ class IndirectFieldDecl : public ValueDecl, 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, diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 42bebc543e3e..797e07b4b78b 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4024,16 +4024,26 @@ EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { 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); } diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 16394e865eb1..72587e388e47 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -569,7 +569,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Var: case ImplicitParam: case ParmVar: - case NonTypeTemplateParm: case ObjCMethod: case ObjCProperty: case MSProperty: @@ -579,6 +578,12 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { 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; diff --git a/clang/test/CXX/class/class.union/class.union.anon/p1.cpp b/clang/test/CXX/class/class.union/class.union.anon/p1.cpp index 7fef4c5d172c..31c9313cf53a 100644 --- a/clang/test/CXX/class/class.union/class.union.anon/p1.cpp +++ b/clang/test/CXX/class/class.union/class.union.anon/p1.cpp @@ -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}} }; diff --git a/clang/test/CXX/temp/temp.res/temp.local/p6.cpp b/clang/test/CXX/temp/temp.res/temp.local/p6.cpp index 06eb1bef7fea..843b45543fcf 100644 --- a/clang/test/CXX/temp/temp.res/temp.local/p6.cpp +++ b/clang/test/CXX/temp/temp.res/temp.local/p6.cpp @@ -5,7 +5,7 @@ namespace N {} template struct X {}; // expected-error {{declaration of 'T' shadows template parameter}} -template struct Y { // expected-note 16{{declared here}} +template struct Y { // expected-note 17{{declared here}} template struct A {}; // expected-error {{declaration of 'T' shadows template parameter}} struct B { @@ -56,9 +56,74 @@ template struct Y { // expected-note 16{{declared here}} 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 struct Z { // expected-note 15{{declared here}} + template struct A {}; // expected-error {{declaration of 'T' shadows template parameter}} + + struct B { + template struct T {}; // FIXME: desired-error {{declaration of 'T' shadows template parameter}} + }; + struct C { + template 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 // expected-note {{declared here}} void f(int T) {} // expected-error {{declaration of 'T' shadows template parameter}}