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
14namespace test1 {
15
16struct A {
17  A();
18  virtual void foo();
19};
20
21struct B : A {
22  virtual void foo();
23};
24
25void 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
34void 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
46void 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}
55namespace test2 {
56struct A {
57  A();
58  virtual void foo();
59};
60
61struct B {
62  B();
63  virtual void bar();
64};
65
66struct C : A, B {
67  C();
68  virtual void foo();
69};
70void g(A *a) { a->foo(); }
71void 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
89void test() {
90  C c;
91  g(&c);
92  h(&c);
93}
94}
95
96namespace test3 {
97struct A {
98  A();
99};
100
101struct B : A {
102  B();
103  virtual void foo();
104};
105
106struct C : virtual A, B {
107  C();
108  virtual void foo();
109};
110void 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: }
117void test() {
118  C c;
119  g(&c);
120}
121} // test3
122
123namespace test4 {
124struct A {
125  A();
126  virtual void foo();
127};
128
129struct B : virtual A {
130  B();
131  virtual void foo();
132};
133struct C : B {
134  C();
135  virtual void foo();
136};
137
138void 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
151void test() {
152  C c;
153  g(&c);
154}
155} // test4
156
157namespace testMS {
158
159struct __declspec(novtable) S {
160  virtual void foo();
161};
162
163void 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
171void test() {
172  S s;
173  g(s);
174}
175
176} // testMS
177
178namespace test6 {
179struct A {
180  A();
181  virtual void foo();
182  virtual ~A() {}
183};
184struct 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: }
200void g() {
201  A *a = new A;
202  B *b = new B;
203}
204}
205
206namespace test7 {
207// Because A's key function is defined here, vtable is generated in this TU
208// CHECK7: @_ZTVN5test71AE = unnamed_addr constant
209struct A {
210  A();
211  virtual void foo();
212  virtual void bar();
213};
214void A::foo() {}
215
216// CHECK7-LABEL: define void @_ZN5test71gEv()
217// CHECK7: call void @_ZN5test71AC1Ev(
218// CHECK7: call void @llvm.assume(
219// CHECK7-LABEL: }
220void g() {
221  A *a = new A();
222  a->bar();
223}
224}
225
226namespace test8 {
227
228struct A {
229  virtual void foo();
230  virtual void bar();
231};
232
233// CHECK8-DAG: @_ZTVN5test81BE = available_externally unnamed_addr constant
234struct B : A {
235  B();
236  void foo();
237  void bar();
238};
239
240// CHECK8-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr constant
241struct C : A {
242  C();
243  void bar();
244  void foo() {}
245};
246inline void C::bar() {}
247
248struct D : A {
249  D();
250  void foo();
251  void inline bar();
252};
253void D::bar() {}
254
255// CHECK8-DAG: @_ZTVN5test81EE = linkonce_odr unnamed_addr constant
256struct E : A {
257  E();
258};
259
260// CHECK8-LABEL: define void @_ZN5test81bEv()
261// CHECK8: call void @llvm.assume(
262// CHECK8-LABEL: }
263void 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: }
274void 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: }
283void d() {
284  D d;
285  d.bar();
286}
287
288// CHECK8-LABEL: define void @_ZN5test81eEv()
289// CHECK8: call void @llvm.assume(
290// CHECK8-LABEL: }
291void e() {
292  E e;
293  e.bar();
294}
295}
296
297namespace test9 {
298
299struct 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: }
307void test() {
308  S *s = new S();
309  s->doStuff();
310  delete s;
311}
312}
313
314