[clang] [clang] Add test for CWG203 "Type of address-of-member expression" (PR #121687)
Vlad Serebrennikov via cfe-commits
cfe-commits at lists.llvm.org
Sun Jan 5 03:23:45 PST 2025
https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/121687
>From bca2bfe17b71faeebf65eba11adcb70927f878fd Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sun, 5 Jan 2025 13:58:16 +0300
Subject: [PATCH 1/2] [clang] Add test for CWG203 "Type of address-of-member
expression"
---
clang/test/CXX/drs/cwg2xx.cpp | 138 +++++++++++++++++++++++++++++++++-
clang/www/cxx_dr_status.html | 2 +-
2 files changed, 137 insertions(+), 3 deletions(-)
diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index ec37b420880e28..6a1dfcf2774779 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -2,8 +2,9 @@
// RUN: %clang_cc1 -std=c++11 %s -verify=expected,since-cxx11,cxx98-11,cxx98-14,cxx98-17 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx11,since-cxx14,cxx98-14,cxx98-17 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,cxx98-17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors
// FIXME: diagnostic above is emitted only on Windows platforms
// PR13819 -- __SIZE_TYPE__ is incompatible.
@@ -41,6 +42,139 @@ namespace cwg202 { // cwg202: 3.1
template struct X<f>;
}
+namespace cwg203 { // cwg203: 2.8
+namespace ex1 {
+struct B {
+ int i;
+};
+struct D1 : B {};
+struct D2 : B {};
+
+int(D1::*pmD1) = &D2::i;
+} // namespace ex1
+
+#if __cplusplus >= 202002L
+namespace ex2 {
+struct A {
+ int i;
+ virtual void f() = 0; // #cwg203-ex2-A-f
+};
+
+struct B : A {
+ int j;
+ constexpr B() : j(5) {}
+ virtual void f();
+};
+
+struct C : B {
+ constexpr C() { j = 10; }
+};
+
+template <class T>
+constexpr int DefaultValue(int(T::*m)) {
+ return T().*m;
+ // since-cxx20-error at -1 {{allocating an object of abstract class type 'cwg203::ex2::A'}}
+ // since-cxx20-note@#cwg203-ex2-a {{in instantiation of function template specialization 'cwg203::ex2::DefaultValue<cwg203::ex2::A>' requested here}}
+ // since-cxx20-note@#cwg203-ex2-A-f {{unimplemented pure virtual method 'f' in 'A'}}
+} // #cwg203-ex2-DefaultValue
+
+int a = DefaultValue(&B::i); // #cwg203-ex2-a
+static_assert(DefaultValue(&C::j) == 5, "");
+} // namespace ex2
+#endif
+
+namespace ex3 {
+class Base {
+public:
+ int func() const;
+};
+
+class Derived : public Base {};
+
+template <class T> class Templ { // #cwg203-ex3-Templ
+public:
+ template <class S> Templ(S (T::*ptmf)() const); // #cwg203-ex3-Templ-ctor
+};
+
+void foo() { Templ<Derived> x(&Derived::func); }
+// expected-error at -1 {{<source>:46:29: error: no matching constructor for initialization of 'Templ<Derived>'}}
+// expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int (cwg203::ex3::Base::*)() const' to 'const Templ<Derived>' for 1st argument}}
+// expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (cwg203::ex3::Base::*)() const' to 'Templ<Derived>' for 1st argument}}
+// expected-note@#cwg203-ex3-Templ-ctor {{candidate template ignored: could not match 'cwg203::ex3::Derived' against 'cwg203::ex3::Base'}}
+} // namespace ex3
+
+namespace ex4 {
+struct Very_base {
+ int a;
+};
+struct Base1 : Very_base {};
+struct Base2 : Very_base {};
+struct Derived : Base1, Base2 {
+};
+
+int f() {
+ Derived d;
+ int Derived::*a_ptr = &Derived::Base1::a;
+ /* expected-error at -1
+ {{ambiguous conversion from pointer to member of base class 'cwg203::ex4::Very_base' to pointer to member of derived class 'cwg203::ex4::Derived':
+ struct cwg203::ex4::Derived -> Base1 -> Very_base
+ struct cwg203::ex4::Derived -> Base2 -> Very_base}}*/
+};
+} // namespace ex4
+
+namespace ex5 {
+struct Base {
+ int a;
+};
+struct Derived : Base {
+ int b;
+};
+
+template <typename Class, typename Member_type, Member_type Base::*ptr>
+Member_type get(Class &c) {
+ return c.*ptr;
+}
+
+void call(int (*f)(Derived &)); // #cwg203-ex5-call
+
+int main() {
+ // ill-formed, contrary to Core issue filing:
+ // `&Derived::b` yields `int Derived::*`, which can't initialize NTTP of type `int Base::*`,
+ // because (implicit) pointer-to-member conversion doesn't upcast.
+ call(&get<Derived, int, &Derived::b>);
+ // expected-error at -1 {{no matching function for call to 'call'}}
+ // expected-note@#cwg203-ex5-call {{candidate function not viable: no overload of 'get' matching 'int (*)(Derived &)' for 1st argument}}
+
+ // well-formed, contrary to Core issue filing:
+ // `&Derived::a` yields `int Base::*`,
+ // which can initialize NTTP of type `int Base::*`.
+ call(&get<Derived, int, &Derived::a>);
+
+ call(&get<Base, int, &Derived::a>);
+ // expected-error at -1 {{no matching function for call to 'call'}}
+ // expected-note@#cwg203-ex5-call {{candidate function not viable: no overload of 'get' matching 'int (*)(Derived &)' for 1st argument}}
+}
+} // namespace ex5
+
+namespace ex6 {
+struct Base {
+ int a;
+};
+struct Derived : private Base { // #cwg203-ex6-Derived
+public:
+ using Base::a; // make `a` accessible
+};
+
+int main() {
+ Derived d;
+ int b = d.a;
+ int Derived::*ptr = &Derived::a;
+ // expected-error at -1 {{cannot cast private base class 'cwg203::ex6::Base' to 'cwg203::ex6::Derived'}}
+ // expected-note@#cwg203-ex6-Derived {{declared private here}}
+}
+} // namespace ex6
+} // namespace cwg203
+
// cwg204: sup 820
namespace cwg206 { // cwg206: yes
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index c069e155fd547c..a383803df670c1 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -1263,7 +1263,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/203.html">203</a></td>
<td>NAD</td>
<td>Type of address-of-member expression</td>
- <td class="unknown" align="center">Unknown</td>
+ <td class="full" align="center">Clang 2.8</td>
</tr>
<tr id="204">
<td><a href="https://cplusplus.github.io/CWG/issues/204.html">204</a></td>
>From fcda3b23eb3976d44fab4a492ab83710cbf3a0da Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sun, 5 Jan 2025 14:23:31 +0300
Subject: [PATCH 2/2] Fix expected directives
---
clang/test/CXX/drs/cwg2xx.cpp | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/clang/test/CXX/drs/cwg2xx.cpp b/clang/test/CXX/drs/cwg2xx.cpp
index 6a1dfcf2774779..73b1be77316ca3 100644
--- a/clang/test/CXX/drs/cwg2xx.cpp
+++ b/clang/test/CXX/drs/cwg2xx.cpp
@@ -97,9 +97,9 @@ template <class T> class Templ { // #cwg203-ex3-Templ
};
void foo() { Templ<Derived> x(&Derived::func); }
-// expected-error at -1 {{<source>:46:29: error: no matching constructor for initialization of 'Templ<Derived>'}}
+// expected-error at -1 {{no matching constructor for initialization of 'Templ<Derived>'}}
// expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int (cwg203::ex3::Base::*)() const' to 'const Templ<Derived>' for 1st argument}}
-// expected-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (cwg203::ex3::Base::*)() const' to 'Templ<Derived>' for 1st argument}}
+// since-cxx11-note@#cwg203-ex3-Templ {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int (cwg203::ex3::Base::*)() const' to 'Templ<Derived>' for 1st argument}}
// expected-note@#cwg203-ex3-Templ-ctor {{candidate template ignored: could not match 'cwg203::ex3::Derived' against 'cwg203::ex3::Base'}}
} // namespace ex3
@@ -114,12 +114,13 @@ struct Derived : Base1, Base2 {
int f() {
Derived d;
+ // FIXME: in the diagnostic below, Very_base is fully qualified, but Derived is not
int Derived::*a_ptr = &Derived::Base1::a;
/* expected-error at -1
- {{ambiguous conversion from pointer to member of base class 'cwg203::ex4::Very_base' to pointer to member of derived class 'cwg203::ex4::Derived':
+ {{ambiguous conversion from pointer to member of base class 'cwg203::ex4::Very_base' to pointer to member of derived class 'Derived':
struct cwg203::ex4::Derived -> Base1 -> Very_base
struct cwg203::ex4::Derived -> Base2 -> Very_base}}*/
-};
+}
} // namespace ex4
namespace ex5 {
@@ -168,8 +169,9 @@ struct Derived : private Base { // #cwg203-ex6-Derived
int main() {
Derived d;
int b = d.a;
+ // FIXME: in the diagnostic below, Base is fully qualified, but Derived is not
int Derived::*ptr = &Derived::a;
- // expected-error at -1 {{cannot cast private base class 'cwg203::ex6::Base' to 'cwg203::ex6::Derived'}}
+ // expected-error at -1 {{cannot cast private base class 'cwg203::ex6::Base' to 'Derived'}}
// expected-note@#cwg203-ex6-Derived {{declared private here}}
}
} // namespace ex6
More information about the cfe-commits
mailing list