1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2 
3 struct Base {
4   int data;
5   int method();
6 };
7 int (Base::*data_ptr) = &Base::data;
8 int (Base::*method_ptr)() = &Base::method;
9 
10 namespace test0 {
11   struct Derived : Base {};
12   void test() {
13     int (Derived::*d) = data_ptr;
14     int (Derived::*m)() = method_ptr;
15   }
16 }
17 
18 // Can't be inaccessible.
19 namespace test1 {
20   struct Derived : private Base {}; // expected-note 2 {{declared private here}}
21   void test() {
22     int (Derived::*d) = data_ptr; // expected-error {{cannot cast private base class 'Base' to 'test1::Derived'}}
23     int (Derived::*m)() = method_ptr; // expected-error {{cannot cast private base class 'Base' to 'test1::Derived'}}
24   }
25 };
26 
27 // Can't be ambiguous.
28 namespace test2 {
29   struct A : Base {};
30   struct B : Base {};
31   struct Derived : A, B {};
32   void test() {
33     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     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   }
36 }
37 
38 // Can't be virtual.
39 namespace test3 {
40   struct Derived : virtual Base {};
41   void test() {
42     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     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   }
45 }
46 
47 // Can't be virtual even if there's a non-virtual path.
48 namespace test4 {
49   struct A : Base {};
50   struct Derived : Base, virtual A {};
51   void test() {
52     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     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   }
55 }
56 
57 // PR6254: don't get thrown off by a virtual base.
58 namespace test5 {
59   struct A {};
60   struct Derived : Base, virtual A {};
61   void test() {
62     int (Derived::*d) = data_ptr;
63     int (Derived::*m)() = method_ptr;
64   }
65 }
66