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.vladis...@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@-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@-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@-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@-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@-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@-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.vladis...@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@-1 {{<source>:46:29: error: no matching constructor for initialization of 'Templ<Derived>'}} +// expected-error@-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@-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@-1 {{cannot cast private base class 'cwg203::ex6::Base' to 'cwg203::ex6::Derived'}} + // expected-error@-1 {{cannot cast private base class 'cwg203::ex6::Base' to 'Derived'}} // expected-note@#cwg203-ex6-Derived {{declared private here}} } } // namespace ex6 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits