https://gcc.gnu.org/g:04a176a1d84a84c630cfd4d232736c12b105957a
commit r16-2447-g04a176a1d84a84c630cfd4d232736c12b105957a Author: Patrick Palka <ppa...@redhat.com> Date: Wed Jul 23 08:31:46 2025 -0400 c++: fix __is_invocable for std::reference_wrapper [PR121055] Our implementation of the INVOKE spec ([func.require]) was incorrectly treating reference_wrapper<T>::get() as returning T instead of T&, which notably makes a difference when invoking a ref-qualified memfn pointer. PR c++/121055 gcc/cp/ChangeLog: * method.cc (build_invoke): Correct reference_wrapper handling. gcc/testsuite/ChangeLog: * g++.dg/ext/is_invocable5.C: New test. Reviewed-by: Jason Merrill <ja...@redhat.com> Diff: --- gcc/cp/method.cc | 3 ++- gcc/testsuite/g++.dg/ext/is_invocable5.C | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index a4089c53c67b..334c325842f7 100644 --- a/gcc/cp/method.cc +++ b/gcc/cp/method.cc @@ -2036,10 +2036,11 @@ build_invoke (tree fn_type, const_tree arg_types, tsubst_flags_t complain) const_tree name = DECL_NAME (datum_decl); if (name && (id_equal (name, "reference_wrapper"))) { - /* 1.2 & 1.5: Retrieve T from std::reference_wrapper<T>, + /* 1.2 & 1.5: Retrieve T& from std::reference_wrapper<T>, i.e., decltype(datum.get()). */ datum_type = TREE_VEC_ELT (TYPE_TI_ARGS (non_ref_datum_type), 0); + datum_type = cp_build_reference_type (datum_type, false); datum_is_refwrap = true; } } diff --git a/gcc/testsuite/g++.dg/ext/is_invocable5.C b/gcc/testsuite/g++.dg/ext/is_invocable5.C new file mode 100644 index 000000000000..460eed595a9a --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_invocable5.C @@ -0,0 +1,15 @@ +// PR c++/121055 +// { dg-do compile { target c++11 } } +// { dg-skip-if "requires hosted libstdc++ for functional function" { ! hostedlib } } + +#include <functional> + +#define SA(X) static_assert((X),#X) + +struct F; + +SA( __is_invocable(void (F::*)() &, std::reference_wrapper<F>) ); +SA( ! __is_invocable(void (F::*)() &&, std::reference_wrapper<F>) ); + +SA( __is_invocable(void (F::*)(int) &, std::reference_wrapper<F>, int) ); +SA( ! __is_invocable(void (F::*)(int) &&, std::reference_wrapper<F>, int) );