diff mbox series

c++: unifying lvalue vs rvalue (non-forwarding) ref [PR116710]

Message ID 20241015044737.1488180-1-ppalka@redhat.com
State New
Headers show
Series c++: unifying lvalue vs rvalue (non-forwarding) ref [PR116710] | expand

Commit Message

Patrick Palka Oct. 15, 2024, 4:47 a.m. UTC
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

Comments

Jason Merrill Oct. 15, 2024, 1:21 p.m. UTC | #1
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 mbox series

Patch

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" }
+}