public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/116439] New: [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture
@ 2024-08-21 10:18 valentin at tolmer dot fr
  2024-08-21 10:49 ` [Bug c++/116439] " rguenth at gcc dot gnu.org
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: valentin at tolmer dot fr @ 2024-08-21 10:18 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 116439
           Summary: [14/15 Regression] decltype(auto) in return type of
                    lambda uses the type of the outer scope, not the
                    capture
           Product: gcc
           Version: 14.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: valentin at tolmer dot fr
  Target Milestone: ---

$ cat source.cpp
struct S {
  S() = default;
  S(const S&) = delete;
};

int main() {
  S source;
  [&] -> decltype(auto) {
    return source;
  }();
}
$ g++ -std=c++23 source.cpp
source.cpp: In lambda function:
source.cpp:9:12: error: use of deleted function 'S::S(const S&)'
    9 |     return source;
      |            ^~~~~~
source.cpp:3:3: note: declared here
    3 |   S(const S&) = delete;
      |   ^
source.cpp:9:12: note: use '-fdiagnostics-all-candidates' to display considered
candidates
    9 |     return source;
      |            ^~~~~~
Compiler returned: 1

AFAIU, starting from 14.1 the decltype(auto) deduces the type from the `S
source;`, the outer variable, rather than the implicit by-ref capture of the
same name. Writing `return (source);` correctly deduces the reference.
Introducing an explicitly named capture `[&source = source]` correctly deduces
the reference.
GCC 13.3 and below returns a reference.

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

* [Bug c++/116439] [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture
  2024-08-21 10:18 [Bug c++/116439] New: [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture valentin at tolmer dot fr
@ 2024-08-21 10:49 ` rguenth at gcc dot gnu.org
  2024-08-21 14:57 ` mpolacek at gcc dot gnu.org
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: rguenth at gcc dot gnu.org @ 2024-08-21 10:49 UTC (permalink / raw)
  To: gcc-bugs

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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |14.3

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

* [Bug c++/116439] [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture
  2024-08-21 10:18 [Bug c++/116439] New: [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture valentin at tolmer dot fr
  2024-08-21 10:49 ` [Bug c++/116439] " rguenth at gcc dot gnu.org
@ 2024-08-21 14:57 ` mpolacek at gcc dot gnu.org
  2024-08-22 15:04 ` ppalka at gcc dot gnu.org
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: mpolacek at gcc dot gnu.org @ 2024-08-21 14:57 UTC (permalink / raw)
  To: gcc-bugs

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

Marek Polacek <mpolacek at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |mpolacek at gcc dot gnu.org,
                   |                            |ppalka at gcc dot gnu.org

--- Comment #1 from Marek Polacek <mpolacek at gcc dot gnu.org> ---
Started with r14-5330-g705ab7927c81b7:

commit 705ab7927c81b77503d229513fac991106617766
Author: Patrick Palka <ppalka@redhat.com>
Date:   Fri Nov 10 10:58:04 2023 -0500

    c++: decltype of capture proxy [PR79378, PR96917]

clang++ also rejects the code.

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

* [Bug c++/116439] [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture
  2024-08-21 10:18 [Bug c++/116439] New: [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture valentin at tolmer dot fr
  2024-08-21 10:49 ` [Bug c++/116439] " rguenth at gcc dot gnu.org
  2024-08-21 14:57 ` mpolacek at gcc dot gnu.org
@ 2024-08-22 15:04 ` ppalka at gcc dot gnu.org
  2024-08-23 13:56 ` valentin at tolmer dot fr
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: ppalka at gcc dot gnu.org @ 2024-08-22 15:04 UTC (permalink / raw)
  To: gcc-bugs

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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |INVALID
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #2 from Patrick Palka <ppalka at gcc dot gnu.org> ---
I believe GCC 14 is behaving correctly according to the standard now.

According to https://eel.is/c++draft/expr.prim.lambda#capture-note-7,
decltype(source) must be S not S&, despite the by-ref capture.  And a
decltype(auto) deduced return type is equivalent decltype(return-expr), so it
must deduce to S here as well.  GCC's previous behavior was inconsistent and
incorrect in the decltype(auto) case.

Doing an init-capture [&source = source] yields S& because in that case there
is no "original entity" (the init-capture is its own independent entity), and
the note doesn't apply, I think.

See also
https://stackoverflow.com/questions/33854388/decltypeauto-deduced-return-type-from-lambda-capture

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

* [Bug c++/116439] [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture
  2024-08-21 10:18 [Bug c++/116439] New: [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture valentin at tolmer dot fr
                   ` (2 preceding siblings ...)
  2024-08-22 15:04 ` ppalka at gcc dot gnu.org
@ 2024-08-23 13:56 ` valentin at tolmer dot fr
  2024-08-23 15:02 ` ppalka at gcc dot gnu.org
  2024-08-23 15:06 ` ppalka at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: valentin at tolmer dot fr @ 2024-08-23 13:56 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Valentin Tolmer <valentin at tolmer dot fr> ---
Digging a little bit into it, there is definitely a bug that was in 14.1 only
(and got fixed in 14.2):

struct S {
  S() = default;
  S(const S&) = delete;
};

int main() {
  S source;
  S& source2 = source;
  // Fails only in 14.1
  [](auto& key) -> S& {
    return [&] -> decltype(auto) { return key; }();
  }(source);
  [&] -> decltype(auto) { return source2; }();
  // Fails on clang++, gcc 14.1 and 14.2
  [&]() -> S& {
    return [&] -> decltype(auto) { return source; }();
  }();
  [&] -> decltype(auto) { return source; }();
}

The first 2 lambdas should clearly deduce S& for the decltype(auto), but don't
in 14.1.

Patrick, I don't think the note you linked applies here: it's not within the
compounds statement of a lambda, and it doesn't refer to a capture by value.

I think the relevant part is
"An id-expression within the compound-statement of a lambda-expression that is
an odr-use of a reference captured by reference refers to the entity to which
the captured reference is bound and not to the captured reference." which would
mean that it gets resolved to decltype(source) and thus S.

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

* [Bug c++/116439] [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture
  2024-08-21 10:18 [Bug c++/116439] New: [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture valentin at tolmer dot fr
                   ` (3 preceding siblings ...)
  2024-08-23 13:56 ` valentin at tolmer dot fr
@ 2024-08-23 15:02 ` ppalka at gcc dot gnu.org
  2024-08-23 15:06 ` ppalka at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: ppalka at gcc dot gnu.org @ 2024-08-23 15:02 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Ah yes, that's PR115504 I think.  The original fix was incorrectly stripping
references from the captured variable type which was fixed for 14.2 by
r15-1631.

It's correct but certainly weird that the current rules mean the second to last
decltype(auto) is invalid, because decltype(source) is S& but the closure
member is const S&..

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

* [Bug c++/116439] [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture
  2024-08-21 10:18 [Bug c++/116439] New: [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture valentin at tolmer dot fr
                   ` (4 preceding siblings ...)
  2024-08-23 15:02 ` ppalka at gcc dot gnu.org
@ 2024-08-23 15:06 ` ppalka at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: ppalka at gcc dot gnu.org @ 2024-08-23 15:06 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from Patrick Palka <ppalka at gcc dot gnu.org> ---
(In reply to Patrick Palka from comment #4)
> It's correct but certainly weird that the current rules mean the second to
> last decltype(auto) is invalid, because decltype(source) is S& but the
> closure member is const S&..
D'oh, ignore this, I totally misinterpreted the testcase.   The weird example I
had in mind was https://gcc.gnu.org/pipermail/gcc-patches/2024-June/655632.html
FWIW

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

end of thread, other threads:[~2024-08-23 15:06 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-08-21 10:18 [Bug c++/116439] New: [14/15 Regression] decltype(auto) in return type of lambda uses the type of the outer scope, not the capture valentin at tolmer dot fr
2024-08-21 10:49 ` [Bug c++/116439] " rguenth at gcc dot gnu.org
2024-08-21 14:57 ` mpolacek at gcc dot gnu.org
2024-08-22 15:04 ` ppalka at gcc dot gnu.org
2024-08-23 13:56 ` valentin at tolmer dot fr
2024-08-23 15:02 ` ppalka at gcc dot gnu.org
2024-08-23 15:06 ` 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).