https://github.com/yuxuanchen1997 updated 
https://github.com/llvm/llvm-project/pull/196597

>From 190653df6b4480e824a079a27089ed847fcb7fdd Mon Sep 17 00:00:00 2001
From: Yuxuan Chen <[email protected]>
Date: Thu, 7 May 2026 20:24:49 -0700
Subject: [PATCH] [Clang] Rebind the closure temporary when rebuilding default
 member initializers

Fixes https://github.com/llvm/llvm-project/issues/196469

Since the CWG1815 implementation, `InitListChecker` rebuilds a default
member initializer at its point of use in aggregate initialization. The
rebuild uses the `EnsureImmediateInvocationInDefaultArgs` tree
transform, where `TransformCXXBindTemporaryExpr` strips
`CXXBindTemporaryExpr` nodes, relying on the subexpression's rebuild to
re-create the temporary binding: every `Rebuild*` path funnels through
`Sema::MaybeBindToTemporary`, which also re-registers the cleanup in
the current evaluation context.

However, the transform overrides `TransformLambdaExpr` to return the
closure unchanged (the body is not a subexpression), skipping the
`MaybeBindToTemporary` call that `BuildLambdaExpr` ends with. The
rebuilt initializer then lacks both the `CXXBindTemporaryExpr` around
the closure and the `ExprWithCleanups` marker, so CodeGen never emits
the closure's destructor and init-captured members leak.

Restore the side effect in the override: re-bind the closure to a
temporary, exactly as building the lambda would have. This is a no-op
for trivially destructible closures.

Co-Authored-By: Claude Fable 5 <[email protected]>
---
 clang/lib/Sema/SemaExpr.cpp                   | 12 ++++++++--
 ...469-default-member-init-lambda-cleanup.cpp | 24 +++++++++++++++++++
 2 files changed, 34 insertions(+), 2 deletions(-)
 create mode 100644 
clang/test/CodeGenCXX/gh196469-default-member-init-lambda-cleanup.cpp

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 9fd8c6a0a5451..cf1ef0a81185f 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5710,9 +5710,17 @@ struct EnsureImmediateInvocationInDefaultArgs
 
   // Lambda can only have immediate invocations in the default
   // args of their parameters, which is transformed upon calling the closure.
-  // The body is not a subexpression, so we have nothing to do.
+  // The body is not a subexpression, so we do not transform the lambda
+  // itself. However, the closure object is returned without rebuilding it,
+  // so we must redo the effects building a lambda has on the enclosing
+  // context: any CXXBindTemporaryExpr around it has been dropped by
+  // TransformCXXBindTemporaryExpr, and the enclosing context must be
+  // marked as requiring cleanups for the closure's destructor to be run
+  // at the end of the full-expression.
   // FIXME: Immediate calls in capture initializers should be transformed.
-  ExprResult TransformLambdaExpr(LambdaExpr *E) { return E; }
+  ExprResult TransformLambdaExpr(LambdaExpr *E) {
+    return SemaRef.MaybeBindToTemporary(E);
+  }
   ExprResult TransformBlockExpr(BlockExpr *E) { return E; }
 
   // Make sure we don't rebuild the this pointer as it would
diff --git 
a/clang/test/CodeGenCXX/gh196469-default-member-init-lambda-cleanup.cpp 
b/clang/test/CodeGenCXX/gh196469-default-member-init-lambda-cleanup.cpp
new file mode 100644
index 0000000000000..71857dc449416
--- /dev/null
+++ b/clang/test/CodeGenCXX/gh196469-default-member-init-lambda-cleanup.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm -o - 
%s | FileCheck %s
+
+struct Noisy {
+  Noisy();
+  ~Noisy();
+};
+
+struct Function {
+  template <typename F> Function(F) {}
+};
+
+struct Options {
+  Function function{[noisy = Noisy{}] {}};
+};
+
+Options kOptions{};
+
+// CHECK-LABEL: define internal void @__cxx_global_var_init
+// CHECK: call void @_ZN5NoisyC1Ev
+// CHECK: call void @_ZN8FunctionC1IN7Options8functionMUlvE_EEET_
+// CHECK: call void @_ZN7Options8functionMUlvE_D1Ev
+
+// CHECK-LABEL: define {{.*}} @_ZN7Options8functionMUlvE_D2Ev
+// CHECK: call void @_ZN5NoisyD1Ev

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to