xref: /llvm-project/clang/test/SemaCXX/member-pointer.cpp (revision 83ea47acd7116bf50274534ba9b3bd3035c01da6)
1 // RUN: %clang_cc1 -fsyntax-only -verify %std_cxx98- %s
2 
3 struct A {};
4 enum B { Dummy };
5 namespace C {}
6 struct D : A {};
7 struct E : A {};
8 struct F : D, E {};
9 struct G : virtual D {};
10 class H : A {}; // expected-note 2{{implicitly declared private here}}
11 
12 int A::*pdi1;
13 int (::A::*pdi2);
14 int (A::*pfi)(int);
15 void (*A::*ppfie)() throw();
16 #if __cplusplus < 201703L
17 // expected-error@-2 {{exception specifications are not allowed beyond a single level of indirection}}
18 #endif
19 
20 int B::*pbi;
21 #if __cplusplus <= 199711L // C++03 or earlier modes
22 // expected-warning@-2 {{use of enumeration in a nested name specifier is a C++11 extension}}
23 #endif
24 // expected-error@-4 {{'pbi' does not point into a class}}
25 int C::*pci; // expected-error {{'pci' does not point into a class}}
26 void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}}
27 int& A::*pdr; // expected-error {{'pdr' declared as a member pointer to a reference}}
28 
f()29 void f() {
30   // This requires tentative parsing.
31   int (A::*pf)(int, int);
32 
33   // Implicit conversion to bool.
34   bool b = pdi1;
35   b = pfi;
36 
37   // Conversion from null pointer constant.
38   pf = 0;
39   pf = __null;
40 
41   // Conversion to member of derived.
42   int D::*pdid = pdi1;
43   pdid = pdi2;
44 
45   // Fail conversion due to ambiguity and virtuality.
46   int F::*pdif = pdi1; // expected-error {{ambiguous conversion from pointer to member of base class 'A' to pointer to member of derived class 'F':}}
47   int G::*pdig = pdi1; // expected-error {{conversion from pointer to member of class 'A' to pointer to member of class 'G' via virtual base 'D' is not allowed}}
48 
49   // Conversion to member of base.
50   pdi1 = pdid; // expected-error {{assigning to 'int A::*' from incompatible type 'int D::*'}}
51 
52   // Comparisons
53   int (A::*pf2)(int, int);
54   int (D::*pf3)(int, int) = 0;
55   bool b1 = (pf == pf2); (void)b1;
56   bool b2 = (pf != pf2); (void)b2;
57   bool b3 = (pf == pf3); (void)b3;
58   bool b4 = (pf != 0); (void)b4;
59 }
60 
61 struct TheBase
62 {
63   void d();
64 };
65 
66 struct HasMembers : TheBase
67 {
68   int i;
69   void f();
70 
71   void g();
72   void g(int);
73   static void g(double);
74 };
75 
76 namespace Fake
77 {
78   int i;
79   void f();
80 }
81 
g()82 void g() {
83   HasMembers hm;
84 
85   int HasMembers::*pmi = &HasMembers::i;
86   int *pni = &Fake::i;
87   int *pmii = &hm.i;
88 
89   void (HasMembers::*pmf)() = &HasMembers::f;
90   void (*pnf)() = &Fake::f;
91   &hm.f; // expected-error {{cannot create a non-constant pointer to member function}}
92 
93   void (HasMembers::*pmgv)() = &HasMembers::g;
94   void (HasMembers::*pmgi)(int) = &HasMembers::g;
95   void (*pmgd)(double) = &HasMembers::g;
96 
97   void (HasMembers::*pmd)() = &HasMembers::d;
98 }
99 
100 struct Incomplete;
101 
h()102 void h() {
103   HasMembers hm, *phm = &hm;
104 
105   int HasMembers::*pi = &HasMembers::i;
106   hm.*pi = 0;
107   int i = phm->*pi;
108   (void)&(hm.*pi);
109   (void)&(phm->*pi);
110   (void)&((&hm)->*pi);
111 
112   void (HasMembers::*pf)() = &HasMembers::f;
113   (hm.*pf)();
114   (phm->*pf)();
115 
116   (void)(hm->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'HasMembers'}}
117   (void)(phm.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'HasMembers *'}}
118   (void)(i.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'int'}}
119   int *ptr;
120   (void)(ptr->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'int *'}}
121 
122   int A::*pai = 0;
123   D d, *pd = &d;
124   (void)(d.*pai);
125   (void)(pd->*pai);
126   F f, *ptrf = &f;
127   (void)(f.*pai); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A'}}
128   (void)(ptrf->*pai); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A'}}
129   H h, *ptrh = &h;
130   (void)(h.*pai); // expected-error {{cannot cast 'H' to its private base class 'A'}}
131   (void)(ptrh->*pai); // expected-error {{cannot cast 'H' to its private base class 'A'}}
132 
133   (void)(hm.*i); // expected-error {{pointer-to-member}}
134   (void)(phm->*i); // expected-error {{pointer-to-member}}
135 
136   // Okay
137   Incomplete *inc;
138   int Incomplete::*pii = 0;
139   (void)(inc->*pii);
140 }
141 
142 struct OverloadsPtrMem
143 {
144   int operator ->*(const char *);
145 };
146 
i()147 void i() {
148   OverloadsPtrMem m;
149   int foo = m->*"Awesome!";
150 }
151 
152 namespace pr5985 {
153   struct c {
154     void h();
fpr5985::c155     void f() {
156       void (c::*p)();
157       p = &h; // expected-error {{must explicitly qualify}}
158       p = &this->h; // expected-error {{cannot create a non-constant pointer to member function}}
159       p = &(*this).h; // expected-error {{cannot create a non-constant pointer to member function}}
160     }
161   };
162 }
163 
164 namespace pr6783 {
165   struct Base {};
166   struct X; // expected-note {{forward declaration}}
167 
test1(int Base::* p2m,X * object)168   int test1(int Base::* p2m, X* object)
169   {
170     return object->*p2m; // expected-error {{left hand operand to ->*}}
171   }
172 }
173 
174 namespace PR7176 {
175   namespace base
176   {
177     struct Process
178     { };
179     struct Continuous : Process
180     {
181       bool cond();
182     };
183   }
184 
185   typedef bool( base::Process::*Condition )();
186 
m()187   void m()
188   { (void)(Condition) &base::Continuous::cond; }
189 }
190 
191 namespace rdar8358512 {
192   // We can't call this with an overload set because we're not allowed
193   // to look into overload sets unless the parameter has some kind of
194   // function type.
195   template <class F> void bind(F f); // expected-note 12 {{candidate template ignored}}
196   template <class F, class T> void bindmem(F (T::*f)()); // expected-note 4 {{candidate template ignored}}
197   template <class F> void bindfn(F (*f)()); // expected-note 4 {{candidate template ignored}}
198 
199   struct A {
200     void nonstat();
201     void nonstat(int);
202 
203     void mixed();
204     static void mixed(int);
205 
206     static void stat();
207     static void stat(int);
208 
209     template <typename T> struct Test0 {
testrdar8358512::A::Test0210       void test() {
211         bind(&nonstat); // expected-error {{no matching function for call}}
212         bind(&A::nonstat); // expected-error {{no matching function for call}}
213 
214         bind(&mixed); // expected-error {{no matching function for call}}
215         bind(&A::mixed); // expected-error {{no matching function for call}}
216 
217         bind(&stat); // expected-error {{no matching function for call}}
218         bind(&A::stat); // expected-error {{no matching function for call}}
219       }
220     };
221 
222     template <typename T> struct Test1 {
testrdar8358512::A::Test1223       void test() {
224         bindmem(&nonstat); // expected-error {{no matching function for call}}
225         bindmem(&A::nonstat);
226 
227         bindmem(&mixed); // expected-error {{no matching function for call}}
228         bindmem(&A::mixed);
229 
230         bindmem(&stat); // expected-error {{no matching function for call}}
231         bindmem(&A::stat); // expected-error {{no matching function for call}}
232       }
233     };
234 
235     template <typename T> struct Test2 {
testrdar8358512::A::Test2236       void test() {
237         bindfn(&nonstat); // expected-error {{no matching function for call}}
238         bindfn(&A::nonstat); // expected-error {{no matching function for call}}
239 
240         bindfn(&mixed); // expected-error {{no matching function for call}}
241         bindfn(&A::mixed); // expected-error {{no matching function for call}}
242 
243         bindfn(&stat);
244         bindfn(&A::stat);
245       }
246     };
247   };
248 
249   template <class T> class B {
250     void nonstat();
251     void nonstat(int);
252 
253     void mixed();
254     static void mixed(int);
255 
256     static void stat();
257     static void stat(int);
258 
259     // None of these can be diagnosed yet, because the arguments are
260     // still dependent.
test0a()261     void test0a() {
262       bind(&nonstat);
263       bind(&B::nonstat);
264 
265       bind(&mixed);
266       bind(&B::mixed);
267 
268       bind(&stat);
269       bind(&B::stat);
270     }
271 
test0b()272     void test0b() {
273       bind(&nonstat); // expected-error {{no matching function for call}}
274       bind(&B::nonstat); // expected-error {{no matching function for call}}
275 
276       bind(&mixed); // expected-error {{no matching function for call}}
277       bind(&B::mixed); // expected-error {{no matching function for call}}
278 
279       bind(&stat); // expected-error {{no matching function for call}}
280       bind(&B::stat); // expected-error {{no matching function for call}}
281     }
282   };
283 
284   template void B<int>::test0b(); // expected-note {{in instantiation}}
285 }
286 
287 namespace PR9973 {
288   template<class R, class T> struct dm
289   {
290     typedef R T::*F;
291     F f_;
callPR9973::dm292     template<class U> int & call(U u)
293     { return u->*f_; } // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} expected-error {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
294 
operator ()PR9973::dm295     template<class U> int operator()(U u)
296     { call(u); } // expected-note{{in instantiation of}}
297   };
298 
299   template<class R, class T>
300   dm<R, T> mem_fn(R T::*) ;
301 
302   struct test
303   { int nullary_v(); };
304 
f()305   void f()
306   {
307     test* t;
308     mem_fn(&test::nullary_v)(t); // expected-note{{in instantiation of}}
309   }
310 }
311 
312 namespace test8 {
313   struct A { int foo; };
test1()314   int test1() {
315     // Verify that we perform (and check) an lvalue conversion on the operands here.
316     return (*((A**) 0)) // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
317              ->**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
318   }
319 
test2()320   int test2() {
321     // Verify that we perform (and check) an lvalue conversion on the operands here.
322     // TODO: the .* should itself warn about being a dereference of null.
323     return (*((A*) 0))
324              .**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
325   }
326 }
327