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 | |
7 | void foo(void *); |
8 | |
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(); |
18 | }; |
19 | |
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(); |
27 | }; |
28 | |
29 | |
30 | struct 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 | |
62 | C::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 | |
75 | void zoo(C* obj) { |
76 | delete obj; |
77 | } |
78 | |
79 | struct D { |
80 | virtual B* goo(); |
81 | }; |
82 | |
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" |
90 | }; |
91 | |
92 | E::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 | |
99 | struct F : virtual A, virtual B { |
100 | virtual void own_method(); |
101 | virtual ~F(); |
102 | }; |
103 | |
104 | F f; // Just make sure we don't crash, e.g. mangling the complete dtor. |
105 | |
106 | struct G : C { }; |
107 | |
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" |
116 | }; |
117 | |
118 | H h; |
119 | |
120 | struct I : D { |
121 | I(); |
122 | virtual F* goo(); |
123 | }; |
124 | |
125 | I::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 | |
140 | namespace 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. |
143 | struct A { |
144 | virtual void __stdcall foo(); |
145 | }; |
146 | struct B { |
147 | virtual void __stdcall foo(); |
148 | }; |
149 | struct C : A, B { |
150 | virtual void __stdcall foo(); |
151 | }; |
152 | C c; |
153 | } |
154 | |
155 | namespace { |
156 | struct E : D { |
157 | E(); |
158 | virtual C* goo(); |
159 | }; |
160 | E::E() {} |
161 | E 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 | |