[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 05:21:52 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/2] [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/2] [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 *')}}



More information about the cfe-commits mailing list