diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-08-11 18:49:54 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-08-11 18:49:54 +0000 |
commit | e64941280877d065a27e8cefd2a9038256d0e3ac (patch) | |
tree | eb1f5ece8bd53df7f0ac1d689f4e7a21debd6c59 | |
parent | b2fedb46056accb808d42c1754031b9bfa6aa69b (diff) |
ir-gen support for anonymous union data member
copying in copy constructors and used in
default constructor's initializer list.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78700 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/DeclCXX.h | 36 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 19 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 10 | ||||
-rw-r--r-- | test/CodeGenCXX/copy-constructor-synthesis.cpp | 16 |
6 files changed, 74 insertions, 18 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 00e583fa6e..4ca9a8222e 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -779,9 +779,28 @@ class CXXBaseOrMemberInitializer { Stmt **Args; unsigned NumArgs; - /// CtorToCall - For a base or member needing a constructor for their - /// initialization, this is the constructor to call. - CXXConstructorDecl *CtorToCall; + union { + /// CtorToCall - For a base or member needing a constructor for their + /// initialization, this is the constructor to call. + CXXConstructorDecl *CtorToCall; + + /// AnonUnionMember - When 'BaseOrMember' is class's anonymous union + /// data member, this field holds the FieldDecl for the member of the + /// anonymous union being initialized. + /// @code + /// struct X { + /// X() : au_i1(123) {} + /// union { + /// int au_i1; + /// float au_f1; + /// }; + /// }; + /// @endcode + /// In above example, BaseOrMember holds the field decl. for anonymous union + /// and AnonUnionMember holds field decl for au_i1. + /// + FieldDecl *AnonUnionMember; + }; /// IdLoc - Location of the id in ctor-initializer list. SourceLocation IdLoc; @@ -854,6 +873,17 @@ public: return 0; } + void setMember(FieldDecl * anonUnionField) { + BaseOrMember = reinterpret_cast<uintptr_t>(anonUnionField); + } + + FieldDecl *getAnonUnionMember() const { + return AnonUnionMember; + } + void setAnonUnionMember(FieldDecl *anonMember) { + AnonUnionMember = anonMember; + } + const CXXConstructorDecl *getConstructor() const { return CtorToCall; } SourceLocation getSourceLocation() const { return IdLoc; } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index f85091e4f5..87a557d4df 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -643,6 +643,11 @@ CXXConstructorDecl::setBaseOrMemberInitializers( for(RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), EA = FieldClassDecl->field_end(); FA != EA; FA++) { if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*FA)) { + // 'Member' is the anonymous union field and 'AnonUnionMember' is + // set to the anonymous union data member used in the initializer + // list. + Value->setMember(*Field); + Value->setAnonUnionMember(*FA); AllToInit.push_back(Value); break; } diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index aff85fa5d4..e9ebf230d6 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -874,8 +874,7 @@ void CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *CD, // FIXME. How about copying arrays! assert(!getContext().getAsArrayType(FieldType) && "FIXME. Copying arrays NYI"); - assert(!Field->isAnonymousStructOrUnion() && - "FIXME. anonymous data member NYI in copy constructor synthesis"); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(FieldClassType->getDecl()); @@ -924,23 +923,25 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) { QualType FieldType = getContext().getCanonicalType((Field)->getType()); assert(!getContext().getAsArrayType(FieldType) && "FIXME. Field arrays initialization unsupported"); - DeclContext *Ctx = Field->getDeclContext(); - RecordDecl *Record = cast<RecordDecl>(Ctx); - assert(!Record->isAnonymousStructOrUnion() && - "FIXME. anonymous union initializer NYI in default constructor"); - (void)Record; LoadOfThis = LoadCXXThis(); LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); if (FieldType->getAs<RecordType>()) { - + if (!Field->isAnonymousStructOrUnion()) { assert(Member->getConstructor() && "EmitCtorPrologue - no constructor to initialize member"); EmitCXXConstructorCall(Member->getConstructor(), Ctor_Complete, LHS.getAddress(), Member->const_arg_begin(), Member->const_arg_end()); - continue; + continue; + } + else { + // Initializing an anonymous union data member. + FieldDecl *anonMember = Member->getAnonUnionMember(); + LHS = EmitLValueForField(LHS.getAddress(), anonMember, false, 0); + FieldType = anonMember->getType(); + } } assert(Member->getNumArgs() == 1 && "Initializer count must be 1 only"); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 59f44de26a..a642de9a46 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -699,14 +699,14 @@ void CodeGenModule::DeferredCopyConstructorToEmit(GlobalDecl CopyCtorDecl) { for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), FieldEnd = ClassDecl->field_end(); Field != FieldEnd; ++Field) { - assert(!(*Field)->isAnonymousStructOrUnion() && - "FIXME. Anonymous union NYI - DeferredCopyConstructorToEmit"); QualType FieldType = Context.getCanonicalType((*Field)->getType()); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + if ((*Field)->isAnonymousStructOrUnion()) + continue; CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(FieldClassType->getDecl()); + = cast<CXXRecordDecl>(FieldClassType->getDecl()); if (CXXConstructorDecl *FieldCopyCtor = FieldClassDecl->getCopyConstructor(Context, 0)) GetAddrOfCXXConstructor(FieldCopyCtor, Ctor_Complete); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index a0bcfb2b78..a4005bae34 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -880,10 +880,16 @@ static void *GetKeyForTopLevelField(FieldDecl *Field) { return static_cast<void *>(Field); } -static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member) { +static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member, + bool MemberMaybeAnon=false) { // For fields injected into the class via declaration of an anonymous union, // use its anonymous union class declaration as the unique key. if (FieldDecl *Field = Member->getMember()) { + // After BuildBaseOrMemberInitializers call, Field is the anonymous union + // data member of the class. Data member used in the initializer list is + // in AnonUnionMember field. + if (MemberMaybeAnon && Field->isAnonymousStructOrUnion()) + Field = Member->getAnonUnionMember(); if (Field->getDeclContext()->isRecord()) { RecordDecl *RD = cast<RecordDecl>(Field->getDeclContext()); if (RD->isAnonymousStructOrUnion()) @@ -973,7 +979,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, for (unsigned i = 0; i < NumMemInits; i++) { CXXBaseOrMemberInitializer *Member = static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]); - void *MemberInCtorList = GetKeyForMember(Member); + void *MemberInCtorList = GetKeyForMember(Member, true); for (; curIndex < Last; curIndex++) if (MemberInCtorList == AllBaseOrMembers[curIndex]) diff --git a/test/CodeGenCXX/copy-constructor-synthesis.cpp b/test/CodeGenCXX/copy-constructor-synthesis.cpp index 851a4ea60a..121fd41b5c 100644 --- a/test/CodeGenCXX/copy-constructor-synthesis.cpp +++ b/test/CodeGenCXX/copy-constructor-synthesis.cpp @@ -26,12 +26,15 @@ struct P { struct X : M, N, P { // ... - X() : f1(1.0), d1(2.0), i1(3), name("HELLO"), bf1(0xff), bf2(0xabcd) {} + X() : f1(1.0), d1(2.0), i1(3), name("HELLO"), bf1(0xff), bf2(0xabcd), + au_i1(1234), au1_4("MASKED") {} P p0; void pr() { printf("iM = %d iN = %d, m1.iM = %d\n", iM, iN, m1.iM); printf("im = %d p0.iP = %d, p1.iP = %d\n", iP, p0.iP, p1.iP); printf("f1 = %f d1 = %f i1 = %d name(%s) \n", f1, d1, i1, name); printf("bf1 = %x bf2 = %x\n", bf1, bf2); + printf("au_i2 = %d\n", au_i2); + printf("au1_1 = %s\n", au1_1); } M m1; P p1; @@ -41,6 +44,17 @@ struct X : M, N, P { // ... const char *name; unsigned bf1 : 8; unsigned bf2 : 16; + + union { + int au_i1; + int au_i2; + }; + union { + const char * au1_1; + float au1_2; + int au1_3; + const char * au1_4; + }; }; int main() |