8 Commits
Author SHA1 Message Date
Tomasz Kamiński b58cf25443 libstdc++: Make function_ref non-dangling for stateless wrappers
This patch makes the function_ref non-dangling for the stateless
wrappers:
* any functor for which operator() selected for arguments is static,
* standard functors, including pre-C++20 ones.
In other words, any function_ref fr, that is constructed from stateless
wrapper w, can be still called after the object w is destroyed, e.g.:
  std::function_ref<bool(int, int)> fr(std::ranges::less{});
  fr(1, 2); // OK, previously UB because fr referred to already destroyed
            // temporary
As function_ref's operator() is not constexpr, we test the change by checking
if the above declaration can be made constexpr, as such variable cannot contain
dangling pointer values.

We adjust the function_ref generic constructor from any functor, to use more
specialized invoker:
* _S_static (newly added) if the called operator() overload is static,
  after changes r16-5624-g0ea9d760fbf44c, this covers all post-c++20 functors;
* _S_nttp<_Fd{}> for pre-C++20 standard functors.
In both above cases the value of _M_ptrs is ignored and simply set to nullptr.

This follows same technique (checking _Fd::operator()(args...)), and support
the same set of types, as for one used for the transform views iterators in
r16-5625-g9ed821d107f7a1.

As after this change we provide well-defined behavior for the code, that
previous was undefined, this changes is pure quality-of-implementation.
As illustrated by the test cases, it has observable side effects, where
non-longer dangling constructs can be used to define constexpr function_ref.
However, the standard does not define when the constructors defined constexpr
are actually usable at compile time, and the already have precedent in form
of SSO string for validity such constructs being implementation specific.

libstdc++-v3/ChangeLog:

	* include/bits/funcref_impl.h (function_ref::function_ref(_Fn&&)):
	Use _S_static and _S_nttp invokers.
	* include/bits/funcwrap.h (_Base_invoker::_S_static):
	Define.
	* include/bits/stl_function.h (std::__is_std_op_template)
	(std::__is_std_op_wrapper) [__cplusplus > 201703L]:
	Moved from std/ranges.
	* include/std/ranges (__detail::__is_std_op_template)
	(__detail::__is_std_op_wrapper): Moved to bits/stl_function.h.
	* testsuite/20_util/function_ref/dangling.cc: New test.
	* testsuite/20_util/function_ref/dangling_neg.cc: New test.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2026-02-11 17:54:09 +01:00
Tomasz Kamiński d7e5113e59 libstdc++: Explicitly call _Mo_base() in _Cpy_base copy-constructor [PR123758]
This silences the warning while preserving current (correct) behavior.

	PR libstdc++/123758

libstdc++-v3/ChangeLog:

	* include/bits/funcwrap.h (_Cpy_base(_Cpy_base const&)):
	Explicitly call _Mo_base() in initializer list.
2026-01-23 11:13:33 +01:00
Tomasz Kamiński 7dcfe01767 libstdc++: Deduce function_ref<M&() noexcept> from member object pointers.
Implement resolution of LWG4425.

libstdc++-v3/ChangeLog:

	* include/bits/funcwrap.h (__polyfunc::__deduce_funcref):
	Adjust signature produced for member object pointers.
	* testsuite/20_util/function_ref/deduction.cc: Update tests.
2025-10-20 17:42:19 +02:00
Tomasz Kamiński 7dd28f0a81 libstdc++: Make function_ref(nontype<f>, r) CTAD SFINAE friendly [PR121940]
Instantiating the __deduce_funcref function body for function pointers
without arguments or member pointers with non-matching object types
previously led to hard errors due to the formation of invalid types.

The __deduce_funcref function is now adjusted to return void in such
cases. The corresponding function_ref deduction guide is constrained to
only match if the return type is not void, making it SFINAE friendly.

	PR libstdc++/121940

libstdc++-v3/ChangeLog:

	* include/bits/funcwrap.h (__polyfunc::__deduce_funcref): Return void
	for ill-formed constructs.
	(function_ref(nontype_t<__f>, _Tp&&)): Constrain on __deduce_funcref
	producing non-void results.
	* testsuite/20_util/function_ref/deduction.cc: Negative tests.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-09-23 15:17:07 +02:00
Tomasz Kamiński 45ea1c542e libstdc++: Reduce chances of object aliasing for function wrapper.
Previously, an empty functor (EmptyIdFunc) stored inside a
std::move_only_function being first member of a Composite class could have the
same address as the base of the EmptyIdFunc type (see included test cases),
resulting in two objects of the same type at the same address.

This commit addresses the issue by moving the internal buffer from the start
of the wrapper object to a position after the manager function pointer. This
minimizes aliasing with the stored buffer but doesn't completely eliminate it,
especially when multiple empty base objects are involved (PR121180).

To facilitate this member reordering, the private section of _Mo_base was
eliminated, and the corresponding _M_manager and _M_destroy members were made
protected. They remain inaccessible to users, as user-facing wrappers derive
from _Mo_base privately.

libstdc++-v3/ChangeLog:

	* include/bits/funcwrap.h (__polyfunc::_Mo_base): Reorder _M_manage
	and _M_storage members. Make _M_destroy protected and remove friend
	declaration.
	* testsuite/20_util/copyable_function/call.cc: Add test for aliasing
	base class.
	* testsuite/20_util/move_only_function/call.cc: Likewise.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-08-27 06:35:04 +02:00
Tomasz Kamiński 08031b88e2 libstdc++: Pass small trivial types by value in polymorphic wrappers
This patch adjust the passing of parameters for the move_only_function,
copyable_function and function_ref. For types that are declared as being passed
by value in signature template argument, they are passed by value to the invoker,
when they are small (at most two pointers), trivially move constructible and
trivially destructible. The latter guarantees that passing them by value has not
user visible side effects.

In particular, this extends the set of types forwarded by value, that was
previously limited to scalars, to also include specializations of std::span and
std::string_view, and similar standard and program defined-types.

Checking the suitability of the parameter types requires the types to be complete.
As a consequence, the implementation imposes requirements on instantiation of
move_only_function and copyable_function. To avoid producing the errors from
the implementation details, a static assertion was added to partial
specializations of copyable_function, move_only_function and function_ref.
The static assertion uses existing __is_complete_or_unbounded, as arrays type
parameters are automatically decayed in function type.

Standard already specifies in [res.on.functions] p2.5 that instantiating these
partial specialization with incomplete types leads to undefined behavior.

libstdc++-v3/ChangeLog:

	* include/bits/funcwrap.h (__polyfunc::__pass_by_rref): Define.
	(__polyfunc::__param_t): Update to use __pass_by_rref.
	* include/bits/cpyfunc_impl.h:: Assert that are parameters type
	are complete.
	* include/bits/funcref_impl.h: Likewise.
	* include/bits/mofunc_impl.h: Likewise.
	* testsuite/20_util/copyable_function/call.cc: New test.
	* testsuite/20_util/function_ref/call.cc: New test.
	* testsuite/20_util/move_only_function/call.cc: New test.
	* testsuite/20_util/copyable_function/conv.cc: New test.
	* testsuite/20_util/function_ref/conv.cc: New test.
	* testsuite/20_util/move_only_function/conv.cc: New test.
	* testsuite/20_util/copyable_function/incomplete_neg.cc: New test.
	* testsuite/20_util/function_ref/incomplete_neg.cc: New test.
	* testsuite/20_util/move_only_function/incomplete_neg.cc: New test.

Reviewed-by: Patrick Palka <ppalka@redhat.com>
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-06-02 13:52:35 +02:00
Tomasz Kamiński 545433e9bd libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.

As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.

The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.

This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.

Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.

	PR libstdc++/119126

libstdc++-v3/ChangeLog:

	* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
	* include/Makefile.am: Added funcref_impl.h file.
	* include/Makefile.in: Added funcref_impl.h file.
	* include/bits/funcref_impl.h: New file.
	* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
	(_Storage::_M_ptr, _Storage::_M_ref): Remove.
	(__polyfunc::__cast_to) Define.
	(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
	(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
	(_Base_invoker::_S_call_ptrs): Define.
	(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
	(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
	const qualified.
	(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
	__glibcxx_move_only_function || __glibcxx_copyable_function.
	(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
	(std::function_ref) [__glibcxx_function_ref]: Define.
	* include/bits/utility.h (std::nontype_t, std::nontype)
	(__is_nontype_v) [__glibcxx_function_ref]: Define.
	* include/bits/version.def: Define function_ref.
	* include/bits/version.h: Regenerate.
	* include/std/functional: Define __cpp_lib_function_ref.
	* src/c++23/std.cc.in (std::nontype_t, std::nontype)
	(std::function_ref) [__cpp_lib_function_ref]: Export.
	* testsuite/20_util/function_ref/assign.cc: New test.
	* testsuite/20_util/function_ref/call.cc: New test.
	* testsuite/20_util/function_ref/cons.cc: New test.
	* testsuite/20_util/function_ref/cons_neg.cc: New test.
	* testsuite/20_util/function_ref/conv.cc: New test.
	* testsuite/20_util/function_ref/deduction.cc: New test.
	* testsuite/20_util/function_ref/mutation.cc: New test.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-26 11:25:28 +02:00
Tomasz Kamiński d9055d0104 libstdc++: Renamed bits/move_only_function.h to bits/funcwrap.h [PR119125]
The file now includes copyable_function in addition to
move_only_function.

	PR libstdc++/119125

libstdc++-v3/ChangeLog:
	* include/bits/move_only_function.h: Move to...
	* include/bits/funcwrap.h: ...here.
	* doc/doxygen/stdheader.cc (init_map): Replaced move_only_function.h
	with funcwrap.h, and changed include guard to use feature test macro.
	Move bits/version.h include before others.
	* include/Makefile.am: Likewise.
	* include/Makefile.in: Likewise.
	* include/std/functional: Likewise.

Reviewed-by: Patrick Palka <ppalka@redhat.com>
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 15:00:41 +02:00