Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGenCXX / microsoft-abi-thunks.cpp
blob38aa81253ccad9c98dc31f30472fdc9d48473d2c
1 // RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 >%t 2>&1
2 // RUN: FileCheck --check-prefix=MANGLING %s < %t
3 // RUN: FileCheck --check-prefix=XMANGLING %s < %t
4 // RUN: FileCheck --check-prefix=CODEGEN %s < %t
5 // RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 2>&1 | FileCheck --check-prefix=MANGLING-X64 %s
7 void foo(void *);
9 struct A {
10 virtual ~A();
11 virtual void public_f();
12 // Make sure we don't emit unneeded thunks:
13 // XMANGLING-NOT: @"?public_f@A@@QAEXXZ"
14 protected:
15 virtual void protected_f();
16 private:
17 virtual void private_f();
20 struct B {
21 virtual ~B();
22 virtual void public_f();
23 protected:
24 virtual void protected_f();
25 private:
26 virtual void private_f();
30 struct C : A, B {
31 C();
33 virtual ~C();
34 // MANGLING-DAG: declare {{.*}} @"??1C@@UAE@XZ"({{.*}})
35 // MANGLING-DAG: define {{.*}} @"??_GC@@UAEPAXI@Z"({{.*}})
36 // MANGLING-DAG: define {{.*}} @"??_EC@@W3AEPAXI@Z"({{.*}}) {{.*}} comdat
37 // MANGLING-X64-DAG: declare {{.*}} @"??1C@@UEAA@XZ"({{.*}})
38 // MANGLING-X64-DAG: define {{.*}} @"??_GC@@UEAAPEAXI@Z"({{.*}})
39 // MANGLING-X64-DAG: define {{.*}} @"??_EC@@W7EAAPEAXI@Z"({{.*}}) {{.*}} comdat
41 // Overrides public_f() of two subobjects with distinct vfptrs, thus needs a thunk.
42 virtual void public_f();
43 // MANGLING-DAG: @"?public_f@C@@UAEXXZ"
44 // MANGLING-DAG: @"?public_f@C@@W3AEXXZ"
45 // MANGLING-X64-DAG: @"?public_f@C@@UEAAXXZ"
46 // MANGLING-X64-DAG: @"?public_f@C@@W7EAAXXZ"
47 protected:
48 virtual void protected_f();
49 // MANGLING-DAG: @"?protected_f@C@@MAEXXZ"
50 // MANGLING-DAG: @"?protected_f@C@@O3AEXXZ"
51 // MANGLING-X64-DAG: @"?protected_f@C@@MEAAXXZ"
52 // MANGLING-X64-DAG: @"?protected_f@C@@O7EAAXXZ"
54 private:
55 virtual void private_f();
56 // MANGLING-DAG: @"?private_f@C@@EAEXXZ"
57 // MANGLING-DAG: @"?private_f@C@@G3AEXXZ"
58 // MANGLING-X64-DAG: @"?private_f@C@@EEAAXXZ"
59 // MANGLING-X64-DAG: @"?private_f@C@@G7EAAXXZ"
62 C::C() {} // Emits vftable and forces thunk generation.
64 // CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_EC@@W3AEPAXI@Z"(ptr noundef %this, i32 noundef %should_call_delete) {{.*}} comdat
65 // CODEGEN: getelementptr i8, ptr {{.*}}, i32 -4
66 // FIXME: should actually call _EC, not _GC.
67 // CODEGEN: call x86_thiscallcc noundef ptr @"??_GC@@UAEPAXI@Z"
68 // CODEGEN: ret
70 // CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?public_f@C@@W3AEXXZ"(ptr
71 // CODEGEN: getelementptr i8, ptr {{.*}}, i32 -4
72 // CODEGEN: call x86_thiscallcc void @"?public_f@C@@UAEXXZ"(ptr
73 // CODEGEN: ret
75 void zoo(C* obj) {
76 delete obj;
79 struct D {
80 virtual B* goo();
83 struct E : D {
84 E();
85 virtual C* goo();
86 // MANGLING-DAG: @"?goo@E@@UAEPAUC@@XZ"
87 // MANGLING-DAG: @"?goo@E@@QAEPAUB@@XZ"
88 // MANGLING-X64-DAG: @"?goo@E@@UEAAPEAUC@@XZ"
89 // MANGLING-X64-DAG: @"?goo@E@@QEAAPEAUB@@XZ"
92 E::E() {} // Emits vftable and forces thunk generation.
94 // CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc noundef ptr @"?goo@E@@QAEPAUB@@XZ"{{.*}} comdat
95 // CODEGEN: call x86_thiscallcc noundef ptr @"?goo@E@@UAEPAUC@@XZ"
96 // CODEGEN: getelementptr inbounds i8, ptr {{.*}}, i32 4
97 // CODEGEN: ret
99 struct F : virtual A, virtual B {
100 virtual void own_method();
101 virtual ~F();
104 F f; // Just make sure we don't crash, e.g. mangling the complete dtor.
106 struct G : C { };
108 struct H : E {
109 virtual G* goo();
110 // MANGLING-DAG: @"?goo@H@@UAEPAUG@@XZ"
111 // MANGLING-DAG: @"?goo@H@@QAEPAUB@@XZ"
112 // MANGLING-DAG: @"?goo@H@@QAEPAUC@@XZ"
113 // MANGLING-X64-DAG: @"?goo@H@@UEAAPEAUG@@XZ"
114 // MANGLING-X64-DAG: @"?goo@H@@QEAAPEAUB@@XZ"
115 // MANGLING-X64-DAG: @"?goo@H@@QEAAPEAUC@@XZ"
118 H h;
120 struct I : D {
121 I();
122 virtual F* goo();
125 I::I() {} // Emits vftable and forces thunk generation.
127 // CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc noundef ptr @"?goo@I@@QAEPAUB@@XZ"{{.*}} comdat
128 // CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc noundef ptr @"?goo@I@@UAEPAUF@@XZ"
129 // CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, ptr %[[ORIG_RET]], i32 4
130 // CODEGEN: %[[VBTABLE:.*]] = load ptr, ptr %[[VBPTR_i8]]
131 // CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = getelementptr inbounds i32, ptr %[[VBTABLE]], i32 2
132 // CODEGEN: %[[VBASE_OFFSET:.*]] = load i32, ptr %[[VBASE_OFFSET_PTR]]
133 // CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8, ptr %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
134 // CODEGEN: phi ptr {{.*}} %[[RES_i8]]
135 // CODEGEN: ret ptr
137 namespace CrashOnThunksForAttributedType {
138 // We used to crash on this because the type of foo is an AttributedType, not
139 // FunctionType, and we had to look through the sugar.
140 struct A {
141 virtual void __stdcall foo();
143 struct B {
144 virtual void __stdcall foo();
146 struct C : A, B {
147 virtual void __stdcall foo();
149 C c;
152 namespace {
153 struct E : D {
154 E();
155 virtual C* goo();
157 E::E() {}
158 E e;
159 // Class with internal linkage has internal linkage thunks.
160 // CODEGEN: define internal x86_thiscallcc noundef ptr @"?goo@E@?A0x{{[^@]*}}@@QAEPAUB@@XZ"