From: Patrick Palka Date: Wed, 23 Jul 2025 12:31:46 +0000 (-0400) Subject: c++: fix __is_invocable for std::reference_wrapper [PR121055] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80a51dae8b9af3f6b318f8ed71c67aab96a3fc91;p=thirdparty%2Fgcc.git c++: fix __is_invocable for std::reference_wrapper [PR121055] Our implementation of the INVOKE spec ([func.require]) was incorrectly treating reference_wrapper::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 (cherry picked from commit 04a176a1d84a84c630cfd4d232736c12b105957a) --- diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc index 05c19cf0661..cf16fc9fc25 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, + /* 1.2 & 1.5: Retrieve T& from std::reference_wrapper, 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 00000000000..460eed595a9 --- /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 + +#define SA(X) static_assert((X),#X) + +struct F; + +SA( __is_invocable(void (F::*)() &, std::reference_wrapper) ); +SA( ! __is_invocable(void (F::*)() &&, std::reference_wrapper) ); + +SA( __is_invocable(void (F::*)(int) &, std::reference_wrapper, int) ); +SA( ! __is_invocable(void (F::*)(int) &&, std::reference_wrapper, int) );