Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk?

-- >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>) );
-- 
2.50.1.319.g90c0775e97

Reply via email to