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