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++).

llvm-svn: 256985
This commit is contained in:
Richard Smith 2016-01-06 22:49:11 +00:00
parent 70eed364fc
commit 9f9518265f
5 changed files with 88 additions and 11 deletions

View File

@ -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,

View File

@ -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);
}

View File

@ -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;

View File

@ -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}}
};

View File

@ -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 { // 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<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}}