member-pointer.cpp revision 3f5b61c394f4f205bcb4d316eb2a7a0a68b8af86
1// RUN: clang-cc -fsyntax-only -verify %s 2 3struct A {}; 4enum B { Dummy }; 5namespace C {} 6struct D : A {}; 7struct E : A {}; 8struct F : D, E {}; 9struct G : virtual D {}; 10 11int A::*pdi1; 12int (::A::*pdi2); 13int (A::*pfi)(int); 14 15int B::*pbi; // expected-error {{expected a class or namespace}} 16int C::*pci; // expected-error {{'pci' does not point into a class}} 17void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}} 18int& A::*pdr; // expected-error {{'pdr' declared as a pointer to a reference}} 19 20void f() { 21 // This requires tentative parsing. 22 int (A::*pf)(int, int); 23 24 // Implicit conversion to bool. 25 bool b = pdi1; 26 b = pfi; 27 28 // Conversion from null pointer constant. 29 pf = 0; 30 pf = __null; 31 32 // Conversion to member of derived. 33 int D::*pdid = pdi1; 34 pdid = pdi2; 35 36 // Fail conversion due to ambiguity and virtuality. 37 int F::*pdif = pdi1; // expected-error {{ambiguous conversion from pointer to member of base class 'struct A' to pointer to member of derived class 'struct F'}} expected-error {{incompatible type}} 38 int G::*pdig = pdi1; // expected-error {{conversion from pointer to member of class 'struct A' to pointer to member of class 'struct G' via virtual base 'struct D' is not allowed}} expected-error {{incompatible type}} 39 40 // Conversion to member of base. 41 pdi1 = pdid; // expected-error {{incompatible type assigning 'int struct D::*', expected 'int struct A::*'}} 42} 43 44struct TheBase 45{ 46 void d(); 47}; 48 49struct HasMembers : TheBase 50{ 51 int i; 52 void f(); 53 54 void g(); 55 void g(int); 56 static void g(double); 57}; 58 59namespace Fake 60{ 61 int i; 62 void f(); 63} 64 65void g() { 66 HasMembers hm; 67 68 int HasMembers::*pmi = &HasMembers::i; 69 int *pni = &Fake::i; 70 int *pmii = &hm.i; 71 72 void (HasMembers::*pmf)() = &HasMembers::f; 73 void (*pnf)() = &Fake::f; 74 &hm.f; // FIXME: needs diagnostic expected-warning{{result unused}} 75 76 void (HasMembers::*pmgv)() = &HasMembers::g; 77 void (HasMembers::*pmgi)(int) = &HasMembers::g; 78 void (*pmgd)(double) = &HasMembers::g; 79 80 void (HasMembers::*pmd)() = &HasMembers::d; 81} 82 83struct Incomplete; 84 85void h() { 86 HasMembers hm, *phm = &hm; 87 88 int HasMembers::*pi = &HasMembers::i; 89 hm.*pi = 0; 90 int i = phm->*pi; 91 (void)&(hm.*pi); 92 (void)&(phm->*pi); 93 (void)&((&hm)->*pi); // expected-error {{address expression must be an lvalue or a function designator}} 94 95 void (HasMembers::*pf)() = &HasMembers::f; 96 (hm.*pf)(); 97 (phm->*pf)(); 98 99 (void)(hm->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct HasMembers'}} 100 (void)(phm.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'struct HasMembers *'}} 101 (void)(i.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'int'}} 102 int *ptr; 103 (void)(ptr->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'int *'}} 104 105 int A::*pai = 0; 106 D d, *pd = &d; 107 (void)(d.*pai); 108 (void)(pd->*pai); 109 F f, *ptrf = &f; 110 (void)(f.*pai); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'struct F'}} 111 (void)(ptrf->*pai); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct F *'}} 112 113 (void)(hm.*i); // expected-error {{pointer-to-member}} 114 (void)(phm->*i); // expected-error {{pointer-to-member}} 115 116 Incomplete *inc; 117 int Incomplete::*pii = 0; 118 (void)(inc->*pii); // okay 119} 120 121struct OverloadsPtrMem 122{ 123 int operator ->*(const char *); 124}; 125 126void i() { 127 OverloadsPtrMem m; 128 int foo = m->*"Awesome!"; 129} 130