xref: /aosp_15_r20/external/clang/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -mconstructor-aliases -triple=i386-pc-win32 | FileCheck %s
2*67e74705SXin Li 
3*67e74705SXin Li struct Left {
4*67e74705SXin Li   virtual void left();
5*67e74705SXin Li };
6*67e74705SXin Li 
7*67e74705SXin Li struct Right {
8*67e74705SXin Li   virtual void right();
9*67e74705SXin Li };
10*67e74705SXin Li 
11*67e74705SXin Li struct ChildNoOverride : Left, Right {
12*67e74705SXin Li };
13*67e74705SXin Li 
14*67e74705SXin Li struct ChildOverride : Left, Right {
15*67e74705SXin Li   virtual void left();
16*67e74705SXin Li   virtual void right();
17*67e74705SXin Li };
18*67e74705SXin Li 
19*67e74705SXin Li extern "C" void foo(void *);
20*67e74705SXin Li 
call_left_no_override(ChildNoOverride * child)21*67e74705SXin Li void call_left_no_override(ChildNoOverride *child) {
22*67e74705SXin Li // CHECK: define void @"\01?call_left_no_override
23*67e74705SXin Li // CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
24*67e74705SXin Li 
25*67e74705SXin Li   child->left();
26*67e74705SXin Li // Only need to cast 'this' to Left*.
27*67e74705SXin Li // CHECK: %[[LEFT:.*]] = bitcast %struct.ChildNoOverride* %[[CHILD]] to %struct.Left*
28*67e74705SXin Li // CHECK: %[[VFPTR:.*]] = bitcast %struct.Left* %[[LEFT]] to void (%struct.Left*)***
29*67e74705SXin Li // CHECK: %[[VFTABLE:.*]] = load void (%struct.Left*)**, void (%struct.Left*)*** %[[VFPTR]]
30*67e74705SXin Li // CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.Left*)*, void (%struct.Left*)** %[[VFTABLE]], i64 0
31*67e74705SXin Li // CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.Left*)*, void (%struct.Left*)** %[[VFUN]]
32*67e74705SXin Li // CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.Left* %[[LEFT]])
33*67e74705SXin Li // CHECK: ret
34*67e74705SXin Li }
35*67e74705SXin Li 
left()36*67e74705SXin Li void ChildOverride::left() {
37*67e74705SXin Li // CHECK: define x86_thiscallcc void @"\01?left@ChildOverride@@UAEXXZ"(%struct.ChildOverride* %[[THIS:.*]])
38*67e74705SXin Li //
39*67e74705SXin Li // No need to adjust 'this' as the ChildOverride's layout begins with Left.
40*67e74705SXin Li // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.ChildOverride*, align 4
41*67e74705SXin Li // CHECK: store %struct.ChildOverride* %[[THIS]], %struct.ChildOverride** %[[THIS_ADDR]], align 4
42*67e74705SXin Li 
43*67e74705SXin Li   foo(this);
44*67e74705SXin Li // CHECK: %[[THIS:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_ADDR]]
45*67e74705SXin Li // CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
46*67e74705SXin Li // CHECK: call void @foo(i8* %[[THIS_i8]])
47*67e74705SXin Li // CHECK: ret
48*67e74705SXin Li }
49*67e74705SXin Li 
call_left_override(ChildOverride * child)50*67e74705SXin Li void call_left_override(ChildOverride *child) {
51*67e74705SXin Li // CHECK: define void @"\01?call_left_override
52*67e74705SXin Li // CHECK: %[[CHILD:.*]] = load %struct.ChildOverride
53*67e74705SXin Li 
54*67e74705SXin Li   child->left();
55*67e74705SXin Li // CHECK: %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to void (%struct.ChildOverride*)***
56*67e74705SXin Li // CHECK: %[[VFTABLE:.*]] = load void (%struct.ChildOverride*)**, void (%struct.ChildOverride*)*** %[[VFPTR]]
57*67e74705SXin Li // CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.ChildOverride*)*, void (%struct.ChildOverride*)** %[[VFTABLE]], i64 0
58*67e74705SXin Li // CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.ChildOverride*)*, void (%struct.ChildOverride*)** %[[VFUN]]
59*67e74705SXin Li //
60*67e74705SXin Li // CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.ChildOverride* %[[CHILD]])
61*67e74705SXin Li // CHECK: ret
62*67e74705SXin Li }
63*67e74705SXin Li 
call_right_no_override(ChildNoOverride * child)64*67e74705SXin Li void call_right_no_override(ChildNoOverride *child) {
65*67e74705SXin Li // CHECK: define void @"\01?call_right_no_override
66*67e74705SXin Li // CHECK: %[[CHILD:.*]] = load %struct.ChildNoOverride
67*67e74705SXin Li 
68*67e74705SXin Li   child->right();
69*67e74705SXin Li // When calling a right base's virtual method, one needs to adjust 'this' at
70*67e74705SXin Li // the caller site.
71*67e74705SXin Li //
72*67e74705SXin Li // CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildNoOverride* %[[CHILD]] to i8*
73*67e74705SXin Li // CHECK: %[[RIGHT_i8:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
74*67e74705SXin Li // CHECK: %[[RIGHT:.*]] = bitcast i8* %[[RIGHT_i8]] to %struct.Right*
75*67e74705SXin Li //
76*67e74705SXin Li // CHECK: %[[VFPTR:.*]] = bitcast %struct.Right* %[[RIGHT]] to void (%struct.Right*)***
77*67e74705SXin Li // CHECK: %[[VFTABLE:.*]] = load void (%struct.Right*)**, void (%struct.Right*)*** %[[VFPTR]]
78*67e74705SXin Li // CHECK: %[[VFUN:.*]] = getelementptr inbounds void (%struct.Right*)*, void (%struct.Right*)** %[[VFTABLE]], i64 0
79*67e74705SXin Li // CHECK: %[[VFUN_VALUE:.*]] = load void (%struct.Right*)*, void (%struct.Right*)** %[[VFUN]]
80*67e74705SXin Li // CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](%struct.Right* %[[RIGHT]])
81*67e74705SXin Li // CHECK: ret
82*67e74705SXin Li }
83*67e74705SXin Li 
right()84*67e74705SXin Li void ChildOverride::right() {
85*67e74705SXin Li // CHECK: define x86_thiscallcc void @"\01?right@ChildOverride@@UAEXXZ"(i8*
86*67e74705SXin Li //
87*67e74705SXin Li // ChildOverride::right gets 'this' cast to Right* in ECX (i.e. this+4) so we
88*67e74705SXin Li // need to adjust 'this' before use.
89*67e74705SXin Li //
90*67e74705SXin Li // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.ChildOverride*, align 4
91*67e74705SXin Li // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX:.*]], i32 -4
92*67e74705SXin Li // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.ChildOverride*
93*67e74705SXin Li // CHECK: store %struct.ChildOverride* %[[THIS]], %struct.ChildOverride** %[[THIS_ADDR]], align 4
94*67e74705SXin Li 
95*67e74705SXin Li   foo(this);
96*67e74705SXin Li // CHECK: %[[THIS:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_ADDR]]
97*67e74705SXin Li // CHECK: %[[THIS_PARAM:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
98*67e74705SXin Li // CHECK: call void @foo(i8* %[[THIS_PARAM]])
99*67e74705SXin Li // CHECK: ret
100*67e74705SXin Li }
101*67e74705SXin Li 
call_right_override(ChildOverride * child)102*67e74705SXin Li void call_right_override(ChildOverride *child) {
103*67e74705SXin Li // CHECK: define void @"\01?call_right_override
104*67e74705SXin Li // CHECK: %[[CHILD:.*]] = load %struct.ChildOverride
105*67e74705SXin Li 
106*67e74705SXin Li   child->right();
107*67e74705SXin Li // When calling a right child's virtual method, one needs to adjust 'this' at
108*67e74705SXin Li // the caller site.
109*67e74705SXin Li //
110*67e74705SXin Li // CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to i8*
111*67e74705SXin Li //
112*67e74705SXin Li // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
113*67e74705SXin Li // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to void (i8*)***
114*67e74705SXin Li // CHECK: %[[VFTABLE:.*]] = load void (i8*)**, void (i8*)*** %[[VFPTR]]
115*67e74705SXin Li // CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)*, void (i8*)** %[[VFTABLE]], i64 0
116*67e74705SXin Li // CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)*, void (i8*)** %[[VFUN]]
117*67e74705SXin Li //
118*67e74705SXin Li // CHECK: %[[CHILD_i8:.*]] = bitcast %struct.ChildOverride* %[[CHILD]] to i8*
119*67e74705SXin Li // CHECK: %[[RIGHT:.*]] = getelementptr inbounds i8, i8* %[[CHILD_i8]], i32 4
120*67e74705SXin Li //
121*67e74705SXin Li // CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* %[[RIGHT]])
122*67e74705SXin Li // CHECK: ret
123*67e74705SXin Li }
124*67e74705SXin Li 
125*67e74705SXin Li struct GrandchildOverride : ChildOverride {
126*67e74705SXin Li   virtual void right();
127*67e74705SXin Li };
128*67e74705SXin Li 
right()129*67e74705SXin Li void GrandchildOverride::right() {
130*67e74705SXin Li // CHECK: define x86_thiscallcc void @"\01?right@GrandchildOverride@@UAEXXZ"(i8*
131*67e74705SXin Li //
132*67e74705SXin Li // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.GrandchildOverride*, align 4
133*67e74705SXin Li // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX:.*]], i32 -4
134*67e74705SXin Li // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.GrandchildOverride*
135*67e74705SXin Li // CHECK: store %struct.GrandchildOverride* %[[THIS]], %struct.GrandchildOverride** %[[THIS_ADDR]], align 4
136*67e74705SXin Li 
137*67e74705SXin Li   foo(this);
138*67e74705SXin Li // CHECK: %[[THIS:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** %[[THIS_ADDR]]
139*67e74705SXin Li // CHECK: %[[THIS_PARAM:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8*
140*67e74705SXin Li // CHECK: call void @foo(i8* %[[THIS_PARAM]])
141*67e74705SXin Li // CHECK: ret
142*67e74705SXin Li }
143*67e74705SXin Li 
call_grandchild_right(GrandchildOverride * obj)144*67e74705SXin Li void call_grandchild_right(GrandchildOverride *obj) {
145*67e74705SXin Li   // Just make sure we don't crash.
146*67e74705SXin Li   obj->right();
147*67e74705SXin Li }
148*67e74705SXin Li 
emit_ctors()149*67e74705SXin Li void emit_ctors() {
150*67e74705SXin Li   Left l;
151*67e74705SXin Li   // CHECK: define {{.*}} @"\01??0Left@@QAE@XZ"
152*67e74705SXin Li   // CHECK-NOT: getelementptr
153*67e74705SXin Li   // CHECK:   store i32 (...)** bitcast ([1 x i8*]* @"\01??_7Left@@6B@" to i32 (...)**)
154*67e74705SXin Li   // CHECK: ret
155*67e74705SXin Li 
156*67e74705SXin Li   Right r;
157*67e74705SXin Li   // CHECK: define {{.*}} @"\01??0Right@@QAE@XZ"
158*67e74705SXin Li   // CHECK-NOT: getelementptr
159*67e74705SXin Li   // CHECK:   store i32 (...)** bitcast ([1 x i8*]* @"\01??_7Right@@6B@" to i32 (...)**)
160*67e74705SXin Li   // CHECK: ret
161*67e74705SXin Li 
162*67e74705SXin Li   ChildOverride co;
163*67e74705SXin Li   // CHECK: define {{.*}} @"\01??0ChildOverride@@QAE@XZ"
164*67e74705SXin Li   // CHECK:   %[[THIS:.*]] = load %struct.ChildOverride*, %struct.ChildOverride**
165*67e74705SXin Li   // CHECK:   %[[VFPTR:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i32 (...)***
166*67e74705SXin Li   // CHECK:   store i32 (...)** bitcast ([1 x i8*]* @"\01??_7ChildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
167*67e74705SXin Li   // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS]] to i8*
168*67e74705SXin Li   // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 4
169*67e74705SXin Li   // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
170*67e74705SXin Li   // CHECK:   store i32 (...)** bitcast ([1 x i8*]* @"\01??_7ChildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
171*67e74705SXin Li   // CHECK: ret
172*67e74705SXin Li 
173*67e74705SXin Li   GrandchildOverride gc;
174*67e74705SXin Li   // CHECK: define {{.*}} @"\01??0GrandchildOverride@@QAE@XZ"
175*67e74705SXin Li   // CHECK:   %[[THIS:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride**
176*67e74705SXin Li   // CHECK:   %[[VFPTR:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i32 (...)***
177*67e74705SXin Li   // CHECK:   store i32 (...)** bitcast ([1 x i8*]* @"\01??_7GrandchildOverride@@6BLeft@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
178*67e74705SXin Li   // CHECK:   %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS]] to i8*
179*67e74705SXin Li   // CHECK:   %[[VFPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 4
180*67e74705SXin Li   // CHECK:   %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to i32 (...)***
181*67e74705SXin Li   // CHECK:   store i32 (...)** bitcast ([1 x i8*]* @"\01??_7GrandchildOverride@@6BRight@@@" to i32 (...)**), i32 (...)*** %[[VFPTR]]
182*67e74705SXin Li   // CHECK: ret
183*67e74705SXin Li }
184*67e74705SXin Li 
185*67e74705SXin Li struct LeftWithNonVirtualDtor {
186*67e74705SXin Li   virtual void left();
187*67e74705SXin Li   ~LeftWithNonVirtualDtor();
188*67e74705SXin Li };
189*67e74705SXin Li 
190*67e74705SXin Li struct AsymmetricChild : LeftWithNonVirtualDtor, Right {
191*67e74705SXin Li   virtual ~AsymmetricChild();
192*67e74705SXin Li };
193*67e74705SXin Li 
call_asymmetric_child_complete_dtor()194*67e74705SXin Li void call_asymmetric_child_complete_dtor() {
195*67e74705SXin Li   // CHECK-LABEL: define void @"\01?call_asymmetric_child_complete_dtor@@YAXXZ"
196*67e74705SXin Li   AsymmetricChild obj;
197*67e74705SXin Li   // CHECK: call x86_thiscallcc %struct.AsymmetricChild* @"\01??0AsymmetricChild@@QAE@XZ"(%struct.AsymmetricChild* %[[OBJ:.*]])
198*67e74705SXin Li   // CHECK-NOT: getelementptr
199*67e74705SXin Li   // CHECK: call x86_thiscallcc void @"\01??1AsymmetricChild@@UAE@XZ"(%struct.AsymmetricChild* %[[OBJ]])
200*67e74705SXin Li   // CHECK: ret
201*67e74705SXin Li }
202