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?