On 7/22/25 4:18 PM, Patrick Palka wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk?
OK, and I think go ahead and apply it to the 15 branch as well.
-- >8 --
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.
---
gcc/cp/method.cc | 3 ++-
gcc/testsuite/g++.dg/ext/is_invocable5.C | 12 ++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/ext/is_invocable5.C
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..d9c0a1162fb0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_invocable5.C
@@ -0,0 +1,12 @@
+// 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>) );