On 3/6/25 2:06 PM, Simon Martin wrote:
Hi Jason,

On Wed Mar 5, 2025 at 9:40 PM CET, Jason Merrill wrote:
On 3/5/25 10:39 AM, Simon Martin wrote:
Hi Jason,

On Wed Mar 5, 2025 at 12:03 AM CET, Jason Merrill wrote:
On 2/18/25 5:12 AM, Simon Martin wrote:
We've been rejecting this valid code since r8-4571:

=== cut here ===
void foo (float);
int main () {
     constexpr float x = 0;
     (void) [&] () {
       foo (x);
       (void) [] () {
         foo (x);
       };
     };
}
=== cut here ===

The problem is that when processing X in the inner lambda,
process_outer_var_ref errors out even though it does find the capture

from the enclosing lambda.

This patch changes process_outer_var_ref to accept and return the outer
proxy if it finds any.

Successfully tested on x86_64-pc-linux-gnu.

        PR c++/110584

gcc/cp/ChangeLog:

        * semantics.cc (process_outer_var_ref): Use capture from
        enclosing lambda, if any.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp0x/lambda/lambda-nested10.C: New test.

---
    gcc/cp/semantics.cc                           |  4 ++
    .../g++.dg/cpp0x/lambda/lambda-nested10.C     | 46 +++++++++++++++++++
    2 files changed, 50 insertions(+)
    create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested10.C

diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 7c7d3e3c432..7bbc82f7dc1 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4598,6 +4598,10 @@ process_outer_var_ref (tree decl, tsubst_flags_t 
complain, bool odr_use)
      if (!odr_use && context == containing_function)
        decl = add_default_capture (lambda_stack,
                                /*id=*/DECL_NAME (decl), initializer);
+  /* When doing lambda capture, if we found a capture in an enclosing lambda,
+     we can use it.  */
+  else if (!odr_use && is_capture_proxy (decl))
+    return decl;

What makes this OK is not that it's a capture, but that the captured

variable is constant, so it should have satisfied this branch:

    /* Only an odr-use of an outer automatic variable causes an
       error, and a constant variable can decay to a prvalue
       constant without odr-use.  So don't complain yet.  */
    else if (!odr_use && decl_constant_var_p (decl))
      return decl;

is_constant_capture_proxy might be useful here.  And/or a new
strip_normal_capture function (that I'm surprised doesn't exist yet).
Yeah, that makes a lot of sense, thanks. This is what the attached updated
patch does, successfully tested on x86_64-pc-linux-gnu. OK for trunk?

@@ -4601,7 +4599,7 @@ process_outer_var_ref (tree decl, tsubst_flags_t 
complain, bool odr_use)
    /* Only an odr-use of an outer automatic variable causes an
       error, and a constant variable can decay to a prvalue
       constant without odr-use.  So don't complain yet.  */
-  else if (!odr_use && decl_constant_var_p (decl))
+  else if (!odr_use && decl_constant_var_p (strip_normal_capture_proxy (decl)))
      return decl;

We also want to strip the proxy from the return value.
Doh, of course, sorry for overlooking this :-/ I checked if I could come up
with a test case that would fail with this mistake but failed to.

Anyway, I attach another revision that fixes the issue, and was successfully
tested on x86_64-pc-linux-gnu. OK for trunk?

OK.

Jason

Reply via email to