[clang] ea0cd51 - [CodeGen][ObjC] Fix a memory leak that occurs when a non-trivial C

Akira Hatanaka via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 5 20:03:23 PST 2023


Author: Akira Hatanaka
Date: 2023-01-05T19:48:25-08:00
New Revision: ea0cd51a495829ea35b7b8304b16784946598d19

URL: https://github.com/llvm/llvm-project/commit/ea0cd51a495829ea35b7b8304b16784946598d19
DIFF: https://github.com/llvm/llvm-project/commit/ea0cd51a495829ea35b7b8304b16784946598d19.diff

LOG: [CodeGen][ObjC] Fix a memory leak that occurs when a non-trivial C
struct property is set using dot notation

Make sure the destructor is called if needed.

Differential Revision: https://reviews.llvm.org/D136639

Added: 
    

Modified: 
    clang/lib/CodeGen/CGExprAgg.cpp
    clang/test/CodeGenObjC/nontrivial-c-struct-property.m

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 5fdbc6a75201f..45b3edf70e2e3 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -201,7 +201,16 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
       return EmitFinalDestCopy(E->getType(), LV);
     }
 
-    CGF.EmitPseudoObjectRValue(E, EnsureSlot(E->getType()));
+    AggValueSlot Slot = EnsureSlot(E->getType());
+    bool NeedsDestruction =
+        !Slot.isExternallyDestructed() &&
+        E->getType().isDestructedType() == QualType::DK_nontrivial_c_struct;
+    if (NeedsDestruction)
+      Slot.setExternallyDestructed();
+    CGF.EmitPseudoObjectRValue(E, Slot);
+    if (NeedsDestruction)
+      CGF.pushDestroy(QualType::DK_nontrivial_c_struct, Slot.getAddress(),
+                      E->getType());
   }
 
   void VisitVAArgExpr(VAArgExpr *E);

diff  --git a/clang/test/CodeGenObjC/nontrivial-c-struct-property.m b/clang/test/CodeGenObjC/nontrivial-c-struct-property.m
index 9f907e20331a0..12c042feac98f 100644
--- a/clang/test/CodeGenObjC/nontrivial-c-struct-property.m
+++ b/clang/test/CodeGenObjC/nontrivial-c-struct-property.m
@@ -68,3 +68,39 @@ -(void)setP1:(S0)s0 {
 // CHECK: call void @objc_copyCppObjectAtomic({{.*}}, {{.*}}, ptr noundef @__move_assignment_8_8_s0)
 // CHECK-NOT: call
 // CHECK: ret void
+
+// CHECK: define void @test0(ptr noundef %[[C:.*]], ptr noundef %[[A:.*]])
+// CHECK: %[[C_ADDR:.*]] = alloca ptr, align 8
+// CHECK: %[[A_ADDR:.*]] = alloca ptr, align 8
+// CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_S0]], align 8
+// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_S0]], align 8
+// CHECK: store ptr null, ptr %[[C_ADDR]], align 8
+// CHECK: call void @llvm.objc.storeStrong(ptr %[[C_ADDR]], ptr %[[C]])
+// CHECK: store ptr %[[A]], ptr %[[A_ADDR]], align 8
+// CHECK: %[[V0:.*]] = load ptr, ptr %[[A_ADDR]], align 8
+// CHECK: call void @__copy_constructor_8_8_s0(ptr %[[AGG_TMP_ENSURED]], ptr %[[V0]])
+// CHECK: %[[V1:.*]] = load ptr, ptr %[[C_ADDR]], align 8
+// CHECK: call void @__copy_constructor_8_8_s0(ptr %[[AGG_TMP]], ptr %[[AGG_TMP_ENSURED]])
+// CHECK: %[[V2:.*]] = icmp eq ptr %[[V1]], null
+// CHECK: br i1 %[[V2]], label %[[MSGSEND_NULL:.*]], label %[[MSGSEND_CALL:.*]]
+
+// CHECK: [[MSGSEND_CALL]]:
+// CHECK: %[[V3:.*]] = load ptr, ptr @OBJC_SELECTOR_REFERENCES_, align 8
+// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_S0]], ptr %[[AGG_TMP]], i32 0, i32 0
+// CHECK: %[[V4:.*]] = load ptr, ptr %[[COERCE_DIVE]], align 8
+// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V4]] to i64
+// CHECK: call void @objc_msgSend(ptr noundef %[[V1]], ptr noundef %[[V3]], i64 %[[COERCE_VAL_PI]])
+// CHECK: br label %[[MSGSEND_CONT:.*]]
+
+// CHECK: [[MSGSEND_NULL]]:
+// CHECK: call void @__destructor_8_s0(ptr %[[AGG_TMP]])
+// CHECK: br label %[[MSGSEND_CONT]]
+
+// CHECK: [[MSGSEND_CONT]]:
+// CHECK: call void @__destructor_8_s0(ptr %[[AGG_TMP_ENSURED]]
+// CHECK: call void @llvm.objc.storeStrong(ptr %[[C_ADDR]], ptr null)
+// CHECK: ret void
+
+void test0(C *c, S0 *a) {
+  c.atomic0 = *a;
+}


        


More information about the cfe-commits mailing list