xref: /aosp_15_r20/external/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s
2*67e74705SXin Li 
3*67e74705SXin Li // In each test case, we have two member pointers whose thunks have the same
4*67e74705SXin Li // vtable offset and same mangling, but their prototypes conflict.  The
5*67e74705SXin Li // arguments and return type may differ.  Therefore, we have to bitcast the
6*67e74705SXin Li // function prototype.  Unfortunately, if the return types differ, LLVM's
7*67e74705SXin Li // optimizers can get upset.
8*67e74705SXin Li 
9*67e74705SXin Li namespace num_params {
10*67e74705SXin Li struct A { virtual void a(int); };
11*67e74705SXin Li struct B { virtual void b(int, int); };
12*67e74705SXin Li struct C : A, B {
13*67e74705SXin Li   virtual void a(int);
14*67e74705SXin Li   virtual void b(int, int);
15*67e74705SXin Li };
f(C * c)16*67e74705SXin Li void f(C *c) {
17*67e74705SXin Li   (c->*(&C::a))(0);
18*67e74705SXin Li   (c->*(&C::b))(0, 0);
19*67e74705SXin Li }
20*67e74705SXin Li }
21*67e74705SXin Li 
22*67e74705SXin Li // CHECK-LABEL: define void @"\01?f@num_params@@YAXPAUC@1@@Z"(%"struct.num_params::C"* %c)
23*67e74705SXin Li // CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"\01??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0)
24*67e74705SXin Li // CHECK: call x86_thiscallcc void bitcast (void (%"struct.num_params::C"*, ...)* @"\01??_9C@num_params@@$BA@AE" to void (%"struct.num_params::C"*, i32, i32)*)(%"struct.num_params::C"* %{{.*}}, i32 0, i32 0)
25*67e74705SXin Li 
26*67e74705SXin Li // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@num_params@@$BA@AE"(%"struct.num_params::C"* %this, ...) {{.*}} comdat
27*67e74705SXin Li // CHECK: musttail call x86_thiscallcc void (%"struct.num_params::C"*, ...) %{{.*}}(%"struct.num_params::C"* %{{.*}}, ...)
28*67e74705SXin Li // CHECK-NEXT: ret void
29*67e74705SXin Li 
30*67e74705SXin Li namespace i64_return {
31*67e74705SXin Li struct A { virtual int a(); };
32*67e74705SXin Li struct B { virtual long long b(); };
33*67e74705SXin Li struct C : A, B {
34*67e74705SXin Li   virtual int a();
35*67e74705SXin Li   virtual long long b();
36*67e74705SXin Li };
f(C * c)37*67e74705SXin Li long long f(C *c) {
38*67e74705SXin Li   int x = (c->*(&C::a))();
39*67e74705SXin Li   long long y = (c->*(&C::b))();
40*67e74705SXin Li   return x + y;
41*67e74705SXin Li }
42*67e74705SXin Li }
43*67e74705SXin Li 
44*67e74705SXin Li // CHECK-LABEL: define i64 @"\01?f@i64_return@@YA_JPAUC@1@@Z"(%"struct.i64_return::C"* %c)
45*67e74705SXin Li // CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.i64_return::C"*, ...)* @"\01??_9C@i64_return@@$BA@AE" to i32 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}})
46*67e74705SXin Li // CHECK: call x86_thiscallcc i64 bitcast (void (%"struct.i64_return::C"*, ...)* @"\01??_9C@i64_return@@$BA@AE" to i64 (%"struct.i64_return::C"*)*)(%"struct.i64_return::C"* %{{.*}})
47*67e74705SXin Li 
48*67e74705SXin Li // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@i64_return@@$BA@AE"(%"struct.i64_return::C"* %this, ...) {{.*}} comdat
49*67e74705SXin Li // CHECK: musttail call x86_thiscallcc void (%"struct.i64_return::C"*, ...) %{{.*}}(%"struct.i64_return::C"* %{{.*}}, ...)
50*67e74705SXin Li // CHECK-NEXT: ret void
51*67e74705SXin Li 
52*67e74705SXin Li namespace sret {
53*67e74705SXin Li struct Big { int big[32]; };
54*67e74705SXin Li struct A { virtual int a(); };
55*67e74705SXin Li struct B { virtual Big b(); };
56*67e74705SXin Li struct C : A, B {
57*67e74705SXin Li   virtual int a();
58*67e74705SXin Li   virtual Big b();
59*67e74705SXin Li };
f(C * c)60*67e74705SXin Li void f(C *c) {
61*67e74705SXin Li   (c->*(&C::a))();
62*67e74705SXin Li   Big b((c->*(&C::b))());
63*67e74705SXin Li }
64*67e74705SXin Li }
65*67e74705SXin Li 
66*67e74705SXin Li // CHECK-LABEL: define void @"\01?f@sret@@YAXPAUC@1@@Z"(%"struct.sret::C"* %c)
67*67e74705SXin Li // CHECK: call x86_thiscallcc i32 bitcast (void (%"struct.sret::C"*, ...)* @"\01??_9C@sret@@$BA@AE" to i32 (%"struct.sret::C"*)*)(%"struct.sret::C"* %{{.*}})
68*67e74705SXin Li // CHECK: call x86_thiscallcc void bitcast (void (%"struct.sret::C"*, ...)* @"\01??_9C@sret@@$BA@AE" to void (%"struct.sret::C"*, %"struct.sret::Big"*)*)(%"struct.sret::C"* %{{.*}}, %"struct.sret::Big"* sret %{{.*}})
69*67e74705SXin Li 
70*67e74705SXin Li // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??_9C@sret@@$BA@AE"(%"struct.sret::C"* %this, ...) {{.*}} comdat
71*67e74705SXin Li // CHECK: musttail call x86_thiscallcc void (%"struct.sret::C"*, ...) %{{.*}}(%"struct.sret::C"* %{{.*}}, ...)
72*67e74705SXin Li // CHECK-NEXT: ret void
73*67e74705SXin Li 
74*67e74705SXin Li namespace cdecl_inalloca {
75*67e74705SXin Li // Fairly evil, since now we end up doing an inalloca-style call through a
76*67e74705SXin Li // thunk that doesn't use inalloca.  Hopefully the stacks line up?
77*67e74705SXin Li struct Big {
78*67e74705SXin Li   Big();
79*67e74705SXin Li   ~Big();
80*67e74705SXin Li   int big[32];
81*67e74705SXin Li };
82*67e74705SXin Li struct A { virtual void __cdecl a(); };
83*67e74705SXin Li struct B { virtual void __cdecl b(Big); };
84*67e74705SXin Li struct C : A, B {
85*67e74705SXin Li   virtual void __cdecl a();
86*67e74705SXin Li   virtual void __cdecl b(Big);
87*67e74705SXin Li };
f(C * c)88*67e74705SXin Li void f(C *c) {
89*67e74705SXin Li   Big b;
90*67e74705SXin Li   (c->*(&C::a))();
91*67e74705SXin Li   ((c->*(&C::b))(b));
92*67e74705SXin Li }
93*67e74705SXin Li }
94*67e74705SXin Li 
95*67e74705SXin Li // CHECK-LABEL: define void @"\01?f@cdecl_inalloca@@YAXPAUC@1@@Z"(%"struct.cdecl_inalloca::C"* %c)
96*67e74705SXin Li // CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AA" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* %{{.*}})
97*67e74705SXin Li // CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"\01??_9C@cdecl_inalloca@@$BA@AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}})
98*67e74705SXin Li 
99*67e74705SXin Li // CHECK-LABEL: define linkonce_odr void @"\01??_9C@cdecl_inalloca@@$BA@AA"(%"struct.cdecl_inalloca::C"* %this, ...) {{.*}} comdat
100*67e74705SXin Li // CHECK: musttail call void (%"struct.cdecl_inalloca::C"*, ...) %{{.*}}(%"struct.cdecl_inalloca::C"* %{{.*}}, ...)
101*67e74705SXin Li // CHECK-NEXT: ret void
102