Hi,

On 18 Feb 2025, at 11:12, 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.
Friendly ping.

Thanks! Simon

>       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;
>    /* 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.  */
> diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested10.C 
> b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested10.C
> new file mode 100644
> index 00000000000..2dd9dd4955e
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested10.C
> @@ -0,0 +1,46 @@
> +// PR c++/110584
> +// { dg-do "run" { target c++11 } }
> +
> +void foo (int i) {
> +  if (i != 0)
> +    __builtin_abort ();
> +}
> +
> +int main () {
> +  const int x = 0;
> +
> +  // We would error out on this.
> +  (void) [&] () {
> +    foo (x);
> +    (void)[] () {
> +      foo (x);
> +    };
> +  } ();
> +  // As well as those.
> +  (void) [&] () {
> +    (void) [] () {
> +      foo (x);
> +    };
> +  } ();
> +  (void) [&x] () {
> +    (void) [] () {
> +      foo (x);
> +    };
> +  } ();
> +  // But those would work already.
> +  (void) [] () {
> +    (void) [&] () {
> +      foo (x);
> +    };
> +  } ();
> +  (void) [&] () {
> +    (void) [&] () {
> +      foo (x);
> +    };
> +  } ();
> +  (void) [=] () {
> +    (void) [] () {
> +      foo (x);
> +    };
> +  } ();
> +}
> -- 
> 2.44.0

Reply via email to