forked from OSchip/llvm-project
[CodeGen] Fix a crash that occurs when a non-trivial C struct with a
volatile array field is copied. The crash occurs because method 'visitArray' passes a null FieldDecl to method 'visit' and some of the methods called downstream expect a non-null FieldDecl to be passed. rdar://problem/33599681 llvm-svn: 330151
This commit is contained in:
parent
92ad94e7cd
commit
1c3bd2ff0c
|
@ -21,10 +21,11 @@ using namespace clang;
|
|||
using namespace CodeGen;
|
||||
|
||||
// Return the size of a field in number of bits.
|
||||
static uint64_t getFieldSize(const FieldDecl *FD, ASTContext &Ctx) {
|
||||
if (FD->isBitField())
|
||||
static uint64_t getFieldSize(const FieldDecl *FD, QualType FT,
|
||||
ASTContext &Ctx) {
|
||||
if (FD && FD->isBitField())
|
||||
return FD->getBitWidthValue(Ctx);
|
||||
return Ctx.getTypeSize(FD->getType());
|
||||
return Ctx.getTypeSize(FT);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -187,7 +188,7 @@ struct CopyStructVisitor : StructVisitor<Derived>,
|
|||
Ts... Args) {
|
||||
assert(!FT.isVolatileQualified() && "volatile field not expected");
|
||||
ASTContext &Ctx = asDerived().getContext();
|
||||
uint64_t FieldSize = getFieldSize(FD, Ctx);
|
||||
uint64_t FieldSize = getFieldSize(FD, FT, Ctx);
|
||||
|
||||
// Ignore zero-sized fields.
|
||||
if (FieldSize == 0)
|
||||
|
@ -336,7 +337,7 @@ struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
|
|||
uint64_t OffsetInBits =
|
||||
this->Ctx.toBits(CurStackOffset) + this->getFieldOffsetInBits(FD);
|
||||
this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" +
|
||||
llvm::to_string(getFieldSize(FD, this->Ctx)));
|
||||
llvm::to_string(getFieldSize(FD, FT, this->Ctx)));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -595,16 +596,25 @@ struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
|
|||
template <class... Ts>
|
||||
void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset,
|
||||
std::array<Address, 2> Addrs) {
|
||||
QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
|
||||
llvm::PointerType *PtrTy = this->CGF->ConvertType(RT)->getPointerTo();
|
||||
Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
|
||||
LValue DstBase = this->CGF->MakeAddrLValue(
|
||||
this->CGF->Builder.CreateBitCast(DstAddr, PtrTy), FT);
|
||||
LValue DstLV = this->CGF->EmitLValueForField(DstBase, FD);
|
||||
Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
|
||||
LValue SrcBase = this->CGF->MakeAddrLValue(
|
||||
this->CGF->Builder.CreateBitCast(SrcAddr, PtrTy), FT);
|
||||
LValue SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
|
||||
LValue DstLV, SrcLV;
|
||||
if (FD) {
|
||||
QualType RT = QualType(FD->getParent()->getTypeForDecl(), 0);
|
||||
llvm::PointerType *PtrTy = this->CGF->ConvertType(RT)->getPointerTo();
|
||||
Address DstAddr = this->getAddrWithOffset(Addrs[DstIdx], Offset);
|
||||
LValue DstBase = this->CGF->MakeAddrLValue(
|
||||
this->CGF->Builder.CreateBitCast(DstAddr, PtrTy), FT);
|
||||
DstLV = this->CGF->EmitLValueForField(DstBase, FD);
|
||||
Address SrcAddr = this->getAddrWithOffset(Addrs[SrcIdx], Offset);
|
||||
LValue SrcBase = this->CGF->MakeAddrLValue(
|
||||
this->CGF->Builder.CreateBitCast(SrcAddr, PtrTy), FT);
|
||||
SrcLV = this->CGF->EmitLValueForField(SrcBase, FD);
|
||||
} else {
|
||||
llvm::PointerType *Ty = this->CGF->ConvertType(FT)->getPointerTo();
|
||||
Address DstAddr = this->CGF->Builder.CreateBitCast(Addrs[DstIdx], Ty);
|
||||
Address SrcAddr = this->CGF->Builder.CreateBitCast(Addrs[SrcIdx], Ty);
|
||||
DstLV = this->CGF->MakeAddrLValue(DstAddr, FT);
|
||||
SrcLV = this->CGF->MakeAddrLValue(SrcAddr, FT);
|
||||
}
|
||||
RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
|
||||
this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
|
||||
}
|
||||
|
|
|
@ -70,6 +70,11 @@ typedef struct {
|
|||
volatile char i6;
|
||||
} Bitfield1;
|
||||
|
||||
typedef struct {
|
||||
id x;
|
||||
volatile int a[16];
|
||||
} VolatileArray ;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USESTRUCT
|
||||
|
@ -540,4 +545,17 @@ void test_strong_in_union() {
|
|||
U t;
|
||||
}
|
||||
|
||||
// CHECK: define void @test_copy_constructor_VolatileArray(
|
||||
// CHECK: call void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE(
|
||||
|
||||
// CHECK: define linkonce_odr hidden void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE(
|
||||
// CHECK: %[[V12:.*]] = bitcast i8** %{{.*}} to i32*
|
||||
// CHECK: %[[V13:.*]] = bitcast i8** %{{.*}} to i32*
|
||||
// CHECK: %[[V14:.*]] = load volatile i32, i32* %[[V13]], align 4
|
||||
// CHECK: store volatile i32 %[[V14]], i32* %[[V12]], align 4
|
||||
|
||||
void test_copy_constructor_VolatileArray(VolatileArray *a) {
|
||||
VolatileArray t = *a;
|
||||
}
|
||||
|
||||
#endif /* USESTRUCT */
|
||||
|
|
Loading…
Reference in New Issue