* [Bug c++/101566] gcc miscompiles lambda used as tuple-like object applied to function for call
2021-07-21 18:07 [Bug c++/101566] New: gcc miscompiles lambda used as tuple-like object applied to function for call weilercdale at gmail dot com
@ 2021-07-21 18:18 ` pinskia at gcc dot gnu.org
2021-07-21 18:24 ` weilercdale at gmail dot com
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-07-21 18:18 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101566
--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
f.0_1 = f_8(D);
tuple = t;
_11 = &tuple.__ts#2;
tuple ={v} {CLOBBER};
template<Size N, typename T>
constexpr decltype(auto) get(T tuple) { return *tuple(Get<N>{}); }
I think the above function (get) is broken and is returning a reference to the
argument and that would be invalid.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/101566] gcc miscompiles lambda used as tuple-like object applied to function for call
2021-07-21 18:07 [Bug c++/101566] New: gcc miscompiles lambda used as tuple-like object applied to function for call weilercdale at gmail dot com
2021-07-21 18:18 ` [Bug c++/101566] " pinskia at gcc dot gnu.org
@ 2021-07-21 18:24 ` weilercdale at gmail dot com
2021-07-21 18:34 ` pinskia at gcc dot gnu.org
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: weilercdale at gmail dot com @ 2021-07-21 18:24 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101566
--- Comment #2 from Dale Weiler <weilercdale at gmail dot com> ---
(In reply to Andrew Pinski from comment #1)
> f.0_1 = f_8(D);
> tuple = t;
> _11 = &tuple.__ts#2;
> tuple ={v} {CLOBBER};
>
>
> template<Size N, typename T>
> constexpr decltype(auto) get(T tuple) { return *tuple(Get<N>{}); }
>
>
> I think the above function (get) is broken and is returning a reference to
> the argument and that would be invalid.
Ah, passing `T&` here instead of T does appear to avoid the issue, the question
now becomes why does -fsanitize=undefined find nothing, and is the return type,
i.e `declval(get<N>(t))` different in gcc compared to the other compiles. I
would expect similar issues in the other compilers if this is returning a
reference to the temporary given by the argument list of `get`
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/101566] gcc miscompiles lambda used as tuple-like object applied to function for call
2021-07-21 18:07 [Bug c++/101566] New: gcc miscompiles lambda used as tuple-like object applied to function for call weilercdale at gmail dot com
2021-07-21 18:18 ` [Bug c++/101566] " pinskia at gcc dot gnu.org
2021-07-21 18:24 ` weilercdale at gmail dot com
@ 2021-07-21 18:34 ` pinskia at gcc dot gnu.org
2021-07-21 18:42 ` weilercdale at gmail dot com
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-07-21 18:34 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101566
--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Dale Weiler from comment #2)
> Ah, passing `T&` here instead of T does appear to avoid the issue, the
> question now becomes why does -fsanitize=undefined find nothing, and is the
> return type, i.e `declval(get<N>(t))` different in gcc compared to the other
> compiles. I would expect similar issues in the other compilers if this is
> returning a reference to the temporary given by the argument list of `get`
So -fsanitize=undefined adds some extra code which just happens to cause GCC
not to optimize as much.
Try -fsanitize=address instead which enables -fsanitize-address-use-after-scope
which should detect the problen but I see it does not ....
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/101566] gcc miscompiles lambda used as tuple-like object applied to function for call
2021-07-21 18:07 [Bug c++/101566] New: gcc miscompiles lambda used as tuple-like object applied to function for call weilercdale at gmail dot com
` (2 preceding siblings ...)
2021-07-21 18:34 ` pinskia at gcc dot gnu.org
@ 2021-07-21 18:42 ` weilercdale at gmail dot com
2021-07-21 18:51 ` weilercdale at gmail dot com
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: weilercdale at gmail dot com @ 2021-07-21 18:42 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101566
--- Comment #4 from Dale Weiler <weilercdale at gmail dot com> ---
(In reply to Andrew Pinski from comment #3)
> (In reply to Dale Weiler from comment #2)
> > Ah, passing `T&` here instead of T does appear to avoid the issue, the
> > question now becomes why does -fsanitize=undefined find nothing, and is the
> > return type, i.e `declval(get<N>(t))` different in gcc compared to the other
> > compiles. I would expect similar issues in the other compilers if this is
> > returning a reference to the temporary given by the argument list of `get`
>
> So -fsanitize=undefined adds some extra code which just happens to cause GCC
> not to optimize as much.
>
> Try -fsanitize=address instead which enables
> -fsanitize-address-use-after-scope which should detect the problem but I see
> it does not ....
I'm unsure why this would be a temporary, given:
auto lambda = [=](auto&& f) mutable -> decltype(auto) { return f(&ts...); };
This should capture all `ts...` by copy, the `f(&ts...)` should reference the
captures of `this` inside the lambda (of the compiler generated structure.)
When `get` is called, the values from the lambda are returned by dereferencing
since the function is called with pointers (synthesized with `&ts...` in the
lambda). I verified this by printing `typeid(decltype(get<N>(t))).name()`
passed to `__cxa_demangle`. There isn't any reference types, just to be sure
that's not some runtime quirk, the compile-time result of `std::is_same_v<int,
decltype(get<0>)>` is true.
Where is the temporary happening?
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/101566] gcc miscompiles lambda used as tuple-like object applied to function for call
2021-07-21 18:07 [Bug c++/101566] New: gcc miscompiles lambda used as tuple-like object applied to function for call weilercdale at gmail dot com
` (3 preceding siblings ...)
2021-07-21 18:42 ` weilercdale at gmail dot com
@ 2021-07-21 18:51 ` weilercdale at gmail dot com
2021-07-21 19:22 ` weilercdale at gmail dot com
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: weilercdale at gmail dot com @ 2021-07-21 18:51 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101566
--- Comment #5 from Dale Weiler <weilercdale at gmail dot com> ---
(In reply to Dale Weiler from comment #4)
> (In reply to Andrew Pinski from comment #3)
> > (In reply to Dale Weiler from comment #2)
> > > Ah, passing `T&` here instead of T does appear to avoid the issue, the
> > > question now becomes why does -fsanitize=undefined find nothing, and is the
> > > return type, i.e `declval(get<N>(t))` different in gcc compared to the other
> > > compiles. I would expect similar issues in the other compilers if this is
> > > returning a reference to the temporary given by the argument list of `get`
> >
> > So -fsanitize=undefined adds some extra code which just happens to cause GCC
> > not to optimize as much.
> >
> > Try -fsanitize=address instead which enables
> > -fsanitize-address-use-after-scope which should detect the problem but I see
> > it does not ....
>
> I'm unsure why this would be a temporary, given:
>
> auto lambda = [=](auto&& f) mutable -> decltype(auto) { return f(&ts...); };
>
> This should capture all `ts...` by copy, the `f(&ts...)` should reference
> the captures of `this` inside the lambda (of the compiler generated
> structure.)
>
> When `get` is called, the values from the lambda are returned by
> dereferencing since the function is called with pointers (synthesized with
> `&ts...` in the lambda). I verified this by printing
> `typeid(decltype(get<N>(t))).name()` passed to `__cxa_demangle`. There isn't
> any reference types, just to be sure that's not some runtime quirk, the
> compile-time result of `std::is_same_v<int, decltype(get<0>)>` is true.
>
> Where is the temporary happening?
This is curious, omitting `decltype(auto)` for get, as in just `auto` seems to
work around the issue as well.
template<Size N, typename T>
constexpr auto get(T tuple) { return *tuple(Get<N>{}); }
I'm a bit out of my element here, in that I don't understand the semantic
differences between the two and if that behavior is correct.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/101566] gcc miscompiles lambda used as tuple-like object applied to function for call
2021-07-21 18:07 [Bug c++/101566] New: gcc miscompiles lambda used as tuple-like object applied to function for call weilercdale at gmail dot com
` (4 preceding siblings ...)
2021-07-21 18:51 ` weilercdale at gmail dot com
@ 2021-07-21 19:22 ` weilercdale at gmail dot com
2021-07-21 19:23 ` weilercdale at gmail dot com
2021-07-21 19:56 ` redi at gcc dot gnu.org
7 siblings, 0 replies; 9+ messages in thread
From: weilercdale at gmail dot com @ 2021-07-21 19:22 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101566
Dale Weiler <weilercdale at gmail dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|--- |INVALID
Status|UNCONFIRMED |RESOLVED
--- Comment #6 from Dale Weiler <weilercdale at gmail dot com> ---
(In reply to Dale Weiler from comment #4)
> (In reply to Andrew Pinski from comment #3)
> > (In reply to Dale Weiler from comment #2)
> > > Ah, passing `T&` here instead of T does appear to avoid the issue, the
> > > question now becomes why does -fsanitize=undefined find nothing, and is the
> > > return type, i.e `declval(get<N>(t))` different in gcc compared to the other
> > > compiles. I would expect similar issues in the other compilers if this is
> > > returning a reference to the temporary given by the argument list of `get`
> >
> > So -fsanitize=undefined adds some extra code which just happens to cause GCC
> > not to optimize as much.
> >
> > Try -fsanitize=address instead which enables
> > -fsanitize-address-use-after-scope which should detect the problem but I see
> > it does not ....
>
> I'm unsure why this would be a temporary, given:
>
> auto lambda = [=](auto&& f) mutable -> decltype(auto) { return f(&ts...); };
>
> This should capture all `ts...` by copy, the `f(&ts...)` should reference
> the captures of `this` inside the lambda (of the compiler generated
> structure.)
>
> When `get` is called, the values from the lambda are returned by
> dereferencing since the function is called with pointers (synthesized with
> `&ts...` in the lambda). I verified this by printing
> `typeid(decltype(get<N>(t))).name()` passed to `__cxa_demangle`. There isn't
> any reference types, just to be sure that's not some runtime quirk, the
> compile-time result of `std::is_same_v<int, decltype(get<0>)>` is true.
>
> Where is the temporary happening?
This is curious, omitting `decltype(auto)` for get, as in just `auto` seems to
work around the issue as well.
template<Size N, typename T>
constexpr auto get(T tuple) { return *tuple(Get<N>{}); }
I'm a bit out of my element here, in that I don't understand the semantic
differences between the two and if that behavior is correct.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/101566] gcc miscompiles lambda used as tuple-like object applied to function for call
2021-07-21 18:07 [Bug c++/101566] New: gcc miscompiles lambda used as tuple-like object applied to function for call weilercdale at gmail dot com
` (5 preceding siblings ...)
2021-07-21 19:22 ` weilercdale at gmail dot com
@ 2021-07-21 19:23 ` weilercdale at gmail dot com
2021-07-21 19:56 ` redi at gcc dot gnu.org
7 siblings, 0 replies; 9+ messages in thread
From: weilercdale at gmail dot com @ 2021-07-21 19:23 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101566
--- Comment #7 from Dale Weiler <weilercdale at gmail dot com> ---
Yeah the code example is invalid, there is a reference to a temporary,
decltype(auto) on *ptr produces reference type, somehow I thought it produced
the value type, sorry for the confusion.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/101566] gcc miscompiles lambda used as tuple-like object applied to function for call
2021-07-21 18:07 [Bug c++/101566] New: gcc miscompiles lambda used as tuple-like object applied to function for call weilercdale at gmail dot com
` (6 preceding siblings ...)
2021-07-21 19:23 ` weilercdale at gmail dot com
@ 2021-07-21 19:56 ` redi at gcc dot gnu.org
7 siblings, 0 replies; 9+ messages in thread
From: redi at gcc dot gnu.org @ 2021-07-21 19:56 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101566
--- Comment #8 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Dale Weiler from comment #5)
> This is curious, omitting `decltype(auto)` for get, as in just `auto` seems
> to work around the issue as well.
>
> template<Size N, typename T>
> constexpr auto get(T tuple) { return *tuple(Get<N>{}); }
>
> I'm a bit out of my element here, in that I don't understand the semantic
> differences between the two and if that behavior is correct.
auto makes it return by value, decltype(auto) returns exactly the type of the
return statement (so if it's a reference, so is the return type).
^ permalink raw reply [flat|nested] 9+ messages in thread