diff mbox series

c++: covariant reference return type [PR99664]

Message ID 20210715163718.1707452-1-ppalka@redhat.com
State New
Headers show
Series c++: covariant reference return type [PR99664] | expand

Commit Message

Patrick Palka July 15, 2021, 4:37 p.m. UTC
This implements the wording changes of DR 960 which clarifies that two
reference types are covariant only if they're both lvalue references
or both rvalue references.

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

	DR 960
	PR c++/99664

gcc/cp/ChangeLog:

	* search.c (check_final_overrider): Compare TYPE_REF_IS_RVALUE
	when the return types are references.

gcc/testsuite/ChangeLog:

	* g++.dg/inherit/covariant23.C: New test.
---
 gcc/cp/search.c                            |  8 +++++++-
 gcc/testsuite/g++.dg/inherit/covariant23.C | 14 ++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/inherit/covariant23.C

Comments

Jason Merrill July 16, 2021, 5:15 p.m. UTC | #1
On 7/15/21 12:37 PM, Patrick Palka wrote:
> This implements the wording changes of DR 960 which clarifies that two
> reference types are covariant only if they're both lvalue references
> or both rvalue references.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> OK for trunk?

OK.

> 	DR 960
> 	PR c++/99664
> 
> gcc/cp/ChangeLog:
> 
> 	* search.c (check_final_overrider): Compare TYPE_REF_IS_RVALUE
> 	when the return types are references.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/inherit/covariant23.C: New test.
> ---
>   gcc/cp/search.c                            |  8 +++++++-
>   gcc/testsuite/g++.dg/inherit/covariant23.C | 14 ++++++++++++++
>   2 files changed, 21 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/inherit/covariant23.C
> 
> diff --git a/gcc/cp/search.c b/gcc/cp/search.c
> index af41bfe5835..943671acff8 100644
> --- a/gcc/cp/search.c
> +++ b/gcc/cp/search.c
> @@ -1948,7 +1948,13 @@ check_final_overrider (tree overrider, tree basefn)
>         fail = !INDIRECT_TYPE_P (base_return);
>         if (!fail)
>   	{
> -	  fail = cp_type_quals (base_return) != cp_type_quals (over_return);
> +	  if (cp_type_quals (base_return) != cp_type_quals (over_return))
> +	    fail = 1;
> +
> +	  if (TYPE_REF_P (base_return)
> +	      && (TYPE_REF_IS_RVALUE (base_return)
> +		  != TYPE_REF_IS_RVALUE (over_return)))
> +	    fail = 1;
>   
>   	  base_return = TREE_TYPE (base_return);
>   	  over_return = TREE_TYPE (over_return);
> diff --git a/gcc/testsuite/g++.dg/inherit/covariant23.C b/gcc/testsuite/g++.dg/inherit/covariant23.C
> new file mode 100644
> index 00000000000..b27be15ef45
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/inherit/covariant23.C
> @@ -0,0 +1,14 @@
> +// PR c++/99664
> +// { dg-do compile { target c++11 } }
> +
> +struct Res { };
> +
> +struct A {
> +  virtual Res &&f();
> +  virtual Res &g();
> +};
> +
> +struct B : A {
> +  Res &f() override; // { dg-error "return type" }
> +  Res &&g() override; // { dg-error "return type" }
> +};
>
diff mbox series

Patch

diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index af41bfe5835..943671acff8 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1948,7 +1948,13 @@  check_final_overrider (tree overrider, tree basefn)
       fail = !INDIRECT_TYPE_P (base_return);
       if (!fail)
 	{
-	  fail = cp_type_quals (base_return) != cp_type_quals (over_return);
+	  if (cp_type_quals (base_return) != cp_type_quals (over_return))
+	    fail = 1;
+
+	  if (TYPE_REF_P (base_return)
+	      && (TYPE_REF_IS_RVALUE (base_return)
+		  != TYPE_REF_IS_RVALUE (over_return)))
+	    fail = 1;
 
 	  base_return = TREE_TYPE (base_return);
 	  over_return = TREE_TYPE (over_return);
diff --git a/gcc/testsuite/g++.dg/inherit/covariant23.C b/gcc/testsuite/g++.dg/inherit/covariant23.C
new file mode 100644
index 00000000000..b27be15ef45
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/covariant23.C
@@ -0,0 +1,14 @@ 
+// PR c++/99664
+// { dg-do compile { target c++11 } }
+
+struct Res { };
+
+struct A {
+  virtual Res &&f();
+  virtual Res &g();
+};
+
+struct B : A {
+  Res &f() override; // { dg-error "return type" }
+  Res &&g() override; // { dg-error "return type" }
+};