xref: /llvm-project/clang/test/AST/ByteCode/memberpointers.cpp (revision c6605a08681309188fa260a409bf5d37400876a0)
1a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -verify=expected,both %s
2a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++23 -fexperimental-new-constant-interpreter -verify=expected,both %s
3a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++14 -verify=ref,both %s
4a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++23 -verify=ref,both %s
5a07aba5dSTimm Baeder 
6a07aba5dSTimm Baeder namespace MemberPointers {
7a07aba5dSTimm Baeder   struct A {
8a07aba5dSTimm Baeder     constexpr A(int n) : n(n) {}
9a07aba5dSTimm Baeder     int n;
10a07aba5dSTimm Baeder     constexpr int f() const { return n + 3; }
11a07aba5dSTimm Baeder   };
12a07aba5dSTimm Baeder 
13a07aba5dSTimm Baeder   constexpr A a(7);
14a07aba5dSTimm Baeder   static_assert(A(5).*&A::n == 5, "");
15a07aba5dSTimm Baeder   static_assert((&a)->*&A::n == 7, "");
16a07aba5dSTimm Baeder   static_assert((A(8).*&A::f)() == 11, "");
17a07aba5dSTimm Baeder   static_assert(((&a)->*&A::f)() == 10, "");
18a07aba5dSTimm Baeder 
19a07aba5dSTimm Baeder   struct B : A {
20a07aba5dSTimm Baeder     constexpr B(int n, int m) : A(n), m(m) {}
21a07aba5dSTimm Baeder     int m;
22a07aba5dSTimm Baeder     constexpr int g() const { return n + m + 1; }
23a07aba5dSTimm Baeder   };
24a07aba5dSTimm Baeder   constexpr B b(9, 13);
25a07aba5dSTimm Baeder   static_assert(B(4, 11).*&A::n == 4, "");
26a07aba5dSTimm Baeder   static_assert(B(4, 11).*&B::m == 11, "");
27a07aba5dSTimm Baeder   static_assert(B(4, 11).m == 11, "");
28a07aba5dSTimm Baeder   static_assert(B(4, 11).*(int(A::*))&B::m == 11, "");
29a07aba5dSTimm Baeder   static_assert(B(4, 11).*&B::m == 11, "");
30a07aba5dSTimm Baeder   static_assert((&b)->*&A::n == 9, "");
31a07aba5dSTimm Baeder   static_assert((&b)->*&B::m == 13, "");
32a07aba5dSTimm Baeder   static_assert((&b)->*(int(A::*))&B::m == 13, "");
33a07aba5dSTimm Baeder   static_assert((B(4, 11).*&A::f)() == 7, "");
34a07aba5dSTimm Baeder   static_assert((B(4, 11).*&B::g)() == 16, "");
35a07aba5dSTimm Baeder 
36a07aba5dSTimm Baeder   static_assert((B(4, 11).*(int(A::*)() const)&B::g)() == 16, "");
37a07aba5dSTimm Baeder 
38a07aba5dSTimm Baeder   static_assert(((&b)->*&A::f)() == 12, "");
39a07aba5dSTimm Baeder   static_assert(((&b)->*&B::g)() == 23, "");
40a07aba5dSTimm Baeder   static_assert(((&b)->*(int(A::*)()const)&B::g)() == 23, "");
41a07aba5dSTimm Baeder 
42a07aba5dSTimm Baeder 
43a07aba5dSTimm Baeder   struct S {
44a07aba5dSTimm Baeder     constexpr S(int m, int n, int (S::*pf)() const, int S::*pn) :
45a07aba5dSTimm Baeder       m(m), n(n), pf(pf), pn(pn) {}
46a07aba5dSTimm Baeder     constexpr S() : m(), n(), pf(&S::f), pn(&S::n) {}
47a07aba5dSTimm Baeder 
48a07aba5dSTimm Baeder     constexpr int f() const { return this->*pn; }
49a07aba5dSTimm Baeder     virtual int g() const;
50a07aba5dSTimm Baeder 
51a07aba5dSTimm Baeder     int m, n;
52a07aba5dSTimm Baeder     int (S::*pf)() const;
53a07aba5dSTimm Baeder     int S::*pn;
54a07aba5dSTimm Baeder   };
55a07aba5dSTimm Baeder 
56a07aba5dSTimm Baeder   constexpr int S::*pm = &S::m;
57a07aba5dSTimm Baeder   constexpr int S::*pn = &S::n;
58a07aba5dSTimm Baeder 
59a07aba5dSTimm Baeder   constexpr int (S::*pf)() const = &S::f;
60a07aba5dSTimm Baeder   constexpr int (S::*pg)() const = &S::g;
61a07aba5dSTimm Baeder 
62a07aba5dSTimm Baeder   constexpr S s(2, 5, &S::f, &S::m);
63a07aba5dSTimm Baeder 
64a07aba5dSTimm Baeder   static_assert((s.*&S::f)() == 2, "");
65a07aba5dSTimm Baeder   static_assert((s.*s.pf)() == 2, "");
66a07aba5dSTimm Baeder 
67a07aba5dSTimm Baeder   static_assert(pf == &S::f, "");
68a07aba5dSTimm Baeder 
69a07aba5dSTimm Baeder   static_assert(pf == s.*&S::pf, "");
70a07aba5dSTimm Baeder 
71a07aba5dSTimm Baeder   static_assert(pm == &S::m, "");
72a07aba5dSTimm Baeder   static_assert(pm != pn, "");
73a07aba5dSTimm Baeder   static_assert(s.pn != pn, "");
74a07aba5dSTimm Baeder   static_assert(s.pn == pm, "");
75a07aba5dSTimm Baeder   static_assert(pg != nullptr, "");
76a07aba5dSTimm Baeder   static_assert(pf != nullptr, "");
77a07aba5dSTimm Baeder   static_assert((int S::*)nullptr == nullptr, "");
78a07aba5dSTimm Baeder   static_assert(pg == pg, ""); // both-error {{constant expression}} \
79a07aba5dSTimm Baeder                                // both-note {{comparison of pointer to virtual member function 'g' has unspecified value}}
80a07aba5dSTimm Baeder   static_assert(pf != pg, ""); // both-error {{constant expression}} \
81a07aba5dSTimm Baeder                                // both-note {{comparison of pointer to virtual member function 'g' has unspecified value}}
82a07aba5dSTimm Baeder 
83a07aba5dSTimm Baeder   template<int n> struct T : T<n-1> { const int X = n;};
84a07aba5dSTimm Baeder   template<> struct T<0> { int n; char k;};
85a07aba5dSTimm Baeder   template<> struct T<30> : T<29> { int m; };
86a07aba5dSTimm Baeder 
87a07aba5dSTimm Baeder   T<17> t17;
88a07aba5dSTimm Baeder   T<30> t30;
89a07aba5dSTimm Baeder 
90a07aba5dSTimm Baeder   constexpr int (T<15>::*deepm) = (int(T<10>::*))&T<30>::m;
91a07aba5dSTimm Baeder   constexpr int (T<10>::*deepn) = &T<0>::n;
92a07aba5dSTimm Baeder   constexpr char (T<10>::*deepk) = &T<0>::k;
93a07aba5dSTimm Baeder 
94a07aba5dSTimm Baeder   static_assert(&(t17.*deepn) == &t17.n, "");
95a07aba5dSTimm Baeder   static_assert(&(t17.*deepk) == &t17.k, "");
96a07aba5dSTimm Baeder   static_assert(deepn == &T<2>::n, "");
97a07aba5dSTimm Baeder 
98a07aba5dSTimm Baeder   constexpr int *pgood = &(t30.*deepm);
99a07aba5dSTimm Baeder   constexpr int *pbad = &(t17.*deepm); // both-error {{constant expression}}
100a07aba5dSTimm Baeder   static_assert(&(t30.*deepm) == &t30.m, "");
101a07aba5dSTimm Baeder 
102a07aba5dSTimm Baeder   static_assert(deepm == &T<50>::m, "");
103a07aba5dSTimm Baeder   static_assert(deepm != deepn, "");
104a07aba5dSTimm Baeder 
105a07aba5dSTimm Baeder   constexpr T<5> *p17_5 = &t17;
106a07aba5dSTimm Baeder   constexpr T<13> *p17_13 = (T<13>*)p17_5;
107a07aba5dSTimm Baeder   constexpr T<23> *p17_23 = (T<23>*)p17_13; // both-error {{constant expression}} \
108a07aba5dSTimm Baeder                                             // both-note {{cannot cast object of dynamic type 'T<17>' to type 'T<23>'}}
109a07aba5dSTimm Baeder   constexpr T<18> *p17_18 = (T<18>*)p17_13; // both-error {{constant expression}} \
110a07aba5dSTimm Baeder                                             // both-note {{cannot cast object of dynamic type 'T<17>' to type 'T<18>'}}
111a07aba5dSTimm Baeder   static_assert(&(p17_5->*(int(T<0>::*))deepn) == &t17.n, "");
112a07aba5dSTimm Baeder   static_assert(&(p17_5->*(int(T<0>::*))deepn), "");
113a07aba5dSTimm Baeder 
114a07aba5dSTimm Baeder 
115a07aba5dSTimm Baeder   static_assert(&(p17_13->*deepn) == &t17.n, "");
116a07aba5dSTimm Baeder   constexpr int *pbad2 = &(p17_13->*(int(T<9>::*))deepm); // both-error {{constant expression}}
117a07aba5dSTimm Baeder 
118a07aba5dSTimm Baeder   constexpr T<5> *p30_5 = &t30;
119a07aba5dSTimm Baeder   constexpr T<23> *p30_23 = (T<23>*)p30_5;
120a07aba5dSTimm Baeder   constexpr T<13> *p30_13 = p30_23;
121a07aba5dSTimm Baeder   static_assert(&(p30_13->*deepn) == &t30.n, "");
122a07aba5dSTimm Baeder   static_assert(&(p30_23->*deepn) == &t30.n, "");
123a07aba5dSTimm Baeder   static_assert(&(p30_5->*(int(T<3>::*))deepn) == &t30.n, "");
124a07aba5dSTimm Baeder 
125a07aba5dSTimm Baeder   static_assert(&(p30_5->*(int(T<2>::*))deepm) == &t30.m, "");
126a07aba5dSTimm Baeder   static_assert(&(((T<17>*)p30_13)->*deepm) == &t30.m, "");
127a07aba5dSTimm Baeder   static_assert(&(p30_23->*deepm) == &t30.m, "");
128a07aba5dSTimm Baeder 
129a07aba5dSTimm Baeder 
130a07aba5dSTimm Baeder   /// Added tests not from constant-expression-cxx11.cpp
131a07aba5dSTimm Baeder   static_assert(pm, "");
132a07aba5dSTimm Baeder   static_assert(!((int S::*)nullptr), "");
133a07aba5dSTimm Baeder   constexpr int S::*pk = nullptr;
134a07aba5dSTimm Baeder   static_assert(!pk, "");
135a07aba5dSTimm Baeder }
136a07aba5dSTimm Baeder 
137a07aba5dSTimm Baeder namespace test3 {
138a07aba5dSTimm Baeder   struct nsCSSRect {
139a07aba5dSTimm Baeder   };
140a07aba5dSTimm Baeder   static int nsCSSRect::* sides;
141a07aba5dSTimm Baeder   nsCSSRect dimenX;
142a07aba5dSTimm Baeder   void ParseBoxCornerRadii(int y) {
143a07aba5dSTimm Baeder     switch (y) {
144a07aba5dSTimm Baeder     }
145a07aba5dSTimm Baeder     int& x = dimenX.*sides;
146a07aba5dSTimm Baeder   }
147a07aba5dSTimm Baeder }
148a07aba5dSTimm Baeder 
149a07aba5dSTimm Baeder void foo() {
150a07aba5dSTimm Baeder   class X;
151a07aba5dSTimm Baeder   void (X::*d) ();
152a07aba5dSTimm Baeder   d = nullptr; /// This calls in the constant interpreter.
153a07aba5dSTimm Baeder }
154a07aba5dSTimm Baeder 
155a07aba5dSTimm Baeder namespace {
156a07aba5dSTimm Baeder   struct A { int n; };
157a07aba5dSTimm Baeder   struct B { int n; };
158a07aba5dSTimm Baeder   struct C : A, B {};
159a07aba5dSTimm Baeder   struct D { double d; C c; };
160a07aba5dSTimm Baeder   const int &&u = static_cast<B&&>(0, ((D&&)D{}).*&D::c).n; // both-warning {{left operand of comma operator has no effect}}
161a07aba5dSTimm Baeder }
162a07aba5dSTimm Baeder 
163a07aba5dSTimm Baeder /// From SemaTemplate/instantiate-member-pointers.cpp
164a07aba5dSTimm Baeder namespace {
165a07aba5dSTimm Baeder   struct Y {
166a07aba5dSTimm Baeder     int x;
167a07aba5dSTimm Baeder   };
168a07aba5dSTimm Baeder 
169a07aba5dSTimm Baeder   template<typename T, typename Class, T Class::*Ptr>
170a07aba5dSTimm Baeder   struct X3 {
171a07aba5dSTimm Baeder     X3<T, Class, Ptr> &operator=(const T& value) {
172a07aba5dSTimm Baeder       return *this;
173a07aba5dSTimm Baeder     }
174a07aba5dSTimm Baeder   };
175a07aba5dSTimm Baeder 
176a07aba5dSTimm Baeder   typedef int Y::*IntMember;
177a07aba5dSTimm Baeder   template<IntMember Member>
178a07aba5dSTimm Baeder   struct X4 {
179a07aba5dSTimm Baeder     X3<int, Y, Member> member;
180a07aba5dSTimm Baeder     int &getMember(Y& y) { return y.*Member; }
181a07aba5dSTimm Baeder   };
182a07aba5dSTimm Baeder 
183a07aba5dSTimm Baeder   int &get_X4(X4<&Y::x> x4, Y& y) {
184a07aba5dSTimm Baeder     return x4.getMember(y);
185a07aba5dSTimm Baeder   }
186a07aba5dSTimm Baeder }
187a07aba5dSTimm Baeder 
188a07aba5dSTimm Baeder /// From test/CXX/basic/basic.def.odr/p2.cpp
189a07aba5dSTimm Baeder namespace {
190a07aba5dSTimm Baeder   void use(int);
191a07aba5dSTimm Baeder   struct S { int x; int f() const; };
192a07aba5dSTimm Baeder   constexpr S *ps = nullptr;
193a07aba5dSTimm Baeder   S *const &psr = ps;
194a07aba5dSTimm Baeder 
195a07aba5dSTimm Baeder   void test() {
196a07aba5dSTimm Baeder     use(ps->*&S::x);
197a07aba5dSTimm Baeder     use(psr->*&S::x);
198a07aba5dSTimm Baeder   }
199a07aba5dSTimm Baeder }
200a07aba5dSTimm Baeder 
201a07aba5dSTimm Baeder namespace MemPtrTemporary {
202a07aba5dSTimm Baeder   struct A {
203a07aba5dSTimm Baeder     constexpr int f() const { return 5; }
204a07aba5dSTimm Baeder   };
205a07aba5dSTimm Baeder 
206a07aba5dSTimm Baeder   constexpr int apply(const A &a, int (A::*ff)() const) {
207a07aba5dSTimm Baeder     return (a.*ff)();
208a07aba5dSTimm Baeder   }
209a07aba5dSTimm Baeder 
210a07aba5dSTimm Baeder   static_assert(apply(A(), &A::f) == 5, "");
211a07aba5dSTimm Baeder }
212*c6605a08STimm Baeder 
213*c6605a08STimm Baeder namespace IndirectFields {
214*c6605a08STimm Baeder   struct I { union { struct { int a, b; }; }; };
215*c6605a08STimm Baeder 
216*c6605a08STimm Baeder   template <typename T, int T::*F>
217*c6605a08STimm Baeder   constexpr int ReadField(const T &o) {
218*c6605a08STimm Baeder     return F ? o.*F : 0;
219*c6605a08STimm Baeder   }
220*c6605a08STimm Baeder   void ReadFields() {
221*c6605a08STimm Baeder     I i;
222*c6605a08STimm Baeder     ReadField<I, &I::a>(i);
223*c6605a08STimm Baeder     ReadField<I, &I::b>(i);
224*c6605a08STimm Baeder   }
225*c6605a08STimm Baeder 
226*c6605a08STimm Baeder   constexpr I i{12};
227*c6605a08STimm Baeder   static_assert(ReadField<I, &I::a>(i) == 12, "");
228*c6605a08STimm Baeder }
229