[clang] 71e1a56 - [CodeGen] Emit destructor calls to destruct non-trivial C struct
via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 23 14:46:45 PDT 2020
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 */
More information about the cfe-commits
mailing list