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


Reply via email to