Clang Project

clang_source_code/test/CodeGenCXX/microsoft-abi-thunks.cpp
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
6
7void foo(void *);
8
9struct 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();
18};
19
20struct B {
21  virtual ~B();
22  virtual void public_f();
23 protected:
24  virtual void protected_f();
25 private:
26  virtual void private_f();
27};
28
29
30struct C : A, B {
31  C();
32
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
40
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"
53
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"
60};
61
62C::C() {}  // Emits vftable and forces thunk generation.
63
64// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_EC@@W3AEPAXI@Z"(%struct.C* %this, i32 %should_call_delete) {{.*}} comdat
65// CODEGEN:   getelementptr i8, i8* {{.*}}, i32 -4
66// FIXME: should actually call _EC, not _GC.
67// CODEGEN:   call x86_thiscallcc i8* @"??_GC@@UAEPAXI@Z"
68// CODEGEN: ret
69
70// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?public_f@C@@W3AEXXZ"(%struct.C*
71// CODEGEN:   getelementptr i8, i8* {{.*}}, i32 -4
72// CODEGEN:   call x86_thiscallcc void @"?public_f@C@@UAEXXZ"(%struct.C*
73// CODEGEN: ret
74
75void zoo(C* obj) {
76  delete obj;
77}
78
79struct D {
80  virtual B* goo();
81};
82
83struct 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"
90};
91
92E::E() {}  // Emits vftable and forces thunk generation.
93
94// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc %struct.C* @"?goo@E@@QAEPAUB@@XZ"{{.*}} comdat
95// CODEGEN:   call x86_thiscallcc %struct.C* @"?goo@E@@UAEPAUC@@XZ"
96// CODEGEN:   getelementptr inbounds i8, i8* {{.*}}, i32 4
97// CODEGEN: ret
98
99struct F : virtual A, virtual B {
100  virtual void own_method();
101  virtual ~F();
102};
103
104F f;  // Just make sure we don't crash, e.g. mangling the complete dtor.
105
106struct G : C { };
107
108struct 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"
116};
117
118H h;
119
120struct I : D {
121  I();
122  virtual F* goo();
123};
124
125I::I() {}  // Emits vftable and forces thunk generation.
126
127// CODEGEN-LABEL: define weak_odr dso_local x86_thiscallcc %struct.{{[BF]}}* @"?goo@I@@QAEPAUB@@XZ"{{.*}} comdat
128// CODEGEN: %[[ORIG_RET:.*]] = call x86_thiscallcc %struct.F* @"?goo@I@@UAEPAUF@@XZ"
129// CODEGEN: %[[ORIG_RET_i8:.*]] = bitcast %struct.F* %[[ORIG_RET]] to i8*
130// CODEGEN: %[[VBPTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ORIG_RET_i8]], i32 4
131// CODEGEN: %[[VBPTR:.*]] = bitcast i8* %[[VBPTR_i8]] to i32**
132// CODEGEN: %[[VBTABLE:.*]] = load i32*, i32** %[[VBPTR]]
133// CODEGEN: %[[VBASE_OFFSET_PTR:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 2
134// CODEGEN: %[[VBASE_OFFSET:.*]] = load i32, i32* %[[VBASE_OFFSET_PTR]]
135// CODEGEN: %[[RES_i8:.*]] = getelementptr inbounds i8, i8* %[[VBPTR_i8]], i32 %[[VBASE_OFFSET]]
136// CODEGEN: %[[RES:.*]] = bitcast i8* %[[RES_i8]] to %struct.F*
137// CODEGEN: phi %struct.F* {{.*}} %[[RES]]
138// CODEGEN: ret %struct.{{[BF]}}*
139
140namespace CrashOnThunksForAttributedType {
141// We used to crash on this because the type of foo is an AttributedType, not
142// FunctionType, and we had to look through the sugar.
143struct A {
144  virtual void __stdcall foo();
145};
146struct B {
147  virtual void __stdcall foo();
148};
149struct C : A, B {
150  virtual void __stdcall foo();
151};
152C c;
153}
154
155namespace {
156struct E : D {
157  E();
158  virtual C* goo();
159};
160E::E() {}
161E e;
162// Class with internal linkage has internal linkage thunks.
163// CODEGEN: define internal x86_thiscallcc %struct.C* @"?goo@E@?A0x{{[^@]*}}@@QAEPAUB@@XZ"
164}
165