forked from OSchip/llvm-project
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:
parent
70eed364fc
commit
9f9518265f
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}}
|
||||
};
|
||||
|
|
|
@ -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}}
|
||||
|
||||
|
|
Loading…
Reference in New Issue