public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/94376] New: When nested inside a lambda body, [=] captures by const value instead of by value
@ 2020-03-28  0:14 arthur.j.odwyer at gmail dot com
  2021-11-02 17:27 ` [Bug c++/94376] " ppalka at gcc dot gnu.org
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: arthur.j.odwyer at gmail dot com @ 2020-03-28  0:14 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94376

            Bug ID: 94376
           Summary: When nested inside a lambda body, [=] captures by
                    const value instead of by value
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: arthur.j.odwyer at gmail dot com
  Target Milestone: ---

David Blaikie, Richard Smith, and I discovered this GCC bug while tracking down
a separate bug in llvm::function_ref whose constructor template was improperly
SFINAEd so that construction from `const T&&` was done wrong. A GCC bug caused
construction from `const T&&` to happen on GCC but not on Clang or EDG. Here's
the reduced test case:

// https://godbolt.org/z/oCvLpv
#include <stdio.h>
#include <utility>

struct I {
    I() { puts(__PRETTY_FUNCTION__); }
    I(I&) { puts(__PRETTY_FUNCTION__); }
    I(const I&) { puts(__PRETTY_FUNCTION__); }
    I(I&&) { puts(__PRETTY_FUNCTION__); }
    I(const I&&) { puts(__PRETTY_FUNCTION__); }

    void operator++() const {}
};

int main() {
    I i;
    auto one = [=]() { 
        return [=]() {
            ++i;
        };
    }();
    puts("-----");
    auto two = std::move(one);  // !!
}

On the line marked "!!", one's implicitly generated move-constructor calls
`I(const I&&)` rather than `I(I&&)` to move the captured copy of `i`. It does
this because it has improperly decided that the type of the captured copy of
`i` should be `const I` instead of plain old `I`.

Richard Smith writes:
> [expr.prim.lambda.capture]p10 is the relevant rule:
> "The type of such a data member is the referenced type
> if the entity is a reference to an object, an lvalue reference
> to the referenced function type if the entity is a reference to a function,
> or the type of the corresponding captured entity otherwise."
>
> Regardless of whether you think the captured entity is
> the original variable or the member of the outer closure type,
> the type of that entity is not const-qualified.
> So the inner capture should not have a const-qualified type.

Besides exposing bugs in llvm::function_ref (a good effect!), GCC's
implementation divergence here could have the bad effect of causing additional
expensive copies when lambdas with improperly const-qualified captures are
moved around. Example:
https://godbolt.org/z/LWEF47


Bug 86697 might be related:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86697

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/94376] When nested inside a lambda body, [=] captures by const value instead of by value
  2020-03-28  0:14 [Bug c++/94376] New: When nested inside a lambda body, [=] captures by const value instead of by value arthur.j.odwyer at gmail dot com
@ 2021-11-02 17:27 ` ppalka at gcc dot gnu.org
  2021-11-19 13:54 ` cvs-commit at gcc dot gnu.org
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: ppalka at gcc dot gnu.org @ 2021-11-02 17:27 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94376

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2021-11-02
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |ASSIGNED
           Assignee|unassigned at gcc dot gnu.org      |ppalka at gcc dot gnu.org
                 CC|                            |ppalka at gcc dot gnu.org
           Keywords|                            |rejects-valid

--- Comment #1 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Confrimed, not a regression.

rejects-valid testcase:

int main() {
  int i = 0;
  [=] () {
    [=] () mutable {
      ++i;
    };
  };
}

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/94376] When nested inside a lambda body, [=] captures by const value instead of by value
  2020-03-28  0:14 [Bug c++/94376] New: When nested inside a lambda body, [=] captures by const value instead of by value arthur.j.odwyer at gmail dot com
  2021-11-02 17:27 ` [Bug c++/94376] " ppalka at gcc dot gnu.org
@ 2021-11-19 13:54 ` cvs-commit at gcc dot gnu.org
  2021-11-19 13:56 ` ppalka at gcc dot gnu.org
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2021-11-19 13:54 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94376

--- Comment #2 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:fd740165e54151ea794fca34904f5c2e2ea1dcda

commit r12-5403-gfd740165e54151ea794fca34904f5c2e2ea1dcda
Author: Patrick Palka <ppalka@redhat.com>
Date:   Fri Nov 19 08:54:25 2021 -0500

    c++: nested lambda capturing a capture proxy [PR94376]

    Here when determining the type of the FIELD_DECL for the by-value capture
    of 'i' in the inner lambda, we incorrectly give it the type const int
    instead of int since the effective initializer is the proxy for the outer
    capture, and this proxy is const since the outer lambda is non-mutable.

    This patch fixes this by making lambda_capture_field_type handle
    by-value capturing of capture proxies specially, namely we instead
    consider the type of their FIELD_DECL which unlike the proxy has the
    true cv-quals of the captured entity.

            PR c++/94376

    gcc/cp/ChangeLog:

            * lambda.c (lambda_capture_field_type): Simplify by handling the
            is_this case first.  When capturing by-value a capture proxy,
            consider the type of the corresponding field instead.

    gcc/testsuite/ChangeLog:

            * g++.dg/cpp0x/lambda/lambda-nested9.C: New test.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/94376] When nested inside a lambda body, [=] captures by const value instead of by value
  2020-03-28  0:14 [Bug c++/94376] New: When nested inside a lambda body, [=] captures by const value instead of by value arthur.j.odwyer at gmail dot com
  2021-11-02 17:27 ` [Bug c++/94376] " ppalka at gcc dot gnu.org
  2021-11-19 13:54 ` cvs-commit at gcc dot gnu.org
@ 2021-11-19 13:56 ` ppalka at gcc dot gnu.org
  2021-12-19 19:42 ` cvs-commit at gcc dot gnu.org
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: ppalka at gcc dot gnu.org @ 2021-11-19 13:56 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94376

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |RESOLVED
         Resolution|---                         |FIXED
   Target Milestone|---                         |12.0

--- Comment #3 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Fixed for GCC 12.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/94376] When nested inside a lambda body, [=] captures by const value instead of by value
  2020-03-28  0:14 [Bug c++/94376] New: When nested inside a lambda body, [=] captures by const value instead of by value arthur.j.odwyer at gmail dot com
                   ` (2 preceding siblings ...)
  2021-11-19 13:56 ` ppalka at gcc dot gnu.org
@ 2021-12-19 19:42 ` cvs-commit at gcc dot gnu.org
  2021-12-28 10:01 ` pinskia at gcc dot gnu.org
  2022-04-26 20:26 ` ppalka at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2021-12-19 19:42 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94376

--- Comment #4 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:89cf57ea35d1e0a0b818997c737ac70b7310d9d9

commit r12-6065-g89cf57ea35d1e0a0b818997c737ac70b7310d9d9
Author: Patrick Palka <ppalka@redhat.com>
Date:   Sun Dec 19 14:42:14 2021 -0500

    c++: nested lambda capturing a capture proxy, cont [PR94376]

    The r12-5403 fix apparently doesn't handle the case where the inner
    lambda explicitly rather than implicitly captures the capture proxy from
    the outer lambda, which causes us to reject the first example in the
    testcase below.

    This is because compared to an implicit capture, the effective initializer
    for an explicit capture is wrapped in a location wrapper (pointing to
within
    the capture list), and this wrapper foils the is_capture_proxy check added
    in r12-5403.

    The simplest fix appears to be to strip location wrappers accordingly
    before checking is_capture_proxy.  And to help prevent against this kind
    of bug, this patch also makes is_capture_proxy assert it doesn't see a
    location wrapper.

            PR c++/94376

    gcc/cp/ChangeLog:

            * lambda.c (lambda_capture_field_type): Strip location wrappers
            before checking for a capture proxy.
            (is_capture_proxy): Assert that we don't see a location wrapper.
            (mark_const_cap_r): Don't call is_constant_capture_proxy on a
            location wrapper.

    gcc/testsuite/ChangeLog:

            * g++.dg/cpp0x/lambda/lambda-nested9a.C: New test.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/94376] When nested inside a lambda body, [=] captures by const value instead of by value
  2020-03-28  0:14 [Bug c++/94376] New: When nested inside a lambda body, [=] captures by const value instead of by value arthur.j.odwyer at gmail dot com
                   ` (3 preceding siblings ...)
  2021-12-19 19:42 ` cvs-commit at gcc dot gnu.org
@ 2021-12-28 10:01 ` pinskia at gcc dot gnu.org
  2022-04-26 20:26 ` ppalka at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-12-28 10:01 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94376

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |rafael at espindo dot la

--- Comment #5 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
*** Bug 95368 has been marked as a duplicate of this bug. ***

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/94376] When nested inside a lambda body, [=] captures by const value instead of by value
  2020-03-28  0:14 [Bug c++/94376] New: When nested inside a lambda body, [=] captures by const value instead of by value arthur.j.odwyer at gmail dot com
                   ` (4 preceding siblings ...)
  2021-12-28 10:01 ` pinskia at gcc dot gnu.org
@ 2022-04-26 20:26 ` ppalka at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: ppalka at gcc dot gnu.org @ 2022-04-26 20:26 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94376

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |cuzdav at gmail dot com

--- Comment #6 from Patrick Palka <ppalka at gcc dot gnu.org> ---
*** Bug 94624 has been marked as a duplicate of this bug. ***

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-04-26 20:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-28  0:14 [Bug c++/94376] New: When nested inside a lambda body, [=] captures by const value instead of by value arthur.j.odwyer at gmail dot com
2021-11-02 17:27 ` [Bug c++/94376] " ppalka at gcc dot gnu.org
2021-11-19 13:54 ` cvs-commit at gcc dot gnu.org
2021-11-19 13:56 ` ppalka at gcc dot gnu.org
2021-12-19 19:42 ` cvs-commit at gcc dot gnu.org
2021-12-28 10:01 ` pinskia at gcc dot gnu.org
2022-04-26 20:26 ` ppalka at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).