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