This has undefined behaviour: #include <functional> int f() { return 0; } int main() { std::function<const int&()> ff = f; return ff(); } but the -Wreturn-local-addr warning that is enabled by default is suppressed in system headers. In file included from fun.cc:1:0: /home/jwakely/gcc/6/include/c++/6.0.0/functional: In instantiation of ‘static _Res std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes&& ...) [with _Res = const int&; _Functor = int (*)(); _ArgTypes = {}]’: /home/jwakely/gcc/6/include/c++/6.0.0/functional:2124:19: required from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = int (*)(); <template-parameter-2-2> = void; <template-parameter-2-3> = void; _Res = const int&; _ArgTypes = {}]’ fun.cc:7:36: required from here /home/jwakely/gcc/6/include/c++/6.0.0/functional:1726:40: warning: returning reference to temporary [-Wreturn-local-addr] std::forward<_ArgTypes>(__args)...); ^ We should either ensure the warning is enabled, even in system headers (similar to PR 58876) or add a run-time check to _Function_handler<_Res(_ArgTypes...), _Functor>::_M_invoke (it can't be a compile-time static assertion because that function is instantiated even if it's never called, and the code is only undefined if it's invoked).
Created attachment 38288 [details] Untested patch. We can enable -Wsystem-headers around the relevant function, but we also need a change to <ext/string_conversions.h> to suppress the false positive -Wsign-compare warnings in there.
Bah, it seems that -Wsystem-headers doesn't get turned off again by the #pragma GCC diagnostic pop
This should get addressed more thoroughly by https://wg21.link/p0932
*** Bug 103543 has been marked as a duplicate of this bug. ***
"A type trait to detect reference binding to temporary" https://wg21.link/p2255r2 is the current direction to resolve this.
(In reply to Jonathan Wakely from comment #5) > "A type trait to detect reference binding to temporary" > https://wg21.link/p2255r2 is the current direction to resolve this. Which is now recorded as PR 104477.
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:fa9bda3ea4315a7285edbc99323e3fa7885cbbb8 commit r13-2922-gfa9bda3ea4315a7285edbc99323e3fa7885cbbb8 Author: Jonathan Wakely <jwakely@redhat.com> Date: Tue Sep 27 20:59:05 2022 +0100 libstdc++: Make INVOKE<R> refuse to create dangling references [PR70692] This is the next part of the library changes from P2255R2. This makes INVOKE<R> ill-formed if converting the INVOKE expression to R would bind a reference to a temporary object. The is_invocable_r trait is now false if the invocation would create a dangling reference. This is done by adding the dangling check to the __is_invocable_impl partial specialization used for INVOKE<R> expressions. This change also slightly simplifies the nothrow checking recently added to that partial specialization. This change also removes the is_invocable_r checks from the pre-C++17 implementation of std::__invoke_r, because there is no need for it to be SFINAE-friendly. None of our C++11 and C++14 uses of INVOKE<R> require those constraints. The std::function constructor needs to check is_invocable_r, but that's already done explicitly, so we don't need to recheck when calling __is_invoke_r in std::function::operator(). The other uses of std::__is_invoke_r do not need to be constrained and can just be ill-formed if the INVOKE<R> expression is ill-formed. libstdc++-v3/ChangeLog: PR libstdc++/70692 * include/bits/invoke.h [__cplusplus < 201703] (__invoke_r): Remove is_invocable and is_convertible constraints. * include/std/type_traits (__is_invocable_impl::_S_conv): Use non-deduced context for parameter. (__is_invocable_impl::_S_test): Remove _Check_noex template parameter and use deduced noexcept value in its place. Add bool parameter to detect dangling references. (__is_invocable_impl::type): Adjust call to _S_test to avoid deducing unnecessary noexcept property.. (__is_invocable_impl::__nothrow_type): Rename to ... (__is_invocable_impl::__nothrow_conv): ... this. Adjust call to _S_test to deduce noexcept property. * testsuite/20_util/bind/dangling_ref.cc: New test. * testsuite/20_util/function/cons/70692.cc: New test. * testsuite/20_util/function_objects/invoke/dangling_ref.cc: New test. * testsuite/20_util/is_invocable/dangling_ref.cc: New test. * testsuite/30_threads/packaged_task/cons/dangling_ref.cc: New test.
Fixed for GCC 13 by implementing the changes from https://wg21.link/P2255R2 The original example is now ill-formed.