When instantiating anonymous structs/unions within a function, make

sure that the anonymous struct/union record declaration gets
instantiated before the variable declaration, and that it and its
fields (recursively) get entries in the local instantiation map. Fixes
PR7088.

llvm-svn: 104305
This commit is contained in:
Douglas Gregor 2010-05-21 00:31:19 +00:00
parent 95dff818e7
commit 04163186a7
2 changed files with 36 additions and 1 deletions

View File

@ -323,6 +323,13 @@ static bool InstantiateInitializer(Sema &S, Expr *Init,
} }
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
// If this is the variable for an anonymous struct or union,
// instantiate the anonymous struct/union type first.
if (const RecordType *RecordTy = D->getType()->getAs<RecordType>())
if (RecordTy->getDecl()->isAnonymousStructOrUnion())
if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl())))
return 0;
// Do substitution on the type of the declaration // Do substitution on the type of the declaration
TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(),
TemplateArgs, TemplateArgs,
@ -491,6 +498,11 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
// Keep track of where this decl came from. // Keep track of where this decl came from.
SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D); SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D);
} }
if (CXXRecordDecl *Parent= dyn_cast<CXXRecordDecl>(Field->getDeclContext())) {
if (Parent->isAnonymousStructOrUnion() &&
Parent->getLookupContext()->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Field);
}
Field->setImplicit(D->isImplicit()); Field->setImplicit(D->isImplicit());
Field->setAccess(D->getAccess()); Field->setAccess(D->getAccess());
@ -913,7 +925,12 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
if (Decl::FriendObjectKind FOK = D->getFriendObjectKind()) if (Decl::FriendObjectKind FOK = D->getFriendObjectKind())
Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared); Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared);
Record->setAnonymousStructOrUnion(D->isAnonymousStructOrUnion()); // Make sure that anonymous structs and unions are recorded.
if (D->isAnonymousStructOrUnion()) {
Record->setAnonymousStructOrUnion(true);
if (Record->getDeclContext()->getLookupContext()->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record);
}
Owner->addDecl(Record); Owner->addDecl(Record);
return Record; return Record;

View File

@ -29,3 +29,21 @@ template <typename T> struct C {
}; };
C<int> c0(0); C<int> c0(0);
namespace PR7088 {
template<typename T>
void f() {
union {
int a;
union {
float real;
T d;
};
};
a = 17;
d = 3.14;
}
template void f<double>();
}