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