зеркало из https://github.com/microsoft/clang.git
When emitting an lvalue for an anonymous struct or union member during
class initialization, drill down through an arbitrary number of anonymous records. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104310 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
bc365c5360
Коммит
a9976d3b19
|
@ -446,13 +446,15 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
|
|||
QualType FieldType = CGF.getContext().getCanonicalType(Field->getType());
|
||||
|
||||
llvm::Value *ThisPtr = CGF.LoadCXXThis();
|
||||
LValue LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0);
|
||||
LValue LHS;
|
||||
|
||||
// If we are initializing an anonymous union field, drill down to the field.
|
||||
if (MemberInit->getAnonUnionMember()) {
|
||||
Field = MemberInit->getAnonUnionMember();
|
||||
LHS = CGF.EmitLValueForField(LHS.getAddress(), Field, 0);
|
||||
LHS = CGF.EmitLValueForAnonRecordField(ThisPtr, Field, 0);
|
||||
FieldType = Field->getType();
|
||||
} else {
|
||||
LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0);
|
||||
}
|
||||
|
||||
// FIXME: If there's no initializer and the CXXBaseOrMemberInitializer
|
||||
|
|
|
@ -1611,6 +1611,35 @@ LValue CodeGenFunction::EmitLValueForBitfield(llvm::Value* BaseValue,
|
|||
Field->getType().getCVRQualifiers()|CVRQualifiers);
|
||||
}
|
||||
|
||||
/// EmitLValueForAnonRecordField - Given that the field is a member of
|
||||
/// an anonymous struct or union buried inside a record, and given
|
||||
/// that the base value is a pointer to the enclosing record, derive
|
||||
/// an lvalue for the ultimate field.
|
||||
LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
|
||||
const FieldDecl *Field,
|
||||
unsigned CVRQualifiers) {
|
||||
llvm::SmallVector<const FieldDecl *, 8> Path;
|
||||
Path.push_back(Field);
|
||||
|
||||
while (Field->getParent()->isAnonymousStructOrUnion()) {
|
||||
const ValueDecl *VD = Field->getParent()->getAnonymousStructOrUnionObject();
|
||||
if (!isa<FieldDecl>(VD)) break;
|
||||
Field = cast<FieldDecl>(VD);
|
||||
Path.push_back(Field);
|
||||
}
|
||||
|
||||
llvm::SmallVectorImpl<const FieldDecl*>::reverse_iterator
|
||||
I = Path.rbegin(), E = Path.rend();
|
||||
while (true) {
|
||||
LValue LV = EmitLValueForField(BaseValue, *I, CVRQualifiers);
|
||||
if (++I == E) return LV;
|
||||
|
||||
assert(LV.isSimple());
|
||||
BaseValue = LV.getAddress();
|
||||
CVRQualifiers |= LV.getVRQualifiers();
|
||||
}
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitLValueForField(llvm::Value* BaseValue,
|
||||
const FieldDecl* Field,
|
||||
unsigned CVRQualifiers) {
|
||||
|
|
|
@ -1052,6 +1052,9 @@ public:
|
|||
|
||||
llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,
|
||||
const ObjCIvarDecl *Ivar);
|
||||
LValue EmitLValueForAnonRecordField(llvm::Value* Base,
|
||||
const FieldDecl* Field,
|
||||
unsigned CVRQualifiers);
|
||||
LValue EmitLValueForField(llvm::Value* Base, const FieldDecl* Field,
|
||||
unsigned CVRQualifiers);
|
||||
|
||||
|
|
|
@ -52,3 +52,29 @@ namespace test2 {
|
|||
// CHECK: store i32 10
|
||||
// CHECK: }
|
||||
}
|
||||
|
||||
namespace test3 {
|
||||
struct A {
|
||||
union {
|
||||
mutable char fibers[100];
|
||||
struct {
|
||||
void (*callback)(void*);
|
||||
void *callback_value;
|
||||
};
|
||||
};
|
||||
|
||||
A();
|
||||
};
|
||||
|
||||
A::A() : callback(0), callback_value(0) {}
|
||||
// CHECK: define void @ZN5test31AC2Ev(
|
||||
// CHECK: [[THIS:%.*]] = load
|
||||
// CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
|
||||
// CHECK-NEXT: [[STRUCT:%.*]] = getelementptr inbounds {{.*}} [[UNION]], i32 0, i32 0
|
||||
// CHECK-NEXT: [[CALLBACK:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0
|
||||
// CHECK-NEXT: store void (i8*)* null, void (i8*)** [[CALLBACK]]
|
||||
// CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0
|
||||
// CHECK-NEXT: [[STRUCT:%.*]] = getelementptr inbounds {{.*}} [[UNION]], i32 0, i32 0
|
||||
// CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0
|
||||
// CHECK-NEXT: store i8* null, void i8** [[CVALUE]]
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче