Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk?
-- >8 -- When unifying two (non-forwarding) reference types, unify immediately recurses into the reference type without first comparing rvalueness. (Note that at this point forwarding references have already been collapsed into non-references by maybe_adjust_types_for_deduction.) gcc/cp/ChangeLog: * pt.cc (unify) <case REFERENCE_TYPE>: Compare rvalueness. gcc/testsuite/ChangeLog: * g++.dg/template/unify12.C: New test. --- gcc/cp/pt.cc | 3 ++- gcc/testsuite/g++.dg/template/unify12.C | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/template/unify12.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index af784a41265..c7cbf6df26c 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -25154,7 +25154,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, } case REFERENCE_TYPE: - if (!TYPE_REF_P (arg)) + if (!TYPE_REF_P (arg) + || TYPE_REF_IS_RVALUE (parm) != TYPE_REF_IS_RVALUE (arg)) return unify_type_mismatch (explain_p, parm, arg); return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg), strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p); diff --git a/gcc/testsuite/g++.dg/template/unify12.C b/gcc/testsuite/g++.dg/template/unify12.C new file mode 100644 index 00000000000..84e4efb4cd9 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/unify12.C @@ -0,0 +1,24 @@ +// PR c++/116710 +// { dg-do compile { target c++11 } } + +template <typename T> struct A : T {}; + +template <typename T> +void f(void (*)(T &), typename A<T>::type * = 0); + +void f(...); + +void g(int &&); + +void q() { f(g); } // OK + +template<class T> +struct B { operator B<T&>(); }; + +template<class T> +void h(B<T&>); + +int main() { + B<int&&> b; + h(b); // { dg-error "no match" } +} -- 2.47.0.72.gef8ce8f3d4