1 // RUN: %clang_cc1 -no-opaque-pointers %s -I%S -triple=x86_64-apple-darwin10 -fstrict-vtable-pointers -std=c++11 -disable-llvm-passes -O2 -emit-llvm -o %t.ll
2 // RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll
3 // RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll
4 // RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll
5 // RUN: FileCheck --check-prefix=CHECK-LINK-REQ %s < %t.ll
6
7 typedef __typeof__(sizeof(0)) size_t;
8 void *operator new(size_t, void *) throw();
9 using uintptr_t = unsigned long long;
10
11 struct NotTrivialDtor {
12 ~NotTrivialDtor();
13 };
14
15 struct DynamicBase1 {
16 NotTrivialDtor obj;
17 virtual void foo();
18 };
19
20 struct DynamicDerived : DynamicBase1 {
21 void foo() override;
22 };
23
24 struct DynamicBase2 {
25 virtual void bar();
~DynamicBase2DynamicBase226 ~DynamicBase2() {
27 bar();
28 }
29 };
30
31 struct DynamicDerivedMultiple : DynamicBase1, DynamicBase2 {
32 void foo() override;
33 void bar() override;
34 };
35
36 struct StaticBase {
37 NotTrivialDtor obj;
38 void bar();
39 };
40
41 struct DynamicFromStatic : StaticBase {
42 virtual void bar();
43 };
44
45 struct DynamicFromVirtualStatic1 : virtual StaticBase {
46 };
47
48 struct DynamicFromVirtualStatic2 : virtual StaticBase {
49 };
50
51 struct DynamicFrom2Virtuals : DynamicFromVirtualStatic1,
52 DynamicFromVirtualStatic2 {
53 };
54
55 // CHECK-NEW-LABEL: define{{.*}} void @_Z12LocalObjectsv()
56 // CHECK-NEW-NOT: @llvm.launder.invariant.group.p0i8(
57 // CHECK-NEW-LABEL: {{^}}}
LocalObjects()58 void LocalObjects() {
59 DynamicBase1 DB;
60 DB.foo();
61 DynamicDerived DD;
62 DD.foo();
63
64 DynamicBase2 DB2;
65 DB2.bar();
66
67 StaticBase SB;
68 SB.bar();
69
70 DynamicDerivedMultiple DDM;
71 DDM.foo();
72 DDM.bar();
73
74 DynamicFromStatic DFS;
75 DFS.bar();
76 DynamicFromVirtualStatic1 DFVS1;
77 DFVS1.bar();
78 DynamicFrom2Virtuals DF2V;
79 DF2V.bar();
80 }
81
82 struct DynamicFromVirtualStatic1;
83 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic1C1Ev
84 // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8(
85 // CHECK-CTORS-LABEL: {{^}}}
86
87 struct DynamicFrom2Virtuals;
88 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN20DynamicFrom2VirtualsC1Ev
89 // CHECK-CTORS: call i8* @llvm.launder.invariant.group.p0i8(
90 // CHECK-CTORS-LABEL: {{^}}}
91
92 // CHECK-NEW-LABEL: define{{.*}} void @_Z9Pointers1v()
93 // CHECK-NEW-NOT: @llvm.launder.invariant.group.p0i8(
94 // CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev(
95
96 // CHECK-NEW: %[[THIS3:.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* %[[THIS2:.*]])
97 // CHECK-NEW: %[[THIS4:.*]] = bitcast i8* %[[THIS3]] to %[[DynamicDerived:.*]]*
98 // CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(%[[DynamicDerived:.*]]* {{[^,]*}} %[[THIS4]])
99 // CHECK-NEW-LABEL: {{^}}}
Pointers1()100 void Pointers1() {
101 DynamicBase1 *DB = new DynamicBase1;
102 DB->foo();
103
104 DynamicDerived *DD = new (DB) DynamicDerived;
105 DD->foo();
106 DD->~DynamicDerived();
107 }
108
109 // CHECK-NEW-LABEL: define{{.*}} void @_Z14HackingObjectsv()
110 // CHECK-NEW: call void @_ZN12DynamicBase1C1Ev
111 // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(
112 // CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(
113 // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(
114 // CHECK-NEW: call void @_ZN12DynamicBase1C1Ev(
115 // CHECK-NEW-LABEL: {{^}}}
HackingObjects()116 void HackingObjects() {
117 DynamicBase1 DB;
118 DB.foo();
119
120 DynamicDerived *DB2 = new (&DB) DynamicDerived;
121 // Using DB now is prohibited.
122 DB2->foo();
123 DB2->~DynamicDerived();
124
125 // We have to get back to the previous type to avoid calling wrong destructor
126 new (&DB) DynamicBase1;
127 DB.foo();
128 }
129
130 /*** Testing Constructors ***/
131 struct DynamicBase1;
132 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1C2Ev(
133 // CHECK-CTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
134 // CHECK-CTORS-LABEL: {{^}}}
135
136 struct DynamicDerived;
137
138 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev(
139 // CHECK-CTORS: %[[THIS0:.*]] = load %[[DynamicDerived:.*]]*, %[[DynamicDerived]]** {{.*}}
140 // CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[DynamicDerived:.*]]* %[[THIS0]] to i8*
141 // CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* %[[THIS1:.*]])
142 // CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2]] to %[[DynamicDerived]]*
143 // CHECK-CTORS: %[[THIS4:.*]] = bitcast %[[DynamicDerived]]* %[[THIS3]] to %[[DynamicBase:.*]]*
144 // CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(%[[DynamicBase]]* {{[^,]*}} %[[THIS4]])
145
146 // CHECK-CTORS: %[[THIS5:.*]] = bitcast %struct.DynamicDerived* %[[THIS0]] to i32 (...)***
147 // CHECK-CTORS: store {{.*}} %[[THIS5]]
148 // CHECK-CTORS-LABEL: {{^}}}
149
150 struct DynamicDerivedMultiple;
151 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleC2Ev(
152
153 // CHECK-CTORS: %[[THIS0:.*]] = load %[[CLASS:.*]]*, %[[CLASS]]** {{.*}}
154 // CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[CLASS:.*]]* %[[THIS0]] to i8*
155 // CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* %[[THIS1]])
156 // CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2]] to %[[CLASS]]*
157 // CHECK-CTORS: %[[THIS4:.*]] = bitcast %[[CLASS]]* %[[THIS3]] to %[[BASE_CLASS:.*]]*
158 // CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(%[[BASE_CLASS]]* {{[^,]*}} %[[THIS4]])
159
160 // CHECK-CTORS: call i8* @llvm.launder.invariant.group.p0i8(
161
162 // CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev(
163 // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8
164
165 // CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)***
166 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2) {{.*}} %[[THIS10]]
167 // CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8*
168 // CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16
169 // CHECK-CTORS: %[[THIS12:.*]] = bitcast i8* %[[THIS_ADD]] to i32 (...)***
170
171 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2) {{.*}} %[[THIS12]]
172 // CHECK-CTORS-LABEL: {{^}}}
173
174 struct DynamicFromStatic;
175 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticC2Ev(
176 // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0i8(
177 // CHECK-CTORS-LABEL: {{^}}}
178
179 struct A {
180 virtual void foo();
181 int m;
182 };
183 struct B : A {
184 void foo() override;
185 };
186
187 union U {
188 A a;
189 B b;
190 };
191
192 void changeToB(U *u);
193 void changeToA(U *u);
194
g2(A * a)195 void g2(A *a) {
196 a->foo();
197 }
198 // We have to guard access to union fields with invariant.group, because
199 // it is very easy to skip the barrier with unions. In this example the inlined
200 // g2 will produce loads with the same !invariant.group metadata, and
201 // u->a and u->b would use the same pointer.
202 // CHECK-NEW-LABEL: define{{.*}} void @_Z14UnionsBarriersP1U
UnionsBarriers(U * u)203 void UnionsBarriers(U *u) {
204 // CHECK-NEW: call void @_Z9changeToBP1U(
205 changeToB(u);
206 // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
207 // CHECK-NEW: call void @_Z2g2P1A(%struct.A*
208 g2(&u->b);
209 // CHECK-NEW: call void @_Z9changeToAP1U(%union.U*
210 changeToA(u);
211 // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
212 // call void @_Z2g2P1A(%struct.A* %a)
213 g2(&u->a);
214 // CHECK-NEW-NOT: call i8* @llvm.launder.invariant.group.p0i8(i8*
215 }
216
217 struct HoldingVirtuals {
218 A a;
219 };
220
221 struct Empty {};
222 struct AnotherEmpty {
223 Empty e;
224 };
225 union NoVptrs {
226 int a;
227 AnotherEmpty empty;
228 };
229 void take(AnotherEmpty &);
230
231 // CHECK-NEW-LABEL: noBarriers
noBarriers(NoVptrs & noVptrs)232 void noBarriers(NoVptrs &noVptrs) {
233 // CHECK-NEW-NOT: call i8* @llvm.launder.invariant.group.p0i8(i8*
234 // CHECK-NEW: 42
235 noVptrs.a += 42;
236 // CHECK-NEW-NOT: call i8* @llvm.launder.invariant.group.p0i8(i8*
237 // CHECK-NEW: call void @_Z4takeR12AnotherEmpty(
238 take(noVptrs.empty);
239 }
240
241 union U2 {
242 HoldingVirtuals h;
243 int z;
244 };
245 void take(HoldingVirtuals &);
246
247 // CHECK-NEW-LABEL: define{{.*}} void @_Z15UnionsBarriers2R2U2
UnionsBarriers2(U2 & u)248 void UnionsBarriers2(U2 &u) {
249 // CHECK-NEW-NOT: call i8* @llvm.launder.invariant.group.p0i8(i8*
250 // CHECK-NEW: 42
251 u.z += 42;
252 // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
253 // CHECK-NEW: call void @_Z4takeR15HoldingVirtuals(
254 take(u.h);
255 }
256
257 struct VirtualInBase : HoldingVirtuals, Empty {
258 };
259
260 struct VirtualInVBase : virtual Empty, virtual HoldingVirtuals {
261 };
262
263 // It has vtable by virtual inheritance.
264 struct VirtualInheritance : virtual Empty {
265 };
266
267 union U3 {
268 VirtualInBase v1;
269 VirtualInBase v2;
270 VirtualInheritance v3;
271 int z;
272 };
273
274 void take(VirtualInBase &);
275 void take(VirtualInVBase &);
276 void take(VirtualInheritance &);
277
UnionsBarrier3(U3 & u)278 void UnionsBarrier3(U3 &u) {
279 // CHECK-NEW-NOT: call i8* @llvm.launder.invariant.group.p0i8(i8*
280 // CHECK-NEW: 42
281 u.z += 42;
282 // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
283 // CHECK-NEW: call void @_Z4takeR13VirtualInBase(
284 take(u.v1);
285 // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
286 // CHECK-NEW: call void @_Z4takeR13VirtualInBase(
287 take(u.v2);
288
289 // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
290 // CHECK-NEW: call void @_Z4takeR18VirtualInheritance(
291 take(u.v3);
292 }
293
294 // CHECK-NEW-LABEL: define{{.*}} void @_Z7comparev()
compare()295 void compare() {
296 A *a = new A;
297 a->foo();
298 // CHECK-NEW: call i8* @llvm.launder.invariant.group.p0i8(i8*
299 A *b = new (a) B;
300
301 // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
302 // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
303 // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
304 // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
305 // CHECK-NEW: %cmp = icmp eq %struct.A* %[[a2]], %[[b2]]
306 if (a == b)
307 b->foo();
308 }
309
310 // CHECK-NEW-LABEL: compare2
compare2(A * a,A * a2)311 bool compare2(A *a, A *a2) {
312 // CHECK-NEW: %[[a:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
313 // CHECK-NEW: %[[a2:.*]] = bitcast i8* %[[a]] to %struct.A*
314 // CHECK-NEW: %[[b:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
315 // CHECK-NEW: %[[b2:.*]] = bitcast i8* %[[b]] to %struct.A*
316 // CHECK-NEW: %cmp = icmp ult %struct.A* %[[a2]], %[[b2]]
317 return a < a2;
318 }
319 // CHECK-NEW-LABEL: compareIntPointers
compareIntPointers(int * a,int * b)320 bool compareIntPointers(int *a, int *b) {
321 // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
322 return a == b;
323 }
324
325 struct HoldingOtherVirtuals {
326 B b;
327 };
328
329 // There is no need to add barriers for comparision of pointer to classes
330 // that are not dynamic.
331 // CHECK-NEW-LABEL: compare5
compare5(HoldingOtherVirtuals * a,HoldingOtherVirtuals * b)332 bool compare5(HoldingOtherVirtuals *a, HoldingOtherVirtuals *b) {
333 // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
334 return a == b;
335 }
336 // CHECK-NEW-LABEL: compareNull
compareNull(A * a)337 bool compareNull(A *a) {
338 // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group
339
340 if (a != nullptr)
341 return false;
342 if (!a)
343 return false;
344 return a == nullptr;
345 }
346
347 struct X;
348 // We have to also introduce the barriers if comparing pointers to incomplete
349 // objects
350 // CHECK-NEW-LABEL: define{{.*}} zeroext i1 @_Z8compare4P1XS0_
compare4(X * x,X * x2)351 bool compare4(X *x, X *x2) {
352 // CHECK-NEW: %[[x:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
353 // CHECK-NEW: %[[xp:.*]] = bitcast i8* %[[x]] to %struct.X*
354 // CHECK-NEW: %[[x2:.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8*
355 // CHECK-NEW: %[[x2p:.*]] = bitcast i8* %[[x2]] to %struct.X*
356 // CHECK-NEW: %cmp = icmp eq %struct.X* %[[xp]], %[[x2p]]
357 return x == x2;
358 }
359
360 // CHECK-NEW-LABEL: define{{.*}} void @_Z7member1P20HoldingOtherVirtuals(
member1(HoldingOtherVirtuals * p)361 void member1(HoldingOtherVirtuals *p) {
362
363 // CHECK-NEW-NOT: call i8* @llvm.strip.invariant.group.p0i8(
364 (void)p->b;
365 }
366
367 // CHECK-NEW-LABEL: member2
member2(A * a)368 void member2(A *a) {
369 // CHECK-NEW: call i8* @llvm.strip.invariant.group.p0i8
370 (void)a->m;
371 }
372
373 // Check if from comparison of addresses of member we can't infer the equality
374 // of ap and bp.
375 // CHECK-NEW-LABEL: @_Z18testCompareMembersv(
testCompareMembers()376 void testCompareMembers() {
377 // CHECK-NEW: [[AP:%.*]] = alloca %struct.A*
378 // CHECK-NEW: [[APM:%.*]] = alloca i32*
379 // CHECK-NEW: [[BP:%.*]] = alloca %struct.B*
380 // CHECK-NEW: [[BPM:%.*]] = alloca i32*
381
382 A *ap = new A;
383 // CHECK-NEW: call void %{{.*}}(%struct.A* {{[^,]*}} %{{.*}})
384 ap->foo();
385 // CHECK-NEW: [[TMP7:%.*]] = load %struct.A*, %struct.A** [[AP]]
386 // CHECK-NEW: [[TMP8:%.*]] = bitcast %struct.A* [[TMP7]] to i8*
387 // CHECK-NEW: [[TMP9:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* [[TMP8]])
388 // CHECK-NEW: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to %struct.A*
389 // CHECK-NEW: [[M:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], %struct.A* [[TMP10]], i32 0, i32 1
390 // CHECK-NEW: store i32* [[M]], i32** [[APM]]
391 int *const apm = &ap->m;
392
393 B *bp = new (ap) B;
394
395 // CHECK-NEW: [[TMP20:%.*]] = load %struct.B*, %struct.B** [[BP]]
396 // CHECK-NEW: [[TMP21:%.*]] = bitcast %struct.B* [[TMP20]] to %struct.A*
397 // CHECK-NEW: [[TMP22:%.*]] = bitcast %struct.A* [[TMP21]] to i8*
398 // CHECK-NEW: [[TMP23:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* [[TMP22]])
399 // CHECK-NEW: [[TMP24:%.*]] = bitcast i8* [[TMP23]] to %struct.A*
400 // CHECK-NEW: [[M4:%.*]] = getelementptr inbounds [[STRUCT_A]], %struct.A* [[TMP24]], i32 0, i32 1
401 // CHECK-NEW: store i32* [[M4]], i32** [[BPM]]
402 int *const bpm = &bp->m;
403
404 // CHECK-NEW: [[TMP25:%.*]] = load i32*, i32** [[APM]]
405 // CHECK-NEW: [[TMP26:%.*]] = load i32*, i32** [[BPM]]
406 // CHECK-NEW-NOT: strip.invariant.group
407 // CHECK-NEW-NOT: launder.invariant.group
408 // CHECK-NEW: [[CMP:%.*]] = icmp eq i32* [[TMP25]], [[TMP26]]
409 if (apm == bpm) {
410 bp->foo();
411 }
412 }
413
414 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast1P1A(%struct.A*
testCast1(A * a)415 void testCast1(A *a) {
416 // Here we get rid of dynamic info
417 // CHECK-NEW: call i8* @llvm.strip.invariant.group
418 auto *v = (void *)a;
419
420 // CHECK-NEW: call i8* @llvm.strip.invariant.group
421 auto i2 = (uintptr_t)a;
422 (void)i2;
423
424 // CHECK-NEW-NOT: @llvm.strip.invariant.group
425 // CHECK-NEW-NOT: @llvm.launder.invariant.group
426
427 // The information is already stripped
428 auto i = (uintptr_t)v;
429 }
430
431 struct Incomplete;
432 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast2P10Incomplete(%struct.Incomplete*
testCast2(Incomplete * I)433 void testCast2(Incomplete *I) {
434 // Here we get rid of potential dynamic info
435 // CHECK-NEW: call i8* @llvm.strip.invariant.group
436 auto *v = (void *)I;
437
438 // CHECK-NEW: call i8* @llvm.strip.invariant.group
439 auto i2 = (uintptr_t)I;
440 (void)i2;
441
442 // CHECK-NEW-NOT: @llvm.strip.invariant.group
443 // CHECK-NEW-NOT: @llvm.launder.invariant.group
444
445 // The information is already stripped
446 auto i = (uintptr_t)v;
447 }
448
449 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast3y(
testCast3(uintptr_t i)450 void testCast3(uintptr_t i) {
451 // CHECK-NEW-NOT: @llvm.strip.invariant.group
452 // CHECK-NEW: @llvm.launder.invariant.group
453 A *a3 = (A *)i;
454 (void)a3;
455
456 auto *v2 = (void *)i;
457
458 // CHECK-NEW: @llvm.launder.invariant.group
459 A *a2 = (A *)v2;
460 (void)a2;
461
462 // CHECK-NEW-NOT: @llvm.launder.invariant.group
463 auto *v3 = (void *)i;
464 (void)v3;
465 }
466
467 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast4y(
testCast4(uintptr_t i)468 void testCast4(uintptr_t i) {
469 // CHECK-NEW-NOT: @llvm.strip.invariant.group
470 // CHECK-NEW: @llvm.launder.invariant.group
471 auto *a3 = (Incomplete *)i;
472 (void)a3;
473
474 // CHECK-NEW: @llvm.launder.invariant.group
475 auto *v2 = (void *)i;
476 // CHECK-NEW-NOT: @llvm.launder.invariant.group
477 auto *a2 = (Incomplete *)v2;
478 (void)a2;
479 }
480
481 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast5P1B(
testCast5(B * b)482 void testCast5(B *b) {
483 // CHECK-NEW-NOT: @llvm.strip.invariant.group
484 // CHECK-NEW-NOT: @llvm.launder.invariant.group
485 A *a = b;
486 (void)a;
487
488 auto *b2 = (B *)a;
489 (void)b2;
490 }
491
492 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast6P1A(
testCast6(A * a)493 void testCast6(A *a) {
494
495 // CHECK-NEW: @llvm.strip.invariant.group
496 auto *I = (Incomplete *)a;
497 (void)I;
498 // CHECK-NEW: @llvm.launder.invariant.group
499 auto *a2 = (A *)I;
500 (void)a2;
501
502 // CHECK-NEW: @llvm.strip.invariant.group
503 auto *E = (Empty *)a;
504 (void)E;
505
506 // CHECK-NEW: @llvm.launder.invariant.group
507 auto *a3 = (A *)E;
508 (void)a3;
509
510 // CHECK-NEW-NOT: @llvm.strip.invariant.group
511 auto i = (uintptr_t)E;
512 (void)i;
513 }
514
515 class Incomplete2;
516 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast7P10Incomplete(
testCast7(Incomplete * I)517 void testCast7(Incomplete *I) {
518 // CHECK-NEW-NOT: @llvm.strip.invariant.group
519
520 // Incomplete2 could be dynamic where Incomplete may not be dynamic, thus
521 // launder is needed. We don't strip firstly because launder is sufficient.
522
523 // CHECK-NEW: @llvm.launder.invariant.group
524 auto *I2 = (Incomplete2 *)I;
525 (void)I2;
526 // CHECK-NEW-LABEL: ret void
527 }
528
529 template <typename Base>
530 struct PossiblyDerivingFromDynamicBase : Base {
531 };
532
533 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast8P10Incomplete(
testCast8(Incomplete * I)534 void testCast8(Incomplete *I) {
535 // CHECK-NEW-NOT: @llvm.strip.invariant.group
536 // CHECK-NEW: @llvm.launder.invariant.group
537 auto *P = (PossiblyDerivingFromDynamicBase<Incomplete> *)I;
538 (void)P;
539
540 // CHECK-NEW: @llvm.launder.invariant.group
541 auto *P2 = (PossiblyDerivingFromDynamicBase<Empty> *)I;
542 (void)P2;
543
544 // CHECK-NEW: @llvm.launder.invariant.group
545 auto *P3 = (PossiblyDerivingFromDynamicBase<A> *)I;
546 (void)P3;
547
548 // CHECK-NEW-NOT: @llvm.launder.invariant.group
549 auto *a3 = (A *)P3;
550
551 // CHECK-NEW-LABEL: ret void
552 }
553
554 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast9
testCast9(PossiblyDerivingFromDynamicBase<Incomplete> * P)555 void testCast9(PossiblyDerivingFromDynamicBase<Incomplete> *P) {
556 // CHECK-NEW: @llvm.strip.invariant.group
557 auto *V = (void *)P;
558
559 // CHECK-NEW-LABEL: ret void
560 }
561
562 /** DTORS **/
563 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev(
564 // CHECK-DTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
565 // CHECK-DTORS-LABEL: {{^}}}
566
567 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic2D2Ev(
568 // CHECK-DTORS-NOT: invariant.barrier
569 // CHECK-DTORS-LABEL: {{^}}}
570
571 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticD2Ev
572 // CHECK-DTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
573 // CHECK-DTORS-LABEL: {{^}}}
574
575 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleD2Ev(
576
577 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase2D2Ev(
578 // CHECK-DTORS: call i8* @llvm.launder.invariant.group.p0i8(
579 // CHECK-DTORS-LABEL: {{^}}}
580
581 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1D2Ev
582 // CHECK-DTORS: call i8* @llvm.launder.invariant.group.p0i8(
583 // CHECK-DTORS-LABEL: {{^}}}
584
585 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedD2Ev
586 // CHECK-DTORS-NOT: call i8* @llvm.launder.invariant.group.p0i8(
587 // CHECK-DTORS-LABEL: {{^}}}
588
589 // CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:[0-9]+]], ![[SEC:[0-9]+]]{{.*}}}
590
591 // CHECK-LINK-REQ: ![[FIRST]] = !{i32 1, !"StrictVTablePointers", i32 1}
592 // CHECK-LINK-REQ: ![[SEC]] = !{i32 3, !"StrictVTablePointersRequirement", ![[META:.*]]}
593 // CHECK-LINK-REQ: ![[META]] = !{!"StrictVTablePointers", i32 1}
594