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