From: Akira Hatanaka Date: Mon, 16 Apr 2018 19:38:00 +0000 (+0000) Subject: [CodeGen] Fix a crash that occurs when a non-trivial C struct with a X-Git-Tag: llvmorg-7.0.0-rc1~8088 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1c3bd2ff0c71590ad02c68bf0d4bbd3bbc27837e;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/clang/lib/CodeGen/CGNonTrivialStruct.cpp b/clang/lib/CodeGen/CGNonTrivialStruct.cpp index 731938a..4f17084 100644 --- a/clang/lib/CodeGen/CGNonTrivialStruct.cpp +++ b/clang/lib/CodeGen/CGNonTrivialStruct.cpp @@ -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, 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, 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, template void visitVolatileTrivial(QualType FT, const FieldDecl *FD, CharUnits Offset, std::array 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); } diff --git a/clang/test/CodeGenObjC/strong-in-c-struct.m b/clang/test/CodeGenObjC/strong-in-c-struct.m index 6310943..393a328 100644 --- a/clang/test/CodeGenObjC/strong-in-c-struct.m +++ b/clang/test/CodeGenObjC/strong-in-c-struct.m @@ -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 */