1 // RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions -fstrict-vtable-pointers
2 // RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions -fstrict-vtable-pointers
3 // FIXME: Assume load should not require -fstrict-vtable-pointers
4
5 // RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s
6 // RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s
7 // RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s
8 // RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s
9 // RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s
10 // RUN: FileCheck --check-prefix=CHECK6 --input-file=%t.ll %s
11 // RUN: FileCheck --check-prefix=CHECK7 --input-file=%t.ll %s
12 // RUN: FileCheck --check-prefix=CHECK8 --input-file=%t.ll %s
13 // RUN: FileCheck --check-prefix=CHECK9 --input-file=%t.ll %s
14 namespace test1 {
15
16 struct A {
17 A();
18 virtual void foo();
19 };
20
21 struct B : A {
22 virtual void foo();
23 };
24
g(A * a)25 void g(A *a) { a->foo(); }
26
27 // CHECK1-LABEL: define void @_ZN5test14fooAEv()
28 // CHECK1: call void @_ZN5test11AC1Ev(%"struct.test1::A"*
29 // CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
30 // CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i32 0, i32 2)
31 // CHECK1: call void @llvm.assume(i1 %[[CMP]])
32 // CHECK1-LABEL: }
33
fooA()34 void fooA() {
35 A a;
36 g(&a);
37 }
38
39 // CHECK1-LABEL: define void @_ZN5test14fooBEv()
40 // CHECK1: call void @_ZN5test11BC1Ev(%"struct.test1::B"* %{{.*}})
41 // CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
42 // CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i32 0, i32 2)
43 // CHECK1: call void @llvm.assume(i1 %[[CMP]])
44 // CHECK1-LABEL: }
45
fooB()46 void fooB() {
47 B b;
48 g(&b);
49 }
50 // there should not be any assumes in the ctor that calls base ctor
51 // CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%"struct.test1::B"*
52 // CHECK1-NOT: @llvm.assume(
53 // CHECK1-LABEL: }
54 }
55 namespace test2 {
56 struct A {
57 A();
58 virtual void foo();
59 };
60
61 struct B {
62 B();
63 virtual void bar();
64 };
65
66 struct C : A, B {
67 C();
68 virtual void foo();
69 };
g(A * a)70 void g(A *a) { a->foo(); }
h(B * b)71 void h(B *b) { b->bar(); }
72
73 // CHECK2-LABEL: define void @_ZN5test24testEv()
74 // CHECK2: call void @_ZN5test21CC1Ev(%"struct.test2::C"*
75 // CHECK2: %[[VTABLE:.*]] = load i8**, i8*** {{.*}}
76 // CHECK2: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i32 0, i32 2)
77 // CHECK2: call void @llvm.assume(i1 %[[CMP]])
78
79 // CHECK2: %[[V2:.*]] = bitcast %"struct.test2::C"* %{{.*}} to i8*
80 // CHECK2: %[[ADD_PTR:.*]] = getelementptr inbounds i8, i8* %[[V2]], i64 8
81 // CHECK2: %[[V3:.*]] = bitcast i8* %[[ADD_PTR]] to i8***
82 // CHECK2: %[[VTABLE2:.*]] = load i8**, i8*** %[[V3]]
83 // CHECK2: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([6 x i8*], [6 x i8*]* @_ZTVN5test21CE, i32 0, i32 5)
84 // CHECK2: call void @llvm.assume(i1 %[[CMP2]])
85
86 // CHECK2: call void @_ZN5test21gEPNS_1AE(
87 // CHECK2-LABEL: }
88
test()89 void test() {
90 C c;
91 g(&c);
92 h(&c);
93 }
94 }
95
96 namespace test3 {
97 struct A {
98 A();
99 };
100
101 struct B : A {
102 B();
103 virtual void foo();
104 };
105
106 struct C : virtual A, B {
107 C();
108 virtual void foo();
109 };
g(B * a)110 void g(B *a) { a->foo(); }
111
112 // CHECK3-LABEL: define void @_ZN5test34testEv()
113 // CHECK3: call void @_ZN5test31CC1Ev(%"struct.test3::C"*
114 // CHECK3: %[[CMP:.*]] = icmp eq i8** %{{.*}}, getelementptr inbounds ([4 x i8*], [4 x i8*]* @_ZTVN5test31CE, i32 0, i32 3)
115 // CHECK3: call void @llvm.assume(i1 %[[CMP]])
116 // CHECK3-LABLEL: }
test()117 void test() {
118 C c;
119 g(&c);
120 }
121 } // test3
122
123 namespace test4 {
124 struct A {
125 A();
126 virtual void foo();
127 };
128
129 struct B : virtual A {
130 B();
131 virtual void foo();
132 };
133 struct C : B {
134 C();
135 virtual void foo();
136 };
137
g(C * c)138 void g(C *c) { c->foo(); }
139
140 // CHECK4-LABEL: define void @_ZN5test44testEv()
141 // CHECK4: call void @_ZN5test41CC1Ev(%"struct.test4::C"*
142 // CHECK4: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}}
143 // CHECK4: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i32 0, i32 4)
144 // CHECK4: call void @llvm.assume(i1 %[[CMP]]
145
146 // CHECK4: %[[VTABLE2:.*]] = load i8**, i8*** %{{.*}}
147 // CHECK4: %[[CMP2:.*]] = icmp eq i8** %[[VTABLE2]], getelementptr inbounds ([5 x i8*], [5 x i8*]* @_ZTVN5test41CE, i32 0, i32 4)
148 // CHECK4: call void @llvm.assume(i1 %[[CMP2]])
149 // CHECK4-LABEL: }
150
test()151 void test() {
152 C c;
153 g(&c);
154 }
155 } // test4
156
157 namespace testMS {
158
159 struct __declspec(novtable) S {
160 virtual void foo();
161 };
162
g(S & s)163 void g(S &s) { s.foo(); }
164
165 // if struct has novtable specifier, then we can't generate assumes
166 // CHECK-MS-LABEL: define void @"\01?test@testMS@@YAXXZ"()
167 // CHECK-MS: call x86_thiscallcc %"struct.testMS::S"* @"\01??0S@testMS@@QAE@XZ"(
168 // CHECK-MS-NOT: @llvm.assume
169 // CHECK-MS-LABEL: }
170
test()171 void test() {
172 S s;
173 g(s);
174 }
175
176 } // testMS
177
178 namespace test6 {
179 struct A {
180 A();
181 virtual void foo();
~Atest6::A182 virtual ~A() {}
183 };
184 struct B : A {
185 B();
186 };
187 // FIXME: Because A's vtable is external, and no virtual functions are hidden,
188 // it's safe to generate assumption loads.
189 // CHECK6-LABEL: define void @_ZN5test61gEv()
190 // CHECK6: call void @_ZN5test61AC1Ev(
191 // CHECK6-NOT: call void @llvm.assume(
192
193 // We can't emit assumption loads for B, because if we would refer to vtable
194 // it would refer to functions that will not be able to find (like implicit
195 // inline destructor).
196
197 // CHECK6-LABEL: call void @_ZN5test61BC1Ev(
198 // CHECK6-NOT: call void @llvm.assume(
199 // CHECK6-LABEL: }
g()200 void g() {
201 A *a = new A;
202 B *b = new B;
203 }
204 }
205
206 namespace test7 {
207 // Because A's key function is defined here, vtable is generated in this TU
208 // CHECK7: @_ZTVN5test71AE = unnamed_addr constant
209 struct A {
210 A();
211 virtual void foo();
212 virtual void bar();
213 };
foo()214 void A::foo() {}
215
216 // CHECK7-LABEL: define void @_ZN5test71gEv()
217 // CHECK7: call void @_ZN5test71AC1Ev(
218 // CHECK7: call void @llvm.assume(
219 // CHECK7-LABEL: }
g()220 void g() {
221 A *a = new A();
222 a->bar();
223 }
224 }
225
226 namespace test8 {
227
228 struct A {
229 virtual void foo();
230 virtual void bar();
231 };
232
233 // CHECK8-DAG: @_ZTVN5test81BE = available_externally unnamed_addr constant
234 struct B : A {
235 B();
236 void foo();
237 void bar();
238 };
239
240 // CHECK8-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr constant
241 struct C : A {
242 C();
243 void bar();
footest8::C244 void foo() {}
245 };
bar()246 inline void C::bar() {}
247
248 struct D : A {
249 D();
250 void foo();
251 void inline bar();
252 };
bar()253 void D::bar() {}
254
255 // CHECK8-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr constant
256 struct E : A {
257 E();
258 };
259
260 // CHECK8-LABEL: define void @_ZN5test81bEv()
261 // CHECK8: call void @llvm.assume(
262 // CHECK8-LABEL: }
b()263 void b() {
264 B b;
265 b.bar();
266 }
267
268 // FIXME: C has inline virtual functions which prohibits as from generating
269 // assumption loads, but because vtable is generated in this TU (key function
270 // defined here) it would be correct to refer to it.
271 // CHECK8-LABEL: define void @_ZN5test81cEv()
272 // CHECK8-NOT: call void @llvm.assume(
273 // CHECK8-LABEL: }
c()274 void c() {
275 C c;
276 c.bar();
277 }
278
279 // FIXME: We could generate assumption loads here.
280 // CHECK8-LABEL: define void @_ZN5test81dEv()
281 // CHECK8-NOT: call void @llvm.assume(
282 // CHECK8-LABEL: }
d()283 void d() {
284 D d;
285 d.bar();
286 }
287
288 // CHECK8-LABEL: define void @_ZN5test81eEv()
289 // CHECK8: call void @llvm.assume(
290 // CHECK8-LABEL: }
e()291 void e() {
292 E e;
293 e.bar();
294 }
295 }
296
297 namespace test9 {
298
299 struct S {
300 S();
301 __attribute__((visibility("hidden"))) virtual void doStuff();
302 };
303
304 // CHECK9-LABEL: define void @_ZN5test94testEv()
305 // CHECK9-NOT: @llvm.assume(
306 // CHECK9: }
test()307 void test() {
308 S *s = new S();
309 s->doStuff();
310 delete s;
311 }
312 }
313
314