[clang] [Clang][CodeGen] Fix clang codegen eh cleanup (PR #226743)

via cfe-commits cfe-commits at lists.llvm.org
Sun Sep 27 18:06:53 PDT 2026


https://github.com/rdong8 updated https://github.com/llvm/llvm-project/pull/226743

>From 87850e035d00eb000086cab024d15a50ffb55044 Mon Sep 17 00:00:00 2001
From: Richard Dong <66289396+rdong8 at users.noreply.github.com>
Date: Mon, 28 Sep 2026 00:24:40 +0000
Subject: [PATCH 1/2] [Clang][CodeGen][test] Add test for compound literals
 with destructors under -fexceptions

Add tests in strong-in-c-struct.m compiling with -fexceptions -fobjc-exceptions to verify that exception handling cleanups (invokes and landing pads with destructor calls) are emitted for lifetime-extended compound literals with destructors.
---
 clang/test/CodeGenObjC/strong-in-c-struct.m | 35 +++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/clang/test/CodeGenObjC/strong-in-c-struct.m b/clang/test/CodeGenObjC/strong-in-c-struct.m
index 8b2a161fd9cbb..efe1ac334cb42 100644
--- a/clang/test/CodeGenObjC/strong-in-c-struct.m
+++ b/clang/test/CodeGenObjC/strong-in-c-struct.m
@@ -2,6 +2,8 @@
 
 // RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks  -fobjc-runtime=ios-11.0 -emit-pch -o %t %s
 // RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks  -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks  -fobjc-runtime=ios-11.0 -fexceptions -fobjc-exceptions -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s --check-prefix=CHECK-EH
+
 
 #ifndef HEADER
 #define HEADER
@@ -678,6 +680,14 @@ void test_copy_constructor_VolatileArray(VolatileArray *a) {
 
 // CHECK: call void @__destructor_8_s8(ptr %[[_COMPOUNDLITERAL]])
 
+// CHECK-EH: define{{.*}} void @test_compound_literal0(
+// CHECK-EH: invoke void @func(
+// CHECK-EH: to label %{{.*}} unwind label %[[LPAD:.*]]
+// CHECK-EH: [[LPAD]]:
+// CHECK-EH: landingpad
+// CHECK-EH: call void @__destructor_8_s8(
+// CHECK-EH: call void @__destructor_8_s8(
+
 void test_compound_literal0(int c) {
   StrongSmall *p = c ? &(StrongSmall){ 1, 0 } : &(StrongSmall){ 2, 0 };
   func(0);
@@ -736,11 +746,36 @@ void test_compound_literal1(int c) {
 
 // CHECK: call void @__destructor_8_s8(ptr %[[_COMPOUNDLITERAL]])
 
+// CHECK-EH: define{{.*}} void @test_compound_literal2(
+// CHECK-EH: invoke void @func(
+// CHECK-EH: to label %{{.*}} unwind label %[[LPAD:.*]]
+// CHECK-EH: [[LPAD]]:
+// CHECK-EH: landingpad
+// CHECK-EH: call void @__destructor_8_s8(
+// CHECK-EH: call void @__destructor_8_s8(
+
 void test_compound_literal2(int c, StrongSmall *p) {
   *p = c ? (StrongSmall){ 1, 0 } : (StrongSmall){ 2, 0 };
   func(0);
 }
 
+// CHECK: define{{.*}} void @test_compound_literal3(
+// CHECK: call void @func(
+// CHECK: call void @__destructor_8_s8(
+
+// CHECK-EH: define{{.*}} void @test_compound_literal3(
+// CHECK-EH: invoke void @func(
+// CHECK-EH: to label %{{.*}} unwind label %[[LPAD:.*]]
+// CHECK-EH: [[LPAD]]:
+// CHECK-EH: landingpad
+// CHECK-EH: call void @__destructor_8_s8(
+
+void test_compound_literal3(int c) {
+  StrongSmall *p = c ? (StrongSmall[]){ {1, 0}, {2, 0} } : 0;
+  func(0);
+}
+
+
 // CHECK: define{{.*}} void @test_member_access(
 // CHECK: %[[TMP:.*]] = alloca %[[STRUCT_STRONGSMALL]],
 // CHECK: call void @__destructor_8_s8(ptr %[[TMP]])

>From a6d8e7944e1adc6d7a4bcd25795f66ec9c168340 Mon Sep 17 00:00:00 2001
From: Richard Dong <66289396+rdong8 at users.noreply.github.com>
Date: Sat, 26 Sep 2026 20:53:54 +0000
Subject: [PATCH 2/2] [Clang][CodeGen] Fix type mismatch in
 pushLifetimeExtendedDestroy for compound literals (NFC)

In EmitCompoundLiteralLValue and VisitCompoundLiteralExpr, the code passed
`DtorKind & EHCleanup` for the `useEHCleanupForArray` argument of
pushLifetimeExtendedDestroy. DtorKind is of type QualType::DestructionKind
(an enum) while EHCleanup is an enumerator of CleanupKind (0x1). Bitwise AND
between them was a type mismatch that inadvertently tested whether the
DestructionKind enum value was odd.

Use needsEHCleanup(DtorKind) (or CGF.needsEHCleanup(DtorKind)) instead, matching
the convention used elsewhere in CodeGen.

This is NFC because:
1. For non-array compound literals, useEHCleanupForArray is unused (only the
   first argument, cleanupKind, determines whether the compound literal itself
   receives an EH cleanup, and that already used getCleanupKind(DtorKind)).
2. For array compound literals, useEHCleanupForArray only pushes a partial
   cleanup during element destruction if an individual element destructor can
   throw. The types where the check changed (DK_objc_strong_lifetime and
   DK_nontrivial_c_struct) have non-throwing destructors, so no exception
   edges are emitted and the partial cleanup is never triggered.
---
 clang/lib/CodeGen/CGExpr.cpp    | 2 +-
 clang/lib/CodeGen/CGExprAgg.cpp | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 4a481c01f6a68..a555e8e851819 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -6175,7 +6175,7 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
     if (QualType::DestructionKind DtorKind = E->getType().isDestructedType())
       pushLifetimeExtendedDestroy(getCleanupKind(DtorKind), DeclPtr,
                                   E->getType(), getDestroyer(DtorKind),
-                                  DtorKind & EHCleanup);
+                                  needsEHCleanup(DtorKind));
 
   return Result;
 }
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index ff0ed1473d7df..f393e75ead1d6 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -794,7 +794,7 @@ void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
     if (QualType::DestructionKind DtorKind = E->getType().isDestructedType())
       CGF.pushLifetimeExtendedDestroy(
           CGF.getCleanupKind(DtorKind), Slot.getAddress(), E->getType(),
-          CGF.getDestroyer(DtorKind), DtorKind & EHCleanup);
+          CGF.getDestroyer(DtorKind), CGF.needsEHCleanup(DtorKind));
 }
 
 /// Attempt to look through various unimportant expressions to find a



More information about the cfe-commits mailing list