Message ID | 20241015044737.1488180-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: unifying lvalue vs rvalue (non-forwarding) ref [PR116710] | expand |
On 10/15/24 12:47 AM, Patrick Palka wrote: > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look > OK for trunk? OK. > -- >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" } > +}
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" } +}