Hi, On Thu Mar 6, 2025 at 8:06 PM CET, 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? Friendly ping.
Thanks, Simon