[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