xref: /aosp_15_r20/external/clang/test/CXX/conv/conv.mem/p4.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify %s
2*67e74705SXin Li 
3*67e74705SXin Li struct Base {
4*67e74705SXin Li   int data;
5*67e74705SXin Li   int method();
6*67e74705SXin Li };
7*67e74705SXin Li int (Base::*data_ptr) = &Base::data;
8*67e74705SXin Li int (Base::*method_ptr)() = &Base::method;
9*67e74705SXin Li 
10*67e74705SXin Li namespace test0 {
11*67e74705SXin Li   struct Derived : Base {};
test()12*67e74705SXin Li   void test() {
13*67e74705SXin Li     int (Derived::*d) = data_ptr;
14*67e74705SXin Li     int (Derived::*m)() = method_ptr;
15*67e74705SXin Li   }
16*67e74705SXin Li }
17*67e74705SXin Li 
18*67e74705SXin Li // Can't be inaccessible.
19*67e74705SXin Li namespace test1 {
20*67e74705SXin Li   struct Derived : private Base {}; // expected-note 2 {{declared private here}}
test()21*67e74705SXin Li   void test() {
22*67e74705SXin Li     int (Derived::*d) = data_ptr; // expected-error {{cannot cast private base class 'Base' to 'test1::Derived'}}
23*67e74705SXin Li     int (Derived::*m)() = method_ptr; // expected-error {{cannot cast private base class 'Base' to 'test1::Derived'}}
24*67e74705SXin Li   }
25*67e74705SXin Li };
26*67e74705SXin Li 
27*67e74705SXin Li // Can't be ambiguous.
28*67e74705SXin Li namespace test2 {
29*67e74705SXin Li   struct A : Base {};
30*67e74705SXin Li   struct B : Base {};
31*67e74705SXin Li   struct Derived : A, B {};
test()32*67e74705SXin Li   void test() {
33*67e74705SXin Li     int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test2::Derived':}}
34*67e74705SXin Li     int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test2::Derived':}}
35*67e74705SXin Li   }
36*67e74705SXin Li }
37*67e74705SXin Li 
38*67e74705SXin Li // Can't be virtual.
39*67e74705SXin Li namespace test3 {
40*67e74705SXin Li   struct Derived : virtual Base {};
test()41*67e74705SXin Li   void test() {
42*67e74705SXin Li     int (Derived::*d) = data_ptr;  // expected-error {{conversion from pointer to member of class 'Base' to pointer to member of class 'test3::Derived' via virtual base 'Base' is not allowed}}
43*67e74705SXin Li     int (Derived::*m)() = method_ptr; // expected-error {{conversion from pointer to member of class 'Base' to pointer to member of class 'test3::Derived' via virtual base 'Base' is not allowed}}
44*67e74705SXin Li   }
45*67e74705SXin Li }
46*67e74705SXin Li 
47*67e74705SXin Li // Can't be virtual even if there's a non-virtual path.
48*67e74705SXin Li namespace test4 {
49*67e74705SXin Li   struct A : Base {};
50*67e74705SXin Li   struct Derived : Base, virtual A {}; // expected-warning  {{direct base 'Base' is inaccessible due to ambiguity:\n    struct test4::Derived -> struct Base\n    struct test4::Derived -> struct test4::A -> struct Base}}
test()51*67e74705SXin Li   void test() {
52*67e74705SXin Li     int (Derived::*d) = data_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test4::Derived':}}
53*67e74705SXin Li     int (Derived::*m)() = method_ptr; // expected-error {{ambiguous conversion from pointer to member of base class 'Base' to pointer to member of derived class 'test4::Derived':}}
54*67e74705SXin Li   }
55*67e74705SXin Li }
56*67e74705SXin Li 
57*67e74705SXin Li // PR6254: don't get thrown off by a virtual base.
58*67e74705SXin Li namespace test5 {
59*67e74705SXin Li   struct A {};
60*67e74705SXin Li   struct Derived : Base, virtual A {};
test()61*67e74705SXin Li   void test() {
62*67e74705SXin Li     int (Derived::*d) = data_ptr;
63*67e74705SXin Li     int (Derived::*m)() = method_ptr;
64*67e74705SXin Li   }
65*67e74705SXin Li }
66