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 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 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 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 }; 70 void g(A *a) { a->foo(); } 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 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 }; 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: } 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 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 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 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 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(); 182 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: } 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 }; 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: } 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(); 244 void foo() {} 245 }; 246 inline void C::bar() {} 247 248 struct D : A { 249 D(); 250 void foo(); 251 void inline bar(); 252 }; 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: } 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: } 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: } 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: } 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: } 307 void test() { 308 S *s = new S(); 309 s->doStuff(); 310 delete s; 311 } 312 } 313 314