forked from OSchip/llvm-project
ir-gen support for anonymous union data member
copying in copy constructors and used in default constructor's initializer list. llvm-svn: 78700
This commit is contained in:
parent
d362857f4c
commit
b2197042b8
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue