[clang] [clang] Add covariance tests that make sure we return an error when return value is different in pointer / lvalue ref / rvalue ref (PR #112853)
Boaz Brickner via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 21 06:53:21 PDT 2024
https://github.com/bricknerb updated https://github.com/llvm/llvm-project/pull/112853
>From b1ffbf6b7a59d1e57dccf8b9fab32c2c7d599058 Mon Sep 17 00:00:00 2001
From: Boaz Brickner <brickner at google.com>
Date: Mon, 21 Oct 2024 13:07:37 +0200
Subject: [PATCH 1/6] [clang] Add covariance tests that make sure we return an
error when return value is different in pointer / lvalue ref / rvalue ref
Per https://cplusplus.github.io/CWG/issues/960.html.
---
clang/test/SemaCXX/virtual-override.cpp | 28 +++++++++++++++++++++----
1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/clang/test/SemaCXX/virtual-override.cpp b/clang/test/SemaCXX/virtual-override.cpp
index ce6dd35e0b56fa..fc2a36937d4b5d 100644
--- a/clang/test/SemaCXX/virtual-override.cpp
+++ b/clang/test/SemaCXX/virtual-override.cpp
@@ -83,7 +83,7 @@ namespace T6 {
struct a { };
class A {
- // Classes.
+ // Check cv-qualification.
virtual const a* const_vs_unqualified_class();
virtual a* unqualified_vs_const_class(); // expected-note{{overridden virtual function is here}}
@@ -102,13 +102,23 @@ class A {
virtual const volatile a* const_volatile_vs_unualified_class();
virtual a* unqualified_vs_const_volatile_class(); // expected-note{{overridden virtual function is here}}
- // Non Classes.
+ // Check lvalue ref vs rvalue ref vs pointer.
+ virtual a& rvalue_ref();
+ virtual a&& lvalue_ref();
+ virtual a& rvalue_vs_lvalue_ref(); // expected-note{{overridden virtual function is here}}
+ virtual a&& lvalue_vs_rvalue_ref(); // expected-note{{overridden virtual function is here}}
+ virtual a& rvalue_ref_vs_pointer(); // expected-note{{overridden virtual function is here}}
+ virtual a* pointer_vs_rvalue_ref(); // expected-note{{overridden virtual function is here}}
+ virtual a&& lvalue_ref_vs_pointer(); // expected-note{{overridden virtual function is here}}
+ virtual a* pointer_vs_lvalue_ref(); // expected-note{{overridden virtual function is here}}
+
+ // Check non class.
virtual const int* const_vs_unqualified_non_class(); // expected-note{{overridden virtual function is here}}
virtual int* unqualified_vs_const_non_class(); // expected-note{{overridden virtual function is here}}
};
class B : A {
- // Classes.
+ // Check cv-qualification.
a* const_vs_unqualified_class() override;
const a* unqualified_vs_const_class() override; // expected-error{{return type of virtual function 'unqualified_vs_const_class' is not covariant with the return type of the function it overrides (class type 'const a *' does not have the same cv-qualification as or less cv-qualification than class type 'a *')}}
@@ -127,7 +137,17 @@ class B : A {
a* const_volatile_vs_unualified_class() override;
const volatile a* unqualified_vs_const_volatile_class() override; // expected-error{{return type of virtual function 'unqualified_vs_const_volatile_class' is not covariant with the return type of the function it overrides (class type 'const volatile a *' does not have the same cv-qualification as or less cv-qualification than class type 'a *')}}
- // Non Classes.
+ // Check lvalue ref vs rvalue ref vs pointer.
+ a& rvalue_ref() override;
+ a&& lvalue_ref() override;
+ a&& rvalue_vs_lvalue_ref() override; // expected-error{{virtual function 'rvalue_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a &')}}
+ a& lvalue_vs_rvalue_ref() override; // expected-error{{virtual function 'lvalue_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a &&')}}
+ a* rvalue_ref_vs_pointer() override; // expected-error{{virtual function 'rvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &')}}
+ a& pointer_vs_rvalue_ref() override; // expected-error{{virtual function 'pointer_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a *')}}
+ a* lvalue_ref_vs_pointer() override; // expected-error{{virtual function 'lvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &&')}}
+ a&& pointer_vs_lvalue_ref() override; // expected-error{{virtual function 'pointer_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a *')}}
+
+ // Check non class.
int* const_vs_unqualified_non_class() override; // expected-error{{virtual function 'const_vs_unqualified_non_class' has a different return type ('int *') than the function it overrides (which has return type 'const int *')}}
const int* unqualified_vs_const_non_class() override; // expected-error{{virtual function 'unqualified_vs_const_non_class' has a different return type ('const int *') than the function it overrides (which has return type 'int *')}}
};
>From b4221ce300697bf429278222a3f61f9498b5f5ae Mon Sep 17 00:00:00 2001
From: Boaz Brickner <brickner at google.com>
Date: Mon, 21 Oct 2024 14:21:14 +0200
Subject: [PATCH 2/6] [clang] Move the tests for
https://cplusplus.github.io/CWG/issues/960.html to
clang/test/CXX/drs/cwg9xx.cpp.
---
clang/test/CXX/drs/cwg9xx.cpp | 32 +++++++++++++++++++++++++
clang/test/SemaCXX/virtual-override.cpp | 20 ----------------
2 files changed, 32 insertions(+), 20 deletions(-)
diff --git a/clang/test/CXX/drs/cwg9xx.cpp b/clang/test/CXX/drs/cwg9xx.cpp
index 2700b0f5662a2c..7e8fb48f110317 100644
--- a/clang/test/CXX/drs/cwg9xx.cpp
+++ b/clang/test/CXX/drs/cwg9xx.cpp
@@ -93,6 +93,38 @@ struct B : A {
} // namespace example2
} // namespace cwg952
+namespace cwg960 { // cwg960: 2.8
+struct a {};
+class A {
+#if __cplusplus >= 201103L
+ // Check lvalue ref vs rvalue ref vs pointer.
+ virtual a& rvalue_ref();
+ virtual a&& lvalue_ref();
+ virtual a& rvalue_vs_lvalue_ref(); // expected-note{{overridden virtual function is here}}
+ virtual a&& lvalue_vs_rvalue_ref(); // expected-note{{overridden virtual function is here}}
+ virtual a& rvalue_ref_vs_pointer(); // expected-note{{overridden virtual function is here}}
+ virtual a* pointer_vs_rvalue_ref(); // expected-note{{overridden virtual function is here}}
+ virtual a&& lvalue_ref_vs_pointer(); // expected-note{{overridden virtual function is here}}
+ virtual a* pointer_vs_lvalue_ref(); // expected-note{{overridden virtual function is here}}
+#endif
+};
+
+class B : A {
+#if __cplusplus >= 201103L
+ // Check lvalue ref vs rvalue ref vs pointer.
+ a& rvalue_ref() override;
+ a&& lvalue_ref() override;
+ a&& rvalue_vs_lvalue_ref() override; // expected-error{{virtual function 'rvalue_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a &')}}
+ a& lvalue_vs_rvalue_ref() override; // expected-error{{virtual function 'lvalue_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a &&')}}
+ a* rvalue_ref_vs_pointer() override; // expected-error{{virtual function 'rvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &')}}
+ a& pointer_vs_rvalue_ref() override; // expected-error{{virtual function 'pointer_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a *')}}
+ a* lvalue_ref_vs_pointer() override; // expected-error{{virtual function 'lvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &&')}}
+ a&& pointer_vs_lvalue_ref() override; // expected-error{{virtual function 'pointer_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a *')}}
+#endif
+};
+
+} // namespace cwg960
+
namespace cwg974 { // cwg974: yes
#if __cplusplus >= 201103L
void test() {
diff --git a/clang/test/SemaCXX/virtual-override.cpp b/clang/test/SemaCXX/virtual-override.cpp
index fc2a36937d4b5d..c8cd4c6a29e2d5 100644
--- a/clang/test/SemaCXX/virtual-override.cpp
+++ b/clang/test/SemaCXX/virtual-override.cpp
@@ -102,16 +102,6 @@ class A {
virtual const volatile a* const_volatile_vs_unualified_class();
virtual a* unqualified_vs_const_volatile_class(); // expected-note{{overridden virtual function is here}}
- // Check lvalue ref vs rvalue ref vs pointer.
- virtual a& rvalue_ref();
- virtual a&& lvalue_ref();
- virtual a& rvalue_vs_lvalue_ref(); // expected-note{{overridden virtual function is here}}
- virtual a&& lvalue_vs_rvalue_ref(); // expected-note{{overridden virtual function is here}}
- virtual a& rvalue_ref_vs_pointer(); // expected-note{{overridden virtual function is here}}
- virtual a* pointer_vs_rvalue_ref(); // expected-note{{overridden virtual function is here}}
- virtual a&& lvalue_ref_vs_pointer(); // expected-note{{overridden virtual function is here}}
- virtual a* pointer_vs_lvalue_ref(); // expected-note{{overridden virtual function is here}}
-
// Check non class.
virtual const int* const_vs_unqualified_non_class(); // expected-note{{overridden virtual function is here}}
virtual int* unqualified_vs_const_non_class(); // expected-note{{overridden virtual function is here}}
@@ -137,16 +127,6 @@ class B : A {
a* const_volatile_vs_unualified_class() override;
const volatile a* unqualified_vs_const_volatile_class() override; // expected-error{{return type of virtual function 'unqualified_vs_const_volatile_class' is not covariant with the return type of the function it overrides (class type 'const volatile a *' does not have the same cv-qualification as or less cv-qualification than class type 'a *')}}
- // Check lvalue ref vs rvalue ref vs pointer.
- a& rvalue_ref() override;
- a&& lvalue_ref() override;
- a&& rvalue_vs_lvalue_ref() override; // expected-error{{virtual function 'rvalue_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a &')}}
- a& lvalue_vs_rvalue_ref() override; // expected-error{{virtual function 'lvalue_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a &&')}}
- a* rvalue_ref_vs_pointer() override; // expected-error{{virtual function 'rvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &')}}
- a& pointer_vs_rvalue_ref() override; // expected-error{{virtual function 'pointer_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a *')}}
- a* lvalue_ref_vs_pointer() override; // expected-error{{virtual function 'lvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &&')}}
- a&& pointer_vs_lvalue_ref() override; // expected-error{{virtual function 'pointer_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a *')}}
-
// Check non class.
int* const_vs_unqualified_non_class() override; // expected-error{{virtual function 'const_vs_unqualified_non_class' has a different return type ('int *') than the function it overrides (which has return type 'const int *')}}
const int* unqualified_vs_const_non_class() override; // expected-error{{virtual function 'unqualified_vs_const_non_class' has a different return type ('const int *') than the function it overrides (which has return type 'int *')}}
>From c07e53d0e9b1a4451d5dd56b8a67b3da52832712 Mon Sep 17 00:00:00 2001
From: Boaz Brickner <brickner at google.com>
Date: Mon, 21 Oct 2024 15:37:08 +0200
Subject: [PATCH 3/6] [clang] Update clang/www/cxx_dr_status.html for CWG 960.
---
clang/www/cxx_dr_status.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 6f3cc8247d2e2d..cbecd6bd1ed685 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -5579,7 +5579,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/960.html">960</a></td>
<td>CD2</td>
<td>Covariant functions and lvalue/rvalue references</td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="full" align="center">Clang 2.8</td>
</tr>
<tr id="961">
<td><a href="https://cplusplus.github.io/CWG/issues/961.html">961</a></td>
>From d76fc7a8da92558cb9d20eb272dbd012b0f9c514 Mon Sep 17 00:00:00 2001
From: Boaz Brickner <brickner at google.com>
Date: Mon, 21 Oct 2024 15:48:20 +0200
Subject: [PATCH 4/6] [clang] Change style of cwg960 test expectations to be
more consistent with other tests.
---
clang/test/CXX/drs/cwg9xx.cpp | 42 +++++++++++++++++++++++++----------
1 file changed, 30 insertions(+), 12 deletions(-)
diff --git a/clang/test/CXX/drs/cwg9xx.cpp b/clang/test/CXX/drs/cwg9xx.cpp
index 7e8fb48f110317..28b3388fe5e441 100644
--- a/clang/test/CXX/drs/cwg9xx.cpp
+++ b/clang/test/CXX/drs/cwg9xx.cpp
@@ -100,12 +100,12 @@ class A {
// Check lvalue ref vs rvalue ref vs pointer.
virtual a& rvalue_ref();
virtual a&& lvalue_ref();
- virtual a& rvalue_vs_lvalue_ref(); // expected-note{{overridden virtual function is here}}
- virtual a&& lvalue_vs_rvalue_ref(); // expected-note{{overridden virtual function is here}}
- virtual a& rvalue_ref_vs_pointer(); // expected-note{{overridden virtual function is here}}
- virtual a* pointer_vs_rvalue_ref(); // expected-note{{overridden virtual function is here}}
- virtual a&& lvalue_ref_vs_pointer(); // expected-note{{overridden virtual function is here}}
- virtual a* pointer_vs_lvalue_ref(); // expected-note{{overridden virtual function is here}}
+ virtual a& rvalue_vs_lvalue_ref(); // #cwg960-A-rvalue_vs_lvalue_ref
+ virtual a&& lvalue_vs_rvalue_ref(); // #cwg960-A-lvalue_vs_rvalue_ref
+ virtual a& rvalue_ref_vs_pointer(); // #cwg960-A-rvalue_ref_vs_pointer
+ virtual a* pointer_vs_rvalue_ref(); // #cwg960-A-pointer_vs_rvalue_ref
+ virtual a&& lvalue_ref_vs_pointer(); // #cwg960-A-lvalue_ref_vs_pointer
+ virtual a* pointer_vs_lvalue_ref(); // #cwg960-A-pointer_vs_lvalue_ref
#endif
};
@@ -114,12 +114,30 @@ class B : A {
// Check lvalue ref vs rvalue ref vs pointer.
a& rvalue_ref() override;
a&& lvalue_ref() override;
- a&& rvalue_vs_lvalue_ref() override; // expected-error{{virtual function 'rvalue_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a &')}}
- a& lvalue_vs_rvalue_ref() override; // expected-error{{virtual function 'lvalue_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a &&')}}
- a* rvalue_ref_vs_pointer() override; // expected-error{{virtual function 'rvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &')}}
- a& pointer_vs_rvalue_ref() override; // expected-error{{virtual function 'pointer_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a *')}}
- a* lvalue_ref_vs_pointer() override; // expected-error{{virtual function 'lvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &&')}}
- a&& pointer_vs_lvalue_ref() override; // expected-error{{virtual function 'pointer_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a *')}}
+
+ a&& rvalue_vs_lvalue_ref() override;
+ // since-cxx11-error at -1 {{virtual function 'rvalue_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a &')}}
+ // since-cxx11-note@#cwg960-A-rvalue_vs_lvalue_ref {{overridden virtual function is here}}
+
+ a& lvalue_vs_rvalue_ref() override;
+ // since-cxx11-error at -1 {{virtual function 'lvalue_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a &&')}}
+ // since-cxx11-note@#cwg960-A-lvalue_vs_rvalue_ref {{overridden virtual function is here}}
+
+ a* rvalue_ref_vs_pointer() override;
+ // since-cxx11-error at -1 {{virtual function 'rvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &')}}
+ // since-cxx11-note@#cwg960-A-rvalue_ref_vs_pointer {{overridden virtual function is here}}
+
+ a& pointer_vs_rvalue_ref() override;
+ // since-cxx11-error at -1 {{virtual function 'pointer_vs_rvalue_ref' has a different return type ('a &') than the function it overrides (which has return type 'a *')}}
+ // since-cxx11-note@#cwg960-A-pointer_vs_rvalue_ref {{overridden virtual function is here}}
+
+ a* lvalue_ref_vs_pointer() override;
+ // since-cxx11-error at -1 {{virtual function 'lvalue_ref_vs_pointer' has a different return type ('a *') than the function it overrides (which has return type 'a &&')}}
+ // since-cxx11-note@#cwg960-A-lvalue_ref_vs_pointer {{overridden virtual function is here}}
+
+ a&& pointer_vs_lvalue_ref() override;
+ // since-cxx11-error at -1 {{virtual function 'pointer_vs_lvalue_ref' has a different return type ('a &&') than the function it overrides (which has return type 'a *')}}
+ // since-cxx11-note@#cwg960-A-pointer_vs_lvalue_ref {{overridden virtual function is here}}
#endif
};
>From 181a9724601636df88b2568f9558fe819d736b03 Mon Sep 17 00:00:00 2001
From: Boaz Brickner <brickner at google.com>
Date: Mon, 21 Oct 2024 15:50:08 +0200
Subject: [PATCH 5/6] [clang] Update cwg960 test to clang 3.0.
https://godbolt.org/z/o77989zM7
---
clang/test/CXX/drs/cwg9xx.cpp | 2 +-
clang/www/cxx_dr_status.html | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/CXX/drs/cwg9xx.cpp b/clang/test/CXX/drs/cwg9xx.cpp
index 28b3388fe5e441..d4f54bcdad6ea0 100644
--- a/clang/test/CXX/drs/cwg9xx.cpp
+++ b/clang/test/CXX/drs/cwg9xx.cpp
@@ -93,7 +93,7 @@ struct B : A {
} // namespace example2
} // namespace cwg952
-namespace cwg960 { // cwg960: 2.8
+namespace cwg960 { // cwg960: 3.0
struct a {};
class A {
#if __cplusplus >= 201103L
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index cbecd6bd1ed685..714fb5c14aff68 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -5579,7 +5579,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/960.html">960</a></td>
<td>CD2</td>
<td>Covariant functions and lvalue/rvalue references</td>
- <td class="full" align="center">Clang 2.8</td>
+ <td class="full" align="center">Clang 3.0</td>
</tr>
<tr id="961">
<td><a href="https://cplusplus.github.io/CWG/issues/961.html">961</a></td>
>From 7c798f9ab87d136877e07b7723793e86022604b9 Mon Sep 17 00:00:00 2001
From: Boaz Brickner <brickner at google.com>
Date: Mon, 21 Oct 2024 15:53:03 +0200
Subject: [PATCH 6/6] [clang] Revert unrelated changes in
clang/test/SemaCXX/virtual-override.cpp.
---
clang/test/SemaCXX/virtual-override.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang/test/SemaCXX/virtual-override.cpp b/clang/test/SemaCXX/virtual-override.cpp
index c8cd4c6a29e2d5..ce6dd35e0b56fa 100644
--- a/clang/test/SemaCXX/virtual-override.cpp
+++ b/clang/test/SemaCXX/virtual-override.cpp
@@ -83,7 +83,7 @@ namespace T6 {
struct a { };
class A {
- // Check cv-qualification.
+ // Classes.
virtual const a* const_vs_unqualified_class();
virtual a* unqualified_vs_const_class(); // expected-note{{overridden virtual function is here}}
@@ -102,13 +102,13 @@ class A {
virtual const volatile a* const_volatile_vs_unualified_class();
virtual a* unqualified_vs_const_volatile_class(); // expected-note{{overridden virtual function is here}}
- // Check non class.
+ // Non Classes.
virtual const int* const_vs_unqualified_non_class(); // expected-note{{overridden virtual function is here}}
virtual int* unqualified_vs_const_non_class(); // expected-note{{overridden virtual function is here}}
};
class B : A {
- // Check cv-qualification.
+ // Classes.
a* const_vs_unqualified_class() override;
const a* unqualified_vs_const_class() override; // expected-error{{return type of virtual function 'unqualified_vs_const_class' is not covariant with the return type of the function it overrides (class type 'const a *' does not have the same cv-qualification as or less cv-qualification than class type 'a *')}}
@@ -127,7 +127,7 @@ class B : A {
a* const_volatile_vs_unualified_class() override;
const volatile a* unqualified_vs_const_volatile_class() override; // expected-error{{return type of virtual function 'unqualified_vs_const_volatile_class' is not covariant with the return type of the function it overrides (class type 'const volatile a *' does not have the same cv-qualification as or less cv-qualification than class type 'a *')}}
- // Check non class.
+ // Non Classes.
int* const_vs_unqualified_non_class() override; // expected-error{{virtual function 'const_vs_unqualified_non_class' has a different return type ('int *') than the function it overrides (which has return type 'const int *')}}
const int* unqualified_vs_const_non_class() override; // expected-error{{virtual function 'unqualified_vs_const_non_class' has a different return type ('const int *') than the function it overrides (which has return type 'int *')}}
};
More information about the cfe-commits
mailing list