Author: Akira Hatanaka Date: 2020-10-23T14:46:17-07:00 New Revision: 71e1a56de153536b9ff655fe740ccbf3f6b1faf0
URL: https://github.com/llvm/llvm-project/commit/71e1a56de153536b9ff655fe740ccbf3f6b1faf0 DIFF: https://github.com/llvm/llvm-project/commit/71e1a56de153536b9ff655fe740ccbf3f6b1faf0.diff LOG: [CodeGen] Emit destructor calls to destruct non-trivial C struct temporaries created by conditional and assignment operators rdar://problem/64989559 Differential Revision: https://reviews.llvm.org/D83448 Added: Modified: clang/lib/CodeGen/CGExprAgg.cpp clang/test/CodeGenObjC/strong-in-c-struct.m Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 9106b90525db..60ea1b2af037 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -1216,6 +1216,11 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { // Copy into the destination if the assignment isn't ignored. EmitFinalDestCopy(E->getType(), LHS); + + if (!Dest.isIgnored() && !Dest.isExternallyDestructed() && + E->getType().isDestructedType() == QualType::DK_nontrivial_c_struct) + CGF.pushDestroy(QualType::DK_nontrivial_c_struct, Dest.getAddress(), + E->getType()); } void AggExprEmitter:: @@ -1233,6 +1238,11 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { // Save whether the destination's lifetime is externally managed. bool isExternallyDestructed = Dest.isExternallyDestructed(); + bool destructNonTrivialCStruct = + !isExternallyDestructed && + E->getType().isDestructedType() == QualType::DK_nontrivial_c_struct; + isExternallyDestructed |= destructNonTrivialCStruct; + Dest.setExternallyDestructed(isExternallyDestructed); eval.begin(CGF); CGF.EmitBlock(LHSBlock); @@ -1254,6 +1264,10 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { Visit(E->getFalseExpr()); eval.end(CGF); + if (destructNonTrivialCStruct) + CGF.pushDestroy(QualType::DK_nontrivial_c_struct, Dest.getAddress(), + E->getType()); + CGF.EmitBlock(ContBlock); } diff --git a/clang/test/CodeGenObjC/strong-in-c-struct.m b/clang/test/CodeGenObjC/strong-in-c-struct.m index f0227119279f..4e098c352ab5 100644 --- a/clang/test/CodeGenObjC/strong-in-c-struct.m +++ b/clang/test/CodeGenObjC/strong-in-c-struct.m @@ -95,12 +95,13 @@ + (StrongSmall)getStrongSmallClass; @end id g0; +StrongSmall g1, g2; +// CHECK: %[[STRUCT_STRONGSMALL:.*]] = type { i32, i8* } // CHECK: %[[STRUCT_STRONGOUTER:.*]] = type { %[[STRUCT_STRONG:.*]], i8*, double } // CHECK: %[[STRUCT_STRONG]] = type { %[[STRUCT_TRIVIAL:.*]], i8* } // CHECK: %[[STRUCT_TRIVIAL]] = type { [4 x i32] } // CHECK: %[[STRUCT_BLOCK_BYREF_T:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_T]]*, i32, i32, i8*, i8*, i8*, %[[STRUCT_STRONGOUTER]] } -// CHECK: %[[STRUCT_STRONGSMALL:.*]] = type { i32, i8* } // CHECK: %[[STRUCT_STRONGBLOCK:.*]] = type { void ()* } // CHECK: %[[STRUCT_BITFIELD1:.*]] = type { i8, i8, i8*, i32, i8*, [3 x i32], i8*, double, i8, i8 } @@ -900,4 +901,47 @@ void test_zero_bitfield() { a = b; } +// CHECK-LABEL: define i8* @test_conditional0( +// CHECK: %[[TMP:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 + +// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TMP]] to i8** +// CHECK: call void @__copy_constructor_8_8_t0w4_s8(i8** %[[V1]], i8** bitcast (%[[STRUCT_STRONGSMALL]]* @g2 to i8**)) + +// CHECK: %[[V2:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TMP]] to i8** +// CHECK: call void @__copy_constructor_8_8_t0w4_s8(i8** %[[V2]], i8** bitcast (%[[STRUCT_STRONGSMALL]]* @g1 to i8**)) + +// CHECK: %[[V5:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TMP]] to i8** +// CHECK: call void @__destructor_8_s8(i8** %[[V5]]) +// CHECK: @llvm.objc.autoreleaseReturnValue + +id test_conditional0(int c) { + return (c ? g2 : g1).f1; +} + +// CHECK-LABEL: define i8* @test_conditional1( +// CHECK-NOT: call void @__destructor + +id test_conditional1(int c) { + calleeStrongSmall(c ? g2 : g1); +} + +// CHECK-LABEL: define i8* @test_assignment0( +// CHECK: %[[TMP:.*]] = alloca %[[STRUCT_STRONGSMALL]], align 8 +// CHECK: call void @__copy_assignment_8_8_t0w4_s8(i8** bitcast (%[[STRUCT_STRONGSMALL]]* @g2 to i8**), i8** bitcast (%[[STRUCT_STRONGSMALL]]* @g1 to i8**)) +// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TMP]] to i8** +// CHECK: call void @__copy_constructor_8_8_t0w4_s8(i8** %[[V0]], i8** bitcast (%[[STRUCT_STRONGSMALL]]* @g2 to i8**)) +// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_STRONGSMALL]]* %[[TMP]] to i8** +// CHECK: call void @__destructor_8_s8(i8** %[[V3]]) + +id test_assignment0(void) { + return (g2 = g1).f1; +} + +// CHECK-LABEL: define i8* @test_assignment1( +// CHECK-NOT: call void @__destructor + +id test_assignment1(void) { + calleeStrongSmall(g2 = g1); +} + #endif /* USESTRUCT */ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits