1*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s
2*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64
3*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify
4*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -Wno-uninitialized -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify
5*67e74705SXin Li
6*67e74705SXin Li struct PR26313_Y;
7*67e74705SXin Li typedef void (PR26313_Y::*PR26313_FUNC)();
8*67e74705SXin Li struct PR26313_X {
9*67e74705SXin Li PR26313_FUNC *ptr;
10*67e74705SXin Li PR26313_X();
11*67e74705SXin Li };
PR26313_X()12*67e74705SXin Li PR26313_X::PR26313_X() {}
PR26313_f(PR26313_FUNC * p)13*67e74705SXin Li void PR26313_f(PR26313_FUNC *p) { delete p; }
14*67e74705SXin Li
15*67e74705SXin Li struct PR26313_Z;
16*67e74705SXin Li int PR26313_Z::**a = nullptr;
17*67e74705SXin Li int PR26313_Z::*b = *a;
18*67e74705SXin Li // CHECK-DAG: @"\01?a@@3PAPQPR26313_Z@@HA" = global %0* null, align 4
19*67e74705SXin Li // CHECK-DAG: @"\01?b@@3PQPR26313_Z@@HQ1@" = global { i32, i32, i32 } { i32 0, i32 0, i32 -1 }, align 4
20*67e74705SXin Li
21*67e74705SXin Li namespace PR20947 {
22*67e74705SXin Li struct A;
23*67e74705SXin Li int A::**a = nullptr;
24*67e74705SXin Li // CHECK-DAG: @"\01?a@PR20947@@3PAPQA@1@HA" = global %{{.*}}* null, align 4
25*67e74705SXin Li
26*67e74705SXin Li struct B;
27*67e74705SXin Li int B::*&b = b;
28*67e74705SXin Li // CHECK-DAG: @"\01?b@PR20947@@3AAPQB@1@HA" = global %{{.*}}* null, align 4
29*67e74705SXin Li }
30*67e74705SXin Li
31*67e74705SXin Li namespace PR20017 {
32*67e74705SXin Li template <typename T>
33*67e74705SXin Li struct A {
m_fn1PR20017::A34*67e74705SXin Li int T::*m_fn1() { return nullptr; }
35*67e74705SXin Li };
36*67e74705SXin Li struct B;
37*67e74705SXin Li auto a = &A<B>::m_fn1;
38*67e74705SXin Li // CHECK-DAG: @"\01?a@PR20017@@3P8?$A@UB@PR20017@@@1@AEPQB@1@HXZQ21@" = global i8* bitcast ({ i32, i32, i32 } ({{.*}}*)* @"\01?m_fn1@?$A@UB@PR20017@@@PR20017@@QAEPQB@2@HXZ" to i8*), align 4
39*67e74705SXin Li }
40*67e74705SXin Li
41*67e74705SXin Li #ifndef INCOMPLETE_VIRTUAL
42*67e74705SXin Li struct B1 {
43*67e74705SXin Li void foo();
44*67e74705SXin Li int b;
45*67e74705SXin Li };
46*67e74705SXin Li struct B2 {
47*67e74705SXin Li int b2;
48*67e74705SXin Li void foo();
49*67e74705SXin Li };
50*67e74705SXin Li struct Single : B1 {
51*67e74705SXin Li void foo();
52*67e74705SXin Li };
53*67e74705SXin Li struct Multiple : B1, B2 {
54*67e74705SXin Li int m;
55*67e74705SXin Li void foo();
56*67e74705SXin Li };
57*67e74705SXin Li struct Virtual : virtual B1 {
58*67e74705SXin Li int v;
59*67e74705SXin Li void foo();
60*67e74705SXin Li };
61*67e74705SXin Li
62*67e74705SXin Li struct POD {
63*67e74705SXin Li int a;
64*67e74705SXin Li int b;
65*67e74705SXin Li };
66*67e74705SXin Li
67*67e74705SXin Li struct Polymorphic {
68*67e74705SXin Li virtual void myVirtual();
69*67e74705SXin Li int a;
70*67e74705SXin Li int b;
71*67e74705SXin Li };
72*67e74705SXin Li
73*67e74705SXin Li // This class uses the virtual inheritance model, yet its vbptr offset is not 0.
74*67e74705SXin Li // We still use zero for the null field offset, despite it being a valid field
75*67e74705SXin Li // offset.
76*67e74705SXin Li struct NonZeroVBPtr : POD, Virtual {
77*67e74705SXin Li int n;
78*67e74705SXin Li void foo();
79*67e74705SXin Li };
80*67e74705SXin Li
81*67e74705SXin Li struct Unspecified;
82*67e74705SXin Li struct UnspecSingle;
83*67e74705SXin Li
84*67e74705SXin Li // Check that we can lower the LLVM types and get the null initializers right.
85*67e74705SXin Li int Single ::*s_d_memptr;
86*67e74705SXin Li int Polymorphic::*p_d_memptr;
87*67e74705SXin Li int Multiple ::*m_d_memptr;
88*67e74705SXin Li int Virtual ::*v_d_memptr;
89*67e74705SXin Li int NonZeroVBPtr::*n_d_memptr;
90*67e74705SXin Li int Unspecified::*u_d_memptr;
91*67e74705SXin Li int UnspecSingle::*us_d_memptr;
92*67e74705SXin Li // CHECK: @"\01?s_d_memptr@@3PQSingle@@HQ1@" = global i32 -1, align 4
93*67e74705SXin Li // CHECK: @"\01?p_d_memptr@@3PQPolymorphic@@HQ1@" = global i32 0, align 4
94*67e74705SXin Li // CHECK: @"\01?m_d_memptr@@3PQMultiple@@HQ1@" = global i32 -1, align 4
95*67e74705SXin Li // CHECK: @"\01?v_d_memptr@@3PQVirtual@@HQ1@" = global { i32, i32 }
96*67e74705SXin Li // CHECK: { i32 0, i32 -1 }, align 4
97*67e74705SXin Li // CHECK: @"\01?n_d_memptr@@3PQNonZeroVBPtr@@HQ1@" = global { i32, i32 }
98*67e74705SXin Li // CHECK: { i32 0, i32 -1 }, align 4
99*67e74705SXin Li // CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HQ1@" = global { i32, i32, i32 }
100*67e74705SXin Li // CHECK: { i32 0, i32 0, i32 -1 }, align 4
101*67e74705SXin Li // CHECK: @"\01?us_d_memptr@@3PQUnspecSingle@@HQ1@" = global { i32, i32, i32 }
102*67e74705SXin Li // CHECK: { i32 0, i32 0, i32 -1 }, align 4
103*67e74705SXin Li
104*67e74705SXin Li void (Single ::*s_f_memptr)();
105*67e74705SXin Li void (Multiple::*m_f_memptr)();
106*67e74705SXin Li void (Virtual ::*v_f_memptr)();
107*67e74705SXin Li // CHECK: @"\01?s_f_memptr@@3P8Single@@AEXXZQ1@" = global i8* null, align 4
108*67e74705SXin Li // CHECK: @"\01?m_f_memptr@@3P8Multiple@@AEXXZQ1@" = global { i8*, i32 } zeroinitializer, align 4
109*67e74705SXin Li // CHECK: @"\01?v_f_memptr@@3P8Virtual@@AEXXZQ1@" = global { i8*, i32, i32 } zeroinitializer, align 4
110*67e74705SXin Li
111*67e74705SXin Li // We can define Unspecified after locking in the inheritance model.
112*67e74705SXin Li struct Unspecified : Multiple, Virtual {
113*67e74705SXin Li void foo();
114*67e74705SXin Li int u;
115*67e74705SXin Li };
116*67e74705SXin Li
117*67e74705SXin Li struct UnspecSingle {
118*67e74705SXin Li void foo();
119*67e74705SXin Li };
120*67e74705SXin Li
121*67e74705SXin Li // Test memptr emission in a constant expression.
122*67e74705SXin Li namespace Const {
123*67e74705SXin Li void (Single ::*s_f_mp)() = &Single::foo;
124*67e74705SXin Li void (Multiple ::*m_f_mp)() = &B2::foo;
125*67e74705SXin Li void (Virtual ::*v_f_mp)() = &Virtual::foo;
126*67e74705SXin Li void (Unspecified::*u_f_mp)() = &Unspecified::foo;
127*67e74705SXin Li void (UnspecSingle::*us_f_mp)() = &UnspecSingle::foo;
128*67e74705SXin Li // CHECK: @"\01?s_f_mp@Const@@3P8Single@@AEXXZQ2@" =
129*67e74705SXin Li // CHECK: global i8* bitcast ({{.*}} @"\01?foo@Single@@QAEXXZ" to i8*), align 4
130*67e74705SXin Li // CHECK: @"\01?m_f_mp@Const@@3P8Multiple@@AEXXZQ2@" =
131*67e74705SXin Li // CHECK: global { i8*, i32 } { i8* bitcast ({{.*}} @"\01?foo@B2@@QAEXXZ" to i8*), i32 4 }, align 4
132*67e74705SXin Li // CHECK: @"\01?v_f_mp@Const@@3P8Virtual@@AEXXZQ2@" =
133*67e74705SXin Li // CHECK: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4
134*67e74705SXin Li // CHECK: @"\01?u_f_mp@Const@@3P8Unspecified@@AEXXZQ2@" =
135*67e74705SXin Li // CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
136*67e74705SXin Li // CHECK: @"\01?us_f_mp@Const@@3P8UnspecSingle@@AEXXZQ2@" =
137*67e74705SXin Li // CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4
138*67e74705SXin Li }
139*67e74705SXin Li
140*67e74705SXin Li namespace CastParam {
141*67e74705SXin Li // This exercises ConstExprEmitter instead of ValueDecl::evaluateValue. The
142*67e74705SXin Li // extra reinterpret_cast for the parameter type requires more careful folding.
143*67e74705SXin Li // FIXME: Or does it? If reinterpret_casts are no-ops, we should be able to
144*67e74705SXin Li // strip them in evaluateValue() and just proceed as normal with an APValue.
145*67e74705SXin Li struct A {
146*67e74705SXin Li int a;
147*67e74705SXin Li void foo(A *p);
148*67e74705SXin Li };
149*67e74705SXin Li struct B { int b; };
150*67e74705SXin Li struct C : B, A { int c; };
151*67e74705SXin Li
152*67e74705SXin Li void (A::*ptr1)(void *) = (void (A::*)(void *)) &A::foo;
153*67e74705SXin Li // CHECK: @"\01?ptr1@CastParam@@3P8A@1@AEXPAX@ZQ21@" =
154*67e74705SXin Li // CHECK: global i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), align 4
155*67e74705SXin Li
156*67e74705SXin Li // Try a reinterpret_cast followed by a memptr conversion.
157*67e74705SXin Li void (C::*ptr2)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) &A::foo;
158*67e74705SXin Li // CHECK: @"\01?ptr2@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
159*67e74705SXin Li // CHECK: global { i8*, i32 } { i8* bitcast (void ({{.*}})* @"\01?foo@A@CastParam@@QAEXPAU12@@Z" to i8*), i32 4 }, align 4
160*67e74705SXin Li
161*67e74705SXin Li void (C::*ptr3)(void *) = (void (C::*)(void *)) (void (A::*)(void *)) (void (A::*)(A *)) 0;
162*67e74705SXin Li // CHECK: @"\01?ptr3@CastParam@@3P8C@1@AEXPAX@ZQ21@" =
163*67e74705SXin Li // CHECK: global { i8*, i32 } zeroinitializer, align 4
164*67e74705SXin Li
165*67e74705SXin Li struct D : C {
166*67e74705SXin Li virtual void isPolymorphic();
167*67e74705SXin Li int d;
168*67e74705SXin Li };
169*67e74705SXin Li
170*67e74705SXin Li // Try a cast that changes the inheritance model. Null for D is 0, but null for
171*67e74705SXin Li // C is -1. We need the cast to long in order to hit the non-APValue path.
172*67e74705SXin Li int C::*ptr4 = (int C::*) (int D::*) (long D::*) 0;
173*67e74705SXin Li // CHECK: @"\01?ptr4@CastParam@@3PQC@1@HQ21@" = global i32 -1, align 4
174*67e74705SXin Li
175*67e74705SXin Li // MSVC rejects this but we accept it.
176*67e74705SXin Li int C::*ptr5 = (int C::*) (long D::*) 0;
177*67e74705SXin Li // CHECK: @"\01?ptr5@CastParam@@3PQC@1@HQ21@" = global i32 -1, align 4
178*67e74705SXin Li }
179*67e74705SXin Li
180*67e74705SXin Li struct UnspecWithVBPtr;
181*67e74705SXin Li int UnspecWithVBPtr::*forceUnspecWithVBPtr;
182*67e74705SXin Li struct UnspecWithVBPtr : B1, virtual B2 {
183*67e74705SXin Li int u;
184*67e74705SXin Li void foo();
185*67e74705SXin Li };
186*67e74705SXin Li
187*67e74705SXin Li // Test emitting non-virtual member pointers in a non-constexpr setting.
EmitNonVirtualMemberPointers()188*67e74705SXin Li void EmitNonVirtualMemberPointers() {
189*67e74705SXin Li void (Single ::*s_f_memptr)() = &Single::foo;
190*67e74705SXin Li void (Multiple ::*m_f_memptr)() = &Multiple::foo;
191*67e74705SXin Li void (Virtual ::*v_f_memptr)() = &Virtual::foo;
192*67e74705SXin Li void (Unspecified::*u_f_memptr)() = &Unspecified::foo;
193*67e74705SXin Li void (UnspecWithVBPtr::*u2_f_memptr)() = &UnspecWithVBPtr::foo;
194*67e74705SXin Li // CHECK: define void @"\01?EmitNonVirtualMemberPointers@@YAXXZ"() {{.*}} {
195*67e74705SXin Li // CHECK: alloca i8*, align 4
196*67e74705SXin Li // CHECK: alloca { i8*, i32 }, align 4
197*67e74705SXin Li // CHECK: alloca { i8*, i32, i32 }, align 4
198*67e74705SXin Li // CHECK: alloca { i8*, i32, i32, i32 }, align 4
199*67e74705SXin Li // CHECK: store i8* bitcast (void (%{{.*}}*)* @"\01?foo@Single@@QAEXXZ" to i8*), i8** %{{.*}}, align 4
200*67e74705SXin Li // CHECK: store { i8*, i32 }
201*67e74705SXin Li // CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Multiple@@QAEXXZ" to i8*), i32 0 },
202*67e74705SXin Li // CHECK: { i8*, i32 }* %{{.*}}, align 4
203*67e74705SXin Li // CHECK: store { i8*, i32, i32 }
204*67e74705SXin Li // CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 },
205*67e74705SXin Li // CHECK: { i8*, i32, i32 }* %{{.*}}, align 4
206*67e74705SXin Li // CHECK: store { i8*, i32, i32, i32 }
207*67e74705SXin Li // CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 },
208*67e74705SXin Li // CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4
209*67e74705SXin Li // CHECK: store { i8*, i32, i32, i32 }
210*67e74705SXin Li // CHECK: { i8* bitcast (void (%{{.*}}*)* @"\01?foo@UnspecWithVBPtr@@QAEXXZ" to i8*),
211*67e74705SXin Li // CHECK: i32 0, i32 0, i32 0 },
212*67e74705SXin Li // CHECK: { i8*, i32, i32, i32 }* %{{.*}}, align 4
213*67e74705SXin Li // CHECK: ret void
214*67e74705SXin Li // CHECK: }
215*67e74705SXin Li }
216*67e74705SXin Li
podMemPtrs()217*67e74705SXin Li void podMemPtrs() {
218*67e74705SXin Li int POD::*memptr;
219*67e74705SXin Li memptr = &POD::a;
220*67e74705SXin Li memptr = &POD::b;
221*67e74705SXin Li if (memptr)
222*67e74705SXin Li memptr = 0;
223*67e74705SXin Li // Check that member pointers use the right offsets and that null is -1.
224*67e74705SXin Li // CHECK: define void @"\01?podMemPtrs@@YAXXZ"() {{.*}} {
225*67e74705SXin Li // CHECK: %[[memptr:.*]] = alloca i32, align 4
226*67e74705SXin Li // CHECK-NEXT: store i32 0, i32* %[[memptr]], align 4
227*67e74705SXin Li // CHECK-NEXT: store i32 4, i32* %[[memptr]], align 4
228*67e74705SXin Li // CHECK-NEXT: %[[memptr_val:.*]] = load i32, i32* %[[memptr]], align 4
229*67e74705SXin Li // CHECK-NEXT: %{{.*}} = icmp ne i32 %[[memptr_val]], -1
230*67e74705SXin Li // CHECK-NEXT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
231*67e74705SXin Li // CHECK: store i32 -1, i32* %[[memptr]], align 4
232*67e74705SXin Li // CHECK: ret void
233*67e74705SXin Li // CHECK: }
234*67e74705SXin Li }
235*67e74705SXin Li
polymorphicMemPtrs()236*67e74705SXin Li void polymorphicMemPtrs() {
237*67e74705SXin Li int Polymorphic::*memptr;
238*67e74705SXin Li memptr = &Polymorphic::a;
239*67e74705SXin Li memptr = &Polymorphic::b;
240*67e74705SXin Li if (memptr)
241*67e74705SXin Li memptr = 0;
242*67e74705SXin Li // Member pointers for polymorphic classes include the vtable slot in their
243*67e74705SXin Li // offset and use 0 to represent null.
244*67e74705SXin Li // CHECK: define void @"\01?polymorphicMemPtrs@@YAXXZ"() {{.*}} {
245*67e74705SXin Li // CHECK: %[[memptr:.*]] = alloca i32, align 4
246*67e74705SXin Li // CHECK-NEXT: store i32 4, i32* %[[memptr]], align 4
247*67e74705SXin Li // CHECK-NEXT: store i32 8, i32* %[[memptr]], align 4
248*67e74705SXin Li // CHECK-NEXT: %[[memptr_val:.*]] = load i32, i32* %[[memptr]], align 4
249*67e74705SXin Li // CHECK-NEXT: %{{.*}} = icmp ne i32 %[[memptr_val]], 0
250*67e74705SXin Li // CHECK-NEXT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
251*67e74705SXin Li // CHECK: store i32 0, i32* %[[memptr]], align 4
252*67e74705SXin Li // CHECK: ret void
253*67e74705SXin Li // CHECK: }
254*67e74705SXin Li }
255*67e74705SXin Li
nullTestDataUnspecified(int Unspecified::* mp)256*67e74705SXin Li bool nullTestDataUnspecified(int Unspecified::*mp) {
257*67e74705SXin Li return mp;
258*67e74705SXin Li // CHECK: define zeroext i1 @"\01?nullTestDataUnspecified@@YA_NPQUnspecified@@H@Z"{{.*}} {
259*67e74705SXin Li // CHECK: %{{.*}} = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
260*67e74705SXin Li // CHECK: store { i32, i32, i32 } {{.*}} align 4
261*67e74705SXin Li // CHECK: %[[mp:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
262*67e74705SXin Li // CHECK: %[[mp0:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 0
263*67e74705SXin Li // CHECK: %[[cmp0:.*]] = icmp ne i32 %[[mp0]], 0
264*67e74705SXin Li // CHECK: %[[mp1:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 1
265*67e74705SXin Li // CHECK: %[[cmp1:.*]] = icmp ne i32 %[[mp1]], 0
266*67e74705SXin Li // CHECK: %[[and0:.*]] = or i1 %[[cmp0]], %[[cmp1]]
267*67e74705SXin Li // CHECK: %[[mp2:.*]] = extractvalue { i32, i32, i32 } %[[mp]], 2
268*67e74705SXin Li // CHECK: %[[cmp2:.*]] = icmp ne i32 %[[mp2]], -1
269*67e74705SXin Li // CHECK: %[[and1:.*]] = or i1 %[[and0]], %[[cmp2]]
270*67e74705SXin Li // CHECK: ret i1 %[[and1]]
271*67e74705SXin Li // CHECK: }
272*67e74705SXin Li
273*67e74705SXin Li // Pass this large type indirectly.
274*67e74705SXin Li // X64-LABEL: define zeroext i1 @"\01?nullTestDataUnspecified@@
275*67e74705SXin Li // X64: ({ i32, i32, i32 }*)
276*67e74705SXin Li }
277*67e74705SXin Li
nullTestFunctionUnspecified(void (Unspecified::* mp)())278*67e74705SXin Li bool nullTestFunctionUnspecified(void (Unspecified::*mp)()) {
279*67e74705SXin Li return mp;
280*67e74705SXin Li // CHECK: define zeroext i1 @"\01?nullTestFunctionUnspecified@@YA_NP8Unspecified@@AEXXZ@Z"{{.*}} {
281*67e74705SXin Li // CHECK: %{{.*}} = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 4
282*67e74705SXin Li // CHECK: store { i8*, i32, i32, i32 } {{.*}} align 4
283*67e74705SXin Li // CHECK: %[[mp:.*]] = load { i8*, i32, i32, i32 }, { i8*, i32, i32, i32 }* %{{.*}}, align 4
284*67e74705SXin Li // CHECK: %[[mp0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[mp]], 0
285*67e74705SXin Li // CHECK: %[[cmp0:.*]] = icmp ne i8* %[[mp0]], null
286*67e74705SXin Li // CHECK: ret i1 %[[cmp0]]
287*67e74705SXin Li // CHECK: }
288*67e74705SXin Li }
289*67e74705SXin Li
loadDataMemberPointerVirtual(Virtual * o,int Virtual::* memptr)290*67e74705SXin Li int loadDataMemberPointerVirtual(Virtual *o, int Virtual::*memptr) {
291*67e74705SXin Li return o->*memptr;
292*67e74705SXin Li // Test that we can unpack this aggregate member pointer and load the member
293*67e74705SXin Li // data pointer.
294*67e74705SXin Li // CHECK: define i32 @"\01?loadDataMemberPointerVirtual@@YAHPAUVirtual@@PQ1@H@Z"{{.*}} {
295*67e74705SXin Li // CHECK: %[[o:.*]] = load %{{.*}}*, %{{.*}}** %{{.*}}, align 4
296*67e74705SXin Li // CHECK: %[[memptr:.*]] = load { i32, i32 }, { i32, i32 }* %{{.*}}, align 4
297*67e74705SXin Li // CHECK: %[[memptr0:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 0
298*67e74705SXin Li // CHECK: %[[memptr1:.*]] = extractvalue { i32, i32 } %[[memptr:.*]], 1
299*67e74705SXin Li // CHECK: %[[v6:.*]] = bitcast %{{.*}}* %[[o]] to i8*
300*67e74705SXin Li // CHECK: %[[vbptr:.*]] = getelementptr inbounds i8, i8* %[[v6]], i32 0
301*67e74705SXin Li // CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32**
302*67e74705SXin Li // CHECK: %[[vbtable:.*]] = load i32*, i32** %[[vbptr_a:.*]]
303*67e74705SXin Li // CHECK: %[[memptr1_shr:.*]] = ashr exact i32 %[[memptr1]], 2
304*67e74705SXin Li // CHECK: %[[v7:.*]] = getelementptr inbounds i32, i32* %[[vbtable]], i32 %[[memptr1_shr]]
305*67e74705SXin Li // CHECK: %[[vbase_offs:.*]] = load i32, i32* %[[v7]]
306*67e74705SXin Li // CHECK: %[[v10:.*]] = getelementptr inbounds i8, i8* %[[vbptr]], i32 %[[vbase_offs]]
307*67e74705SXin Li // CHECK: %[[offset:.*]] = getelementptr inbounds i8, i8* %[[v10]], i32 %[[memptr0]]
308*67e74705SXin Li // CHECK: %[[v11:.*]] = bitcast i8* %[[offset]] to i32*
309*67e74705SXin Li // CHECK: %[[v12:.*]] = load i32, i32* %[[v11]]
310*67e74705SXin Li // CHECK: ret i32 %[[v12]]
311*67e74705SXin Li // CHECK: }
312*67e74705SXin Li
313*67e74705SXin Li // A two-field data memptr on x64 gets coerced to i64 and is passed in a
314*67e74705SXin Li // register or memory.
315*67e74705SXin Li // X64-LABEL: define i32 @"\01?loadDataMemberPointerVirtual@@YAHPEAUVirtual@@PEQ1@H@Z"
316*67e74705SXin Li // X64: (%struct.Virtual* %o, i64 %memptr.coerce)
317*67e74705SXin Li }
318*67e74705SXin Li
loadDataMemberPointerUnspecified(Unspecified * o,int Unspecified::* memptr)319*67e74705SXin Li int loadDataMemberPointerUnspecified(Unspecified *o, int Unspecified::*memptr) {
320*67e74705SXin Li return o->*memptr;
321*67e74705SXin Li // Test that we can unpack this aggregate member pointer and load the member
322*67e74705SXin Li // data pointer.
323*67e74705SXin Li // CHECK: define i32 @"\01?loadDataMemberPointerUnspecified@@YAHPAUUnspecified@@PQ1@H@Z"{{.*}} {
324*67e74705SXin Li // CHECK: %[[o:.*]] = load %{{.*}}*, %{{.*}}** %{{.*}}, align 4
325*67e74705SXin Li // CHECK: %[[memptr:.*]] = load { i32, i32, i32 }, { i32, i32, i32 }* %{{.*}}, align 4
326*67e74705SXin Li // CHECK: %[[memptr0:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 0
327*67e74705SXin Li // CHECK: %[[memptr1:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 1
328*67e74705SXin Li // CHECK: %[[memptr2:.*]] = extractvalue { i32, i32, i32 } %[[memptr:.*]], 2
329*67e74705SXin Li // CHECK: %[[base:.*]] = bitcast %{{.*}}* %[[o]] to i8*
330*67e74705SXin Li // CHECK: %[[is_vbase:.*]] = icmp ne i32 %[[memptr2]], 0
331*67e74705SXin Li // CHECK: br i1 %[[is_vbase]], label %[[vadjust:.*]], label %[[skip:.*]]
332*67e74705SXin Li //
333*67e74705SXin Li // CHECK: [[vadjust]]
334*67e74705SXin Li // CHECK: %[[vbptr:.*]] = getelementptr inbounds i8, i8* %[[base]], i32 %[[memptr1]]
335*67e74705SXin Li // CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32**
336*67e74705SXin Li // CHECK: %[[vbtable:.*]] = load i32*, i32** %[[vbptr_a:.*]]
337*67e74705SXin Li // CHECK: %[[memptr2_shr:.*]] = ashr exact i32 %[[memptr2]], 2
338*67e74705SXin Li // CHECK: %[[v7:.*]] = getelementptr inbounds i32, i32* %[[vbtable]], i32 %[[memptr2_shr]]
339*67e74705SXin Li // CHECK: %[[vbase_offs:.*]] = load i32, i32* %[[v7]]
340*67e74705SXin Li // CHECK: %[[base_adj:.*]] = getelementptr inbounds i8, i8* %[[vbptr]], i32 %[[vbase_offs]]
341*67e74705SXin Li //
342*67e74705SXin Li // CHECK: [[skip]]
343*67e74705SXin Li // CHECK: %[[new_base:.*]] = phi i8* [ %[[base]], %{{.*}} ], [ %[[base_adj]], %[[vadjust]] ]
344*67e74705SXin Li // CHECK: %[[offset:.*]] = getelementptr inbounds i8, i8* %[[new_base]], i32 %[[memptr0]]
345*67e74705SXin Li // CHECK: %[[v11:.*]] = bitcast i8* %[[offset]] to i32*
346*67e74705SXin Li // CHECK: %[[v12:.*]] = load i32, i32* %[[v11]]
347*67e74705SXin Li // CHECK: ret i32 %[[v12]]
348*67e74705SXin Li // CHECK: }
349*67e74705SXin Li }
350*67e74705SXin Li
callMemberPointerSingle(Single * o,void (Single::* memptr)())351*67e74705SXin Li void callMemberPointerSingle(Single *o, void (Single::*memptr)()) {
352*67e74705SXin Li (o->*memptr)();
353*67e74705SXin Li // Just look for an indirect thiscall.
354*67e74705SXin Li // CHECK: define void @"\01?callMemberPointerSingle@@{{.*}} {{.*}} {
355*67e74705SXin Li // CHECK: call x86_thiscallcc void %{{.*}}(%{{.*}} %{{.*}})
356*67e74705SXin Li // CHECK: ret void
357*67e74705SXin Li // CHECK: }
358*67e74705SXin Li
359*67e74705SXin Li // X64-LABEL: define void @"\01?callMemberPointerSingle@@
360*67e74705SXin Li // X64: (%struct.Single* %o, i8* %memptr)
361*67e74705SXin Li // X64: bitcast i8* %{{[^ ]*}} to void (%struct.Single*)*
362*67e74705SXin Li // X64: ret void
363*67e74705SXin Li }
364*67e74705SXin Li
callMemberPointerMultiple(Multiple * o,void (Multiple::* memptr)())365*67e74705SXin Li void callMemberPointerMultiple(Multiple *o, void (Multiple::*memptr)()) {
366*67e74705SXin Li (o->*memptr)();
367*67e74705SXin Li // CHECK: define void @"\01?callMemberPointerMultiple@@{{.*}} {
368*67e74705SXin Li // CHECK: %[[memptr0:.*]] = extractvalue { i8*, i32 } %{{.*}}, 0
369*67e74705SXin Li // CHECK: %[[memptr1:.*]] = extractvalue { i8*, i32 } %{{.*}}, 1
370*67e74705SXin Li // CHECK: %[[this_adjusted:.*]] = getelementptr inbounds i8, i8* %{{.*}}, i32 %[[memptr1]]
371*67e74705SXin Li // CHECK: %[[this:.*]] = bitcast i8* %[[this_adjusted]] to {{.*}}
372*67e74705SXin Li // CHECK: %[[fptr:.*]] = bitcast i8* %[[memptr0]] to {{.*}}
373*67e74705SXin Li // CHECK: call x86_thiscallcc void %[[fptr]](%{{.*}} %[[this]])
374*67e74705SXin Li // CHECK: ret void
375*67e74705SXin Li // CHECK: }
376*67e74705SXin Li }
377*67e74705SXin Li
callMemberPointerVirtualBase(Virtual * o,void (Virtual::* memptr)())378*67e74705SXin Li void callMemberPointerVirtualBase(Virtual *o, void (Virtual::*memptr)()) {
379*67e74705SXin Li (o->*memptr)();
380*67e74705SXin Li // This shares a lot with virtual data member pointers.
381*67e74705SXin Li // CHECK: define void @"\01?callMemberPointerVirtualBase@@{{.*}} {
382*67e74705SXin Li // CHECK: %[[memptr0:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 0
383*67e74705SXin Li // CHECK: %[[memptr1:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 1
384*67e74705SXin Li // CHECK: %[[memptr2:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 2
385*67e74705SXin Li // CHECK: %[[vbptr:.*]] = getelementptr inbounds i8, i8* %{{.*}}, i32 0
386*67e74705SXin Li // CHECK: %[[vbptr_a:.*]] = bitcast i8* %[[vbptr]] to i32**
387*67e74705SXin Li // CHECK: %[[vbtable:.*]] = load i32*, i32** %[[vbptr_a:.*]]
388*67e74705SXin Li // CHECK: %[[memptr2_shr:.*]] = ashr exact i32 %[[memptr2]], 2
389*67e74705SXin Li // CHECK: %[[v7:.*]] = getelementptr inbounds i32, i32* %[[vbtable]], i32 %[[memptr2_shr]]
390*67e74705SXin Li // CHECK: %[[vbase_offs:.*]] = load i32, i32* %[[v7]]
391*67e74705SXin Li // CHECK: %[[v10:.*]] = getelementptr inbounds i8, i8* %[[vbptr]], i32 %[[vbase_offs]]
392*67e74705SXin Li // CHECK: %[[this_adjusted:.*]] = getelementptr inbounds i8, i8* %[[v10]], i32 %[[memptr1]]
393*67e74705SXin Li // CHECK: %[[fptr:.*]] = bitcast i8* %[[memptr0]] to void ({{.*}})
394*67e74705SXin Li // CHECK: %[[this:.*]] = bitcast i8* %[[this_adjusted]] to {{.*}}
395*67e74705SXin Li // CHECK: call x86_thiscallcc void %[[fptr]](%{{.*}} %[[this]])
396*67e74705SXin Li // CHECK: ret void
397*67e74705SXin Li // CHECK: }
398*67e74705SXin Li }
399*67e74705SXin Li
compareSingleFunctionMemptr(void (Single::* l)(),void (Single::* r)())400*67e74705SXin Li bool compareSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
401*67e74705SXin Li return l == r;
402*67e74705SXin Li // Should only be one comparison here.
403*67e74705SXin Li // CHECK: define zeroext i1 @"\01?compareSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} {
404*67e74705SXin Li // CHECK-NOT: icmp
405*67e74705SXin Li // CHECK: %[[r:.*]] = icmp eq
406*67e74705SXin Li // CHECK-NOT: icmp
407*67e74705SXin Li // CHECK: ret i1 %[[r]]
408*67e74705SXin Li // CHECK: }
409*67e74705SXin Li
410*67e74705SXin Li // X64-LABEL: define zeroext i1 @"\01?compareSingleFunctionMemptr@@
411*67e74705SXin Li // X64: (i8* %{{[^,]*}}, i8* %{{[^)]*}})
412*67e74705SXin Li }
413*67e74705SXin Li
compareNeqSingleFunctionMemptr(void (Single::* l)(),void (Single::* r)())414*67e74705SXin Li bool compareNeqSingleFunctionMemptr(void (Single::*l)(), void (Single::*r)()) {
415*67e74705SXin Li return l != r;
416*67e74705SXin Li // Should only be one comparison here.
417*67e74705SXin Li // CHECK: define zeroext i1 @"\01?compareNeqSingleFunctionMemptr@@YA_NP8Single@@AEXXZ0@Z"{{.*}} {
418*67e74705SXin Li // CHECK-NOT: icmp
419*67e74705SXin Li // CHECK: %[[r:.*]] = icmp ne
420*67e74705SXin Li // CHECK-NOT: icmp
421*67e74705SXin Li // CHECK: ret i1 %[[r]]
422*67e74705SXin Li // CHECK: }
423*67e74705SXin Li }
424*67e74705SXin Li
unspecFuncMemptrEq(void (Unspecified::* l)(),void (Unspecified::* r)())425*67e74705SXin Li bool unspecFuncMemptrEq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
426*67e74705SXin Li return l == r;
427*67e74705SXin Li // CHECK: define zeroext i1 @"\01?unspecFuncMemptrEq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} {
428*67e74705SXin Li // CHECK: %[[lhs0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[l:.*]], 0
429*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r:.*]], 0
430*67e74705SXin Li // CHECK: %[[cmp0:.*]] = icmp eq i8* %[[lhs0]], %{{.*}}
431*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 1
432*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 1
433*67e74705SXin Li // CHECK: %[[cmp1:.*]] = icmp eq i32
434*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 2
435*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 2
436*67e74705SXin Li // CHECK: %[[cmp2:.*]] = icmp eq i32
437*67e74705SXin Li // CHECK: %[[res12:.*]] = and i1 %[[cmp1]], %[[cmp2]]
438*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 3
439*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 3
440*67e74705SXin Li // CHECK: %[[cmp3:.*]] = icmp eq i32
441*67e74705SXin Li // CHECK: %[[res123:.*]] = and i1 %[[res12]], %[[cmp3]]
442*67e74705SXin Li // CHECK: %[[iszero:.*]] = icmp eq i8* %[[lhs0]], null
443*67e74705SXin Li // CHECK: %[[bits_or_null:.*]] = or i1 %[[res123]], %[[iszero]]
444*67e74705SXin Li // CHECK: %{{.*}} = and i1 %[[bits_or_null]], %[[cmp0]]
445*67e74705SXin Li // CHECK: ret i1 %{{.*}}
446*67e74705SXin Li // CHECK: }
447*67e74705SXin Li
448*67e74705SXin Li // X64-LABEL: define zeroext i1 @"\01?unspecFuncMemptrEq@@
449*67e74705SXin Li // X64: ({ i8*, i32, i32, i32 }*, { i8*, i32, i32, i32 }*)
450*67e74705SXin Li }
451*67e74705SXin Li
unspecFuncMemptrNeq(void (Unspecified::* l)(),void (Unspecified::* r)())452*67e74705SXin Li bool unspecFuncMemptrNeq(void (Unspecified::*l)(), void (Unspecified::*r)()) {
453*67e74705SXin Li return l != r;
454*67e74705SXin Li // CHECK: define zeroext i1 @"\01?unspecFuncMemptrNeq@@YA_NP8Unspecified@@AEXXZ0@Z"{{.*}} {
455*67e74705SXin Li // CHECK: %[[lhs0:.*]] = extractvalue { i8*, i32, i32, i32 } %[[l:.*]], 0
456*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r:.*]], 0
457*67e74705SXin Li // CHECK: %[[cmp0:.*]] = icmp ne i8* %[[lhs0]], %{{.*}}
458*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 1
459*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 1
460*67e74705SXin Li // CHECK: %[[cmp1:.*]] = icmp ne i32
461*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 2
462*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 2
463*67e74705SXin Li // CHECK: %[[cmp2:.*]] = icmp ne i32
464*67e74705SXin Li // CHECK: %[[res12:.*]] = or i1 %[[cmp1]], %[[cmp2]]
465*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[l]], 3
466*67e74705SXin Li // CHECK: %{{.*}} = extractvalue { i8*, i32, i32, i32 } %[[r]], 3
467*67e74705SXin Li // CHECK: %[[cmp3:.*]] = icmp ne i32
468*67e74705SXin Li // CHECK: %[[res123:.*]] = or i1 %[[res12]], %[[cmp3]]
469*67e74705SXin Li // CHECK: %[[iszero:.*]] = icmp ne i8* %[[lhs0]], null
470*67e74705SXin Li // CHECK: %[[bits_or_null:.*]] = and i1 %[[res123]], %[[iszero]]
471*67e74705SXin Li // CHECK: %{{.*}} = or i1 %[[bits_or_null]], %[[cmp0]]
472*67e74705SXin Li // CHECK: ret i1 %{{.*}}
473*67e74705SXin Li // CHECK: }
474*67e74705SXin Li }
475*67e74705SXin Li
unspecDataMemptrEq(int Unspecified::* l,int Unspecified::* r)476*67e74705SXin Li bool unspecDataMemptrEq(int Unspecified::*l, int Unspecified::*r) {
477*67e74705SXin Li return l == r;
478*67e74705SXin Li // CHECK: define zeroext i1 @"\01?unspecDataMemptrEq@@YA_NPQUnspecified@@H0@Z"{{.*}} {
479*67e74705SXin Li // CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 0
480*67e74705SXin Li // CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 0
481*67e74705SXin Li // CHECK: icmp eq i32
482*67e74705SXin Li // CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 1
483*67e74705SXin Li // CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 1
484*67e74705SXin Li // CHECK: icmp eq i32
485*67e74705SXin Li // CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 2
486*67e74705SXin Li // CHECK: extractvalue { i32, i32, i32 } %{{.*}}, 2
487*67e74705SXin Li // CHECK: icmp eq i32
488*67e74705SXin Li // CHECK: and i1
489*67e74705SXin Li // CHECK: and i1
490*67e74705SXin Li // CHECK: ret i1
491*67e74705SXin Li // CHECK: }
492*67e74705SXin Li
493*67e74705SXin Li // X64-LABEL: define zeroext i1 @"\01?unspecDataMemptrEq@@
494*67e74705SXin Li // X64: ({ i32, i32, i32 }*, { i32, i32, i32 }*)
495*67e74705SXin Li }
496*67e74705SXin Li
convertB2FuncToMultiple(void (B2::* mp)())497*67e74705SXin Li void (Multiple::*convertB2FuncToMultiple(void (B2::*mp)()))() {
498*67e74705SXin Li return mp;
499*67e74705SXin Li // CHECK: define i64 @"\01?convertB2FuncToMultiple@@YAP8Multiple@@AEXXZP8B2@@AEXXZ@Z"{{.*}} {
500*67e74705SXin Li // CHECK: store
501*67e74705SXin Li // CHECK: %[[mp:.*]] = load i8*, i8** %{{.*}}, align 4
502*67e74705SXin Li // CHECK: icmp ne i8* %[[mp]], null
503*67e74705SXin Li // CHECK: br i1 %{{.*}} label %{{.*}}, label %{{.*}}
504*67e74705SXin Li //
505*67e74705SXin Li // memptr.convert: ; preds = %entry
506*67e74705SXin Li // CHECK: insertvalue { i8*, i32 } undef, i8* %[[mp]], 0
507*67e74705SXin Li // CHECK: insertvalue { i8*, i32 } %{{.*}}, i32 4, 1
508*67e74705SXin Li // CHECK: br label
509*67e74705SXin Li //
510*67e74705SXin Li // memptr.converted: ; preds = %memptr.convert, %entry
511*67e74705SXin Li // CHECK: phi { i8*, i32 } [ zeroinitializer, %{{.*}} ], [ {{.*}} ]
512*67e74705SXin Li // CHECK: }
513*67e74705SXin Li }
514*67e74705SXin Li
convertMultipleFuncToB2(void (Multiple::* mp)())515*67e74705SXin Li void (B2::*convertMultipleFuncToB2(void (Multiple::*mp)()))() {
516*67e74705SXin Li // FIXME: cl emits warning C4407 on this code because of the representation
517*67e74705SXin Li // change. We might want to do the same.
518*67e74705SXin Li return static_cast<void (B2::*)()>(mp);
519*67e74705SXin Li // FIXME: We should return i8* instead of i32 here. The ptrtoint cast prevents
520*67e74705SXin Li // LLVM from optimizing away the branch. This is likely a bug in
521*67e74705SXin Li // lib/CodeGen/TargetInfo.cpp with how we classify memptr types for returns.
522*67e74705SXin Li //
523*67e74705SXin Li // CHECK: define i32 @"\01?convertMultipleFuncToB2@@YAP8B2@@AEXXZP8Multiple@@AEXXZ@Z"{{.*}} {
524*67e74705SXin Li // CHECK: store
525*67e74705SXin Li // CHECK: %[[src:.*]] = load { i8*, i32 }, { i8*, i32 }* %{{.*}}, align 4
526*67e74705SXin Li // CHECK: extractvalue { i8*, i32 } %[[src]], 0
527*67e74705SXin Li // CHECK: icmp ne i8* %{{.*}}, null
528*67e74705SXin Li // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
529*67e74705SXin Li //
530*67e74705SXin Li // memptr.convert: ; preds = %entry
531*67e74705SXin Li // CHECK: %[[fp:.*]] = extractvalue { i8*, i32 } %[[src]], 0
532*67e74705SXin Li // CHECK: br label
533*67e74705SXin Li //
534*67e74705SXin Li // memptr.converted: ; preds = %memptr.convert, %entry
535*67e74705SXin Li // CHECK: phi i8* [ null, %{{.*}} ], [ %[[fp]], %{{.*}} ]
536*67e74705SXin Li // CHECK: }
537*67e74705SXin Li }
538*67e74705SXin Li
539*67e74705SXin Li namespace Test1 {
540*67e74705SXin Li
541*67e74705SXin Li struct A { int a; };
542*67e74705SXin Li struct B { int b; };
543*67e74705SXin Li struct C : virtual A { int c; };
544*67e74705SXin Li struct D : B, C { int d; };
545*67e74705SXin Li
convertCToD(void (C::* mp)())546*67e74705SXin Li void (D::*convertCToD(void (C::*mp)()))() {
547*67e74705SXin Li return mp;
548*67e74705SXin Li // CHECK: define void @"\01?convertCToD@Test1@@YAP8D@1@AEXXZP8C@1@AEXXZ@Z"{{.*}} {
549*67e74705SXin Li // CHECK: store
550*67e74705SXin Li // CHECK: load { i8*, i32, i32 }, { i8*, i32, i32 }* %{{.*}}, align 4
551*67e74705SXin Li // CHECK: extractvalue { i8*, i32, i32 } %{{.*}}, 0
552*67e74705SXin Li // CHECK: icmp ne i8* %{{.*}}, null
553*67e74705SXin Li // CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
554*67e74705SXin Li //
555*67e74705SXin Li // memptr.convert: ; preds = %entry
556*67e74705SXin Li // CHECK: extractvalue { i8*, i32, i32 } %{{.*}}, 0
557*67e74705SXin Li // CHECK: %[[nvoff:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 1
558*67e74705SXin Li // CHECK: %[[vbidx:.*]] = extractvalue { i8*, i32, i32 } %{{.*}}, 2
559*67e74705SXin Li // CHECK: %[[is_nvbase:.*]] = icmp eq i32 %[[vbidx]], 0
560*67e74705SXin Li // CHECK: %[[nv_disp:.*]] = add nsw i32 %[[nvoff]], 4
561*67e74705SXin Li // CHECK: %[[nv_adj:.*]] = select i1 %[[is_nvbase]], i32 %[[nv_disp]], i32 0
562*67e74705SXin Li // CHECK: %[[dst_adj:.*]] = select i1 %[[is_nvbase]], i32 4, i32 0
563*67e74705SXin Li // CHECK: %[[adj:.*]] = sub nsw i32 %[[nv_adj]], %[[dst_adj]]
564*67e74705SXin Li // CHECK: insertvalue { i8*, i32, i32 } undef, i8* {{.*}}, 0
565*67e74705SXin Li // CHECK: insertvalue { i8*, i32, i32 } {{.*}}, i32 %[[adj]], 1
566*67e74705SXin Li // CHECK: insertvalue { i8*, i32, i32 } {{.*}}, i32 {{.*}}, 2
567*67e74705SXin Li // CHECK: br label
568*67e74705SXin Li //
569*67e74705SXin Li // memptr.converted: ; preds = %memptr.convert, %entry
570*67e74705SXin Li // CHECK: phi { i8*, i32, i32 } [ { i8* null, i32 0, i32 -1 }, {{.*}} ], [ {{.*}} ]
571*67e74705SXin Li // CHECK: }
572*67e74705SXin Li }
573*67e74705SXin Li
574*67e74705SXin Li }
575*67e74705SXin Li
576*67e74705SXin Li namespace Test2 {
577*67e74705SXin Li // Test that we dynamically convert between different null reps.
578*67e74705SXin Li
579*67e74705SXin Li struct A { int a; };
580*67e74705SXin Li struct B : A { int b; };
581*67e74705SXin Li struct C : A {
582*67e74705SXin Li int c;
583*67e74705SXin Li virtual void hasVfPtr();
584*67e74705SXin Li };
585*67e74705SXin Li
reinterpret(int B::* mp)586*67e74705SXin Li int A::*reinterpret(int B::*mp) {
587*67e74705SXin Li return reinterpret_cast<int A::*>(mp);
588*67e74705SXin Li // CHECK: define i32 @"\01?reinterpret@Test2@@YAPQA@1@HPQB@1@H@Z"{{.*}} {
589*67e74705SXin Li // CHECK-NOT: select
590*67e74705SXin Li // CHECK: ret i32
591*67e74705SXin Li // CHECK: }
592*67e74705SXin Li }
593*67e74705SXin Li
reinterpret(int C::* mp)594*67e74705SXin Li int A::*reinterpret(int C::*mp) {
595*67e74705SXin Li return reinterpret_cast<int A::*>(mp);
596*67e74705SXin Li // CHECK: define i32 @"\01?reinterpret@Test2@@YAPQA@1@HPQC@1@H@Z"{{.*}} {
597*67e74705SXin Li // CHECK: %[[mp:.*]] = load i32, i32*
598*67e74705SXin Li // CHECK: %[[cmp:.*]] = icmp ne i32 %[[mp]], 0
599*67e74705SXin Li // CHECK: select i1 %[[cmp]], i32 %[[mp]], i32 -1
600*67e74705SXin Li // CHECK: }
601*67e74705SXin Li }
602*67e74705SXin Li
603*67e74705SXin Li }
604*67e74705SXin Li
605*67e74705SXin Li namespace Test3 {
606*67e74705SXin Li // Make sure we cast 'this' to i8* before using GEP.
607*67e74705SXin Li
608*67e74705SXin Li struct A {
609*67e74705SXin Li int a;
610*67e74705SXin Li int b;
611*67e74705SXin Li };
612*67e74705SXin Li
load_data(A * a,int A::* mp)613*67e74705SXin Li int *load_data(A *a, int A::*mp) {
614*67e74705SXin Li return &(a->*mp);
615*67e74705SXin Li // CHECK-LABEL: define i32* @"\01?load_data@Test3@@YAPAHPAUA@1@PQ21@H@Z"{{.*}} {
616*67e74705SXin Li // CHECK: %[[a:.*]] = load %"struct.Test3::A"*, %"struct.Test3::A"** %{{.*}}, align 4
617*67e74705SXin Li // CHECK: %[[mp:.*]] = load i32, i32* %{{.*}}, align 4
618*67e74705SXin Li // CHECK: %[[a_i8:.*]] = bitcast %"struct.Test3::A"* %[[a]] to i8*
619*67e74705SXin Li // CHECK: getelementptr inbounds i8, i8* %[[a_i8]], i32 %[[mp]]
620*67e74705SXin Li // CHECK: }
621*67e74705SXin Li }
622*67e74705SXin Li
623*67e74705SXin Li }
624*67e74705SXin Li
625*67e74705SXin Li namespace Test4 {
626*67e74705SXin Li
627*67e74705SXin Li struct A { virtual void f(); };
628*67e74705SXin Li struct B { virtual void g(); };
629*67e74705SXin Li struct C : A, B { virtual void g(); };
630*67e74705SXin Li
getmp()631*67e74705SXin Li void (C::*getmp())() {
632*67e74705SXin Li return &C::g;
633*67e74705SXin Li }
634*67e74705SXin Li // CHECK-LABEL: define i64 @"\01?getmp@Test4@@YAP8C@1@AEXXZXZ"()
635*67e74705SXin Li // CHECK: store { i8*, i32 } { i8* bitcast (void (%"struct.Test4::C"*, ...)* @"\01??_9C@Test4@@$BA@AE" to i8*), i32 4 }, { i8*, i32 }* %{{.*}}
636*67e74705SXin Li //
637*67e74705SXin Li
638*67e74705SXin Li // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@Test4@@$BA@AE"(%"struct.Test4::C"* %this, ...) {{.*}} comdat
639*67e74705SXin Li // CHECK-NOT: getelementptr
640*67e74705SXin Li // CHECK: load void (%"struct.Test4::C"*, ...)**, void (%"struct.Test4::C"*, ...)*** %{{.*}}
641*67e74705SXin Li // CHECK: getelementptr inbounds void (%"struct.Test4::C"*, ...)*, void (%"struct.Test4::C"*, ...)** %{{.*}}, i64 0
642*67e74705SXin Li // CHECK-NOT: getelementptr
643*67e74705SXin Li // CHECK: musttail call x86_thiscallcc void (%"struct.Test4::C"*, ...) %
644*67e74705SXin Li
645*67e74705SXin Li }
646*67e74705SXin Li
647*67e74705SXin Li namespace pr20007 {
648*67e74705SXin Li struct A {
649*67e74705SXin Li void f();
650*67e74705SXin Li void f(int);
651*67e74705SXin Li };
652*67e74705SXin Li struct B : public A {};
test()653*67e74705SXin Li void test() { void (B::*a)() = &B::f; }
654*67e74705SXin Li // CHECK-LABEL: define void @"\01?test@pr20007@@YAXXZ"
655*67e74705SXin Li // CHECK: store i8* bitcast (void (%"struct.pr20007::A"*)* @"\01?f@A@pr20007@@QAEXXZ" to i8*)
656*67e74705SXin Li }
657*67e74705SXin Li
658*67e74705SXin Li namespace pr20007_kw {
659*67e74705SXin Li struct A {
660*67e74705SXin Li void f();
661*67e74705SXin Li void f(int);
662*67e74705SXin Li };
663*67e74705SXin Li struct __single_inheritance B;
664*67e74705SXin Li struct B : public A {};
test()665*67e74705SXin Li void test() { void (B::*a)() = &B::f; }
666*67e74705SXin Li // CHECK-LABEL: define void @"\01?test@pr20007_kw@@YAXXZ"
667*67e74705SXin Li // CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"\01?f@A@pr20007_kw@@QAEXXZ" to i8*)
668*67e74705SXin Li }
669*67e74705SXin Li
670*67e74705SXin Li namespace pr20007_pragma {
671*67e74705SXin Li struct A {
672*67e74705SXin Li void f();
673*67e74705SXin Li void f(int);
674*67e74705SXin Li };
675*67e74705SXin Li struct B : public A {};
test()676*67e74705SXin Li void test() { (void)(void (B::*)()) &B::f; }
677*67e74705SXin Li #pragma pointers_to_members(full_generality, virtual_inheritance)
678*67e74705SXin Li static_assert(sizeof(int B::*) == 4, "");
679*67e74705SXin Li static_assert(sizeof(int A::*) == 4, "");
680*67e74705SXin Li #pragma pointers_to_members(best_case)
681*67e74705SXin Li // CHECK-LABEL: define void @"\01?test@pr20007_pragma@@YAXXZ"
682*67e74705SXin Li }
683*67e74705SXin Li
684*67e74705SXin Li namespace pr20007_pragma2 {
685*67e74705SXin Li struct A {
686*67e74705SXin Li };
687*67e74705SXin Li struct B : public A {
688*67e74705SXin Li void f();
689*67e74705SXin Li };
test()690*67e74705SXin Li void test() { (void)&B::f; }
691*67e74705SXin Li #pragma pointers_to_members(full_generality, virtual_inheritance)
692*67e74705SXin Li static_assert(sizeof(int B::*) == 4, "");
693*67e74705SXin Li static_assert(sizeof(int A::*) == 12, "");
694*67e74705SXin Li #pragma pointers_to_members(best_case)
695*67e74705SXin Li // CHECK-LABEL: define void @"\01?test@pr20007_pragma2@@YAXXZ"
696*67e74705SXin Li }
697*67e74705SXin Li
698*67e74705SXin Li namespace pr23823 {
699*67e74705SXin Li struct Base { void Method(); };
700*67e74705SXin Li struct Child : Base {};
701*67e74705SXin Li void use(void (Child::*const &)());
f()702*67e74705SXin Li void f() { use(&Child::Method); }
703*67e74705SXin Li #pragma pointers_to_members(full_generality, virtual_inheritance)
704*67e74705SXin Li static_assert(sizeof(int Base::*) == 4, "");
705*67e74705SXin Li static_assert(sizeof(int Child::*) == 4, "");
706*67e74705SXin Li #pragma pointers_to_members(best_case)
707*67e74705SXin Li }
708*67e74705SXin Li
709*67e74705SXin Li namespace pr19987 {
710*67e74705SXin Li template <typename T>
711*67e74705SXin Li struct S {
712*67e74705SXin Li int T::*x;
713*67e74705SXin Li };
714*67e74705SXin Li
715*67e74705SXin Li struct U : S<U> {};
716*67e74705SXin Li
717*67e74705SXin Li static_assert(sizeof(S<U>::x) == 12, "");
718*67e74705SXin Li }
719*67e74705SXin Li
720*67e74705SXin Li #else
721*67e74705SXin Li struct __virtual_inheritance A;
722*67e74705SXin Li #ifdef MEMFUN
foo(A * a,int (A::* mp)())723*67e74705SXin Li int foo(A *a, int (A::*mp)()) {
724*67e74705SXin Li return (a->*mp)(); // expected-error{{requires a complete class type}}
725*67e74705SXin Li }
726*67e74705SXin Li #else
foo(A * a,int A::* mp)727*67e74705SXin Li int foo(A *a, int A::*mp) {
728*67e74705SXin Li return a->*mp; // expected-error{{requires a complete class type}}
729*67e74705SXin Li }
730*67e74705SXin Li #endif
731*67e74705SXin Li #endif
732*67e74705SXin Li
733*67e74705SXin Li namespace pr23878 {
734*67e74705SXin Li struct A { virtual void g(); };
735*67e74705SXin Li struct B { virtual void f(); };
736*67e74705SXin Li struct C : virtual B { void f(); };
737*67e74705SXin Li struct D : A, C {};
738*67e74705SXin Li
739*67e74705SXin Li typedef void (D::*DMemPtrTy)();
740*67e74705SXin Li
741*67e74705SXin Li // CHECK-LABEL: define void @"\01?get_memptr@pr23878@@YAP8D@1@AEXXZXZ"
742*67e74705SXin Li // CHECK: @"\01??_9C@pr23878@@$BA@AE" to i8*), i32 0, i32 4
get_memptr()743*67e74705SXin Li DMemPtrTy get_memptr() { return &D::f; }
744*67e74705SXin Li }
745*67e74705SXin Li
746*67e74705SXin Li class C {};
747*67e74705SXin Li
748*67e74705SXin Li typedef void (C::*f)();
749*67e74705SXin Li
750*67e74705SXin Li class CA : public C {
751*67e74705SXin Li public:
752*67e74705SXin Li void OnHelp(void);
753*67e74705SXin Li int OnHelp(int);
754*67e74705SXin Li };
755*67e74705SXin Li
756*67e74705SXin Li // CHECK-LABEL: foo_fun
foo_fun()757*67e74705SXin Li void foo_fun() {
758*67e74705SXin Li // CHECK: store i8* bitcast (void (%class.CA*)* @"\01?OnHelp@CA@@QAEXXZ" to i8*), i8**
759*67e74705SXin Li f func = (f)&CA::OnHelp;
760*67e74705SXin Li }
761*67e74705SXin Li namespace PR24703 {
762*67e74705SXin Li struct S;
763*67e74705SXin Li
f(int S::* & p)764*67e74705SXin Li void f(int S::*&p) {}
765*67e74705SXin Li // CHECK-LABEL: define void @"\01?f@PR24703@@YAXAAPQS@1@H@Z"(
766*67e74705SXin Li }
767*67e74705SXin Li
768*67e74705SXin Li namespace ReferenceToMPTWithIncompleteClass {
769*67e74705SXin Li struct S;
770*67e74705SXin Li struct J;
771*67e74705SXin Li struct K;
772*67e74705SXin Li extern K *k;
773*67e74705SXin Li
774*67e74705SXin Li // CHECK-LABEL: @"\01?f@ReferenceToMPTWithIncompleteClass@@YAIAAPQS@1@H@Z"(
775*67e74705SXin Li // CHECK: ret i32 12
f(int S::* & p)776*67e74705SXin Li unsigned f(int S::*&p) { return sizeof p; }
777*67e74705SXin Li
778*67e74705SXin Li // CHECK-LABEL: @"\01?g@ReferenceToMPTWithIncompleteClass@@YA_NAAPQJ@1@H0@Z"(
g(int J::* & p,int J::* & q)779*67e74705SXin Li bool g(int J::*&p, int J::*&q) { return p == q; }
780*67e74705SXin Li
781*67e74705SXin Li // CHECK-LABEL: @"\01?h@ReferenceToMPTWithIncompleteClass@@YAHAAPQK@1@H@Z"(
h(int K::* & p)782*67e74705SXin Li int h(int K::*&p) { return k->*p; }
783*67e74705SXin Li }
784*67e74705SXin Li
785*67e74705SXin Li namespace PMFInTemplateArgument {
786*67e74705SXin Li template <class C, int (C::*M)(int)>
787*67e74705SXin Li void JSMethod();
788*67e74705SXin Li class A {
789*67e74705SXin Li int printd(int);
790*67e74705SXin Li void printd();
791*67e74705SXin Li };
printd()792*67e74705SXin Li void A::printd() { JSMethod<A, &A::printd>(); }
793*67e74705SXin Li // CHECK-LABEL: @"\01??$JSMethod@VA@PMFInTemplateArgument@@$1?printd@12@AAEHH@Z@PMFInTemplateArgument@@YAXXZ"(
794*67e74705SXin Li }
795