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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits