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