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.