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