From 9901c57806f7e36736ed1616e6ab3eebcc99b78c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 21 May 2010 00:31:19 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104305 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateInstantiateDecl.cpp | 19 ++++++++++++++++++- .../instantiate-anonymous-union.cpp | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 592b474dfb..e8cbb66694 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -323,6 +323,13 @@ static bool InstantiateInitializer(Sema &S, Expr *Init, } 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()) + if (RecordTy->getDecl()->isAnonymousStructOrUnion()) + if (!VisitCXXRecordDecl(cast(RecordTy->getDecl()))) + return 0; + // Do substitution on the type of the declaration TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, @@ -490,6 +497,11 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { if (!Field->getDeclName()) { // Keep track of where this decl came from. SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D); + } + if (CXXRecordDecl *Parent= dyn_cast(Field->getDeclContext())) { + if (Parent->isAnonymousStructOrUnion() && + Parent->getLookupContext()->isFunctionOrMethod()) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Field); } Field->setImplicit(D->isImplicit()); @@ -913,7 +925,12 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { if (Decl::FriendObjectKind FOK = D->getFriendObjectKind()) 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); return Record; diff --git a/test/SemaTemplate/instantiate-anonymous-union.cpp b/test/SemaTemplate/instantiate-anonymous-union.cpp index 7c75885788..255454b2eb 100644 --- a/test/SemaTemplate/instantiate-anonymous-union.cpp +++ b/test/SemaTemplate/instantiate-anonymous-union.cpp @@ -29,3 +29,21 @@ template struct C { }; C c0(0); + +namespace PR7088 { + template + void f() { + union { + int a; + union { + float real; + T d; + }; + }; + + a = 17; + d = 3.14; + } + + template void f(); +} -- 2.50.1