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