1 // RUN: %clang_cc1 %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
7 typedef __typeof__(sizeof(0)) size_t;
8 void *operator new(size_t, void *) throw();
9 using uintptr_t = unsigned long long;
11 struct NotTrivialDtor
{
20 struct DynamicDerived
: DynamicBase1
{
31 struct DynamicDerivedMultiple
: DynamicBase1
, DynamicBase2
{
41 struct DynamicFromStatic
: StaticBase
{
45 struct DynamicFromVirtualStatic1
: virtual StaticBase
{
48 struct DynamicFromVirtualStatic2
: virtual StaticBase
{
51 struct DynamicFrom2Virtuals
: DynamicFromVirtualStatic1
,
52 DynamicFromVirtualStatic2
{
55 // CHECK-NEW-LABEL: define{{.*}} void @_Z12LocalObjectsv()
56 // CHECK-NEW-NOT: @llvm.launder.invariant.group.p0(
57 // CHECK-NEW-LABEL: {{^}}}
70 DynamicDerivedMultiple DDM
;
74 DynamicFromStatic DFS
;
76 DynamicFromVirtualStatic1 DFVS1
;
78 DynamicFrom2Virtuals DF2V
;
82 struct DynamicFromVirtualStatic1
;
83 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic1C1Ev
84 // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0(
85 // CHECK-CTORS-LABEL: {{^}}}
87 struct DynamicFrom2Virtuals
;
88 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN20DynamicFrom2VirtualsC1Ev
89 // CHECK-CTORS: call ptr @llvm.launder.invariant.group.p0(
90 // CHECK-CTORS-LABEL: {{^}}}
92 // CHECK-NEW-LABEL: define{{.*}} void @_Z9Pointers1v()
93 // CHECK-NEW-NOT: @llvm.launder.invariant.group.p0(
94 // CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev(
96 // CHECK-NEW: %[[THIS3:.*]] = call ptr @llvm.launder.invariant.group.p0(ptr %[[THIS2:.*]])
97 // CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(ptr {{[^,]*}} %[[THIS3]])
98 // CHECK-NEW-LABEL: {{^}}}
100 DynamicBase1
*DB
= new DynamicBase1
;
103 DynamicDerived
*DD
= new (DB
) DynamicDerived
;
105 DD
->~DynamicDerived();
108 // CHECK-NEW-LABEL: define{{.*}} void @_Z14HackingObjectsv()
109 // CHECK-NEW: call void @_ZN12DynamicBase1C1Ev
110 // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(
111 // CHECK-NEW: call void @_ZN14DynamicDerivedC1Ev(
112 // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(
113 // CHECK-NEW: call void @_ZN12DynamicBase1C1Ev(
114 // CHECK-NEW-LABEL: {{^}}}
115 void HackingObjects() {
119 DynamicDerived
*DB2
= new (&DB
) DynamicDerived
;
120 // Using DB now is prohibited.
122 DB2
->~DynamicDerived();
124 // We have to get back to the previous type to avoid calling wrong destructor
125 new (&DB
) DynamicBase1
;
129 /*** Testing Constructors ***/
131 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1C2Ev(
132 // CHECK-CTORS-NOT: call ptr @llvm.launder.invariant.group.p0(
133 // CHECK-CTORS-LABEL: {{^}}}
135 struct DynamicDerived
;
137 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev(
138 // CHECK-CTORS: %[[THIS0:.*]] = load ptr, ptr {{.*}}
139 // CHECK-CTORS: %[[THIS2:.*]] = call ptr @llvm.launder.invariant.group.p0(ptr %[[THIS1:.*]])
140 // CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(ptr {{[^,]*}} %[[THIS2]])
142 // CHECK-CTORS: store {{.*}} %[[THIS0]]
143 // CHECK-CTORS-LABEL: {{^}}}
145 struct DynamicDerivedMultiple
;
146 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleC2Ev(
148 // CHECK-CTORS: %[[THIS0:.*]] = load ptr, ptr {{.*}}
149 // CHECK-CTORS: %[[THIS2:.*]] = call ptr @llvm.launder.invariant.group.p0(ptr %[[THIS0]])
150 // CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(ptr {{[^,]*}} %[[THIS2]])
152 // CHECK-CTORS: call ptr @llvm.launder.invariant.group.p0(
154 // CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev(
155 // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0
157 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 0, i32 2), {{.*}} %[[THIS0]]
158 // CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, ptr %[[THIS0]], i64 16
160 // CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i32 0, inrange i32 1, i32 2), {{.*}} %[[THIS_ADD]]
161 // CHECK-CTORS-LABEL: {{^}}}
163 struct DynamicFromStatic
;
164 // CHECK-CTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticC2Ev(
165 // CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0(
166 // CHECK-CTORS-LABEL: {{^}}}
181 void changeToB(U
*u
);
182 void changeToA(U
*u
);
187 // We have to guard access to union fields with invariant.group, because
188 // it is very easy to skip the barrier with unions. In this example the inlined
189 // g2 will produce loads with the same !invariant.group metadata, and
190 // u->a and u->b would use the same pointer.
191 // CHECK-NEW-LABEL: define{{.*}} void @_Z14UnionsBarriersP1U
192 void UnionsBarriers(U
*u
) {
193 // CHECK-NEW: call void @_Z9changeToBP1U(
195 // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr
196 // CHECK-NEW: call void @_Z2g2P1A(ptr
198 // CHECK-NEW: call void @_Z9changeToAP1U(ptr
200 // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr
201 // call void @_Z2g2P1A(ptr %a)
203 // CHECK-NEW-NOT: call ptr @llvm.launder.invariant.group.p0(ptr
206 struct HoldingVirtuals
{
211 struct AnotherEmpty
{
218 void take(AnotherEmpty
&);
220 // CHECK-NEW-LABEL: noBarriers
221 void noBarriers(NoVptrs
&noVptrs
) {
222 // CHECK-NEW-NOT: call ptr @llvm.launder.invariant.group.p0(ptr
225 // CHECK-NEW-NOT: call ptr @llvm.launder.invariant.group.p0(ptr
226 // CHECK-NEW: call void @_Z4takeR12AnotherEmpty(
234 void take(HoldingVirtuals
&);
236 // CHECK-NEW-LABEL: define{{.*}} void @_Z15UnionsBarriers2R2U2
237 void UnionsBarriers2(U2
&u
) {
238 // CHECK-NEW-NOT: call ptr @llvm.launder.invariant.group.p0(ptr
241 // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr
242 // CHECK-NEW: call void @_Z4takeR15HoldingVirtuals(
246 struct VirtualInBase
: HoldingVirtuals
, Empty
{
249 struct VirtualInVBase
: virtual Empty
, virtual HoldingVirtuals
{
252 // It has vtable by virtual inheritance.
253 struct VirtualInheritance
: virtual Empty
{
259 VirtualInheritance v3
;
263 void take(VirtualInBase
&);
264 void take(VirtualInVBase
&);
265 void take(VirtualInheritance
&);
267 void UnionsBarrier3(U3
&u
) {
268 // CHECK-NEW-NOT: call ptr @llvm.launder.invariant.group.p0(ptr
271 // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr
272 // CHECK-NEW: call void @_Z4takeR13VirtualInBase(
274 // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr
275 // CHECK-NEW: call void @_Z4takeR13VirtualInBase(
278 // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr
279 // CHECK-NEW: call void @_Z4takeR18VirtualInheritance(
283 // CHECK-NEW-LABEL: define{{.*}} void @_Z7comparev()
287 // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr
290 // CHECK-NEW: %[[a:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr
291 // CHECK-NEW: %[[b:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr
292 // CHECK-NEW: %cmp = icmp eq ptr %[[a]], %[[b]]
297 // CHECK-NEW-LABEL: compare2
298 bool compare2(A
*a
, A
*a2
) {
299 // CHECK-NEW: %[[a:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr
300 // CHECK-NEW: %[[b:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr
301 // CHECK-NEW: %cmp = icmp ult ptr %[[a]], %[[b]]
304 // CHECK-NEW-LABEL: compareIntPointers
305 bool compareIntPointers(int *a
, int *b
) {
306 // CHECK-NEW-NOT: call ptr @llvm.strip.invariant.group
310 struct HoldingOtherVirtuals
{
314 // There is no need to add barriers for comparision of pointer to classes
315 // that are not dynamic.
316 // CHECK-NEW-LABEL: compare5
317 bool compare5(HoldingOtherVirtuals
*a
, HoldingOtherVirtuals
*b
) {
318 // CHECK-NEW-NOT: call ptr @llvm.strip.invariant.group
321 // CHECK-NEW-LABEL: compareNull
322 bool compareNull(A
*a
) {
323 // CHECK-NEW-NOT: call ptr @llvm.strip.invariant.group
333 // We have to also introduce the barriers if comparing pointers to incomplete
335 // CHECK-NEW-LABEL: define{{.*}} zeroext i1 @_Z8compare4P1XS0_
336 bool compare4(X
*x
, X
*x2
) {
337 // CHECK-NEW: %[[x:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr
338 // CHECK-NEW: %[[x2:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr
339 // CHECK-NEW: %cmp = icmp eq ptr %[[x]], %[[x2]]
343 // CHECK-NEW-LABEL: define{{.*}} void @_Z7member1P20HoldingOtherVirtuals(
344 void member1(HoldingOtherVirtuals
*p
) {
346 // CHECK-NEW-NOT: call ptr @llvm.strip.invariant.group.p0(
350 // CHECK-NEW-LABEL: member2
352 // CHECK-NEW: call ptr @llvm.strip.invariant.group.p0
356 // Check if from comparison of addresses of member we can't infer the equality
358 // CHECK-NEW-LABEL: @_Z18testCompareMembersv(
359 void testCompareMembers() {
360 // CHECK-NEW: [[AP:%.*]] = alloca ptr
361 // CHECK-NEW: [[APM:%.*]] = alloca ptr
362 // CHECK-NEW: [[BP:%.*]] = alloca ptr
363 // CHECK-NEW: [[BPM:%.*]] = alloca ptr
366 // CHECK-NEW: call void %{{.*}}(ptr {{[^,]*}} %{{.*}})
368 // CHECK-NEW: [[TMP7:%.*]] = load ptr, ptr [[AP]]
369 // CHECK-NEW: [[TMP9:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[TMP7]])
370 // CHECK-NEW: [[M:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[TMP9]], i32 0, i32 1
371 // CHECK-NEW: store ptr [[M]], ptr [[APM]]
372 int *const apm
= &ap
->m
;
376 // CHECK-NEW: [[TMP20:%.*]] = load ptr, ptr [[BP]]
377 // CHECK-NEW: [[TMP23:%.*]] = call ptr @llvm.strip.invariant.group.p0(ptr [[TMP20]])
378 // CHECK-NEW: [[M4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[TMP23]], i32 0, i32 1
379 // CHECK-NEW: store ptr [[M4]], ptr [[BPM]]
380 int *const bpm
= &bp
->m
;
382 // CHECK-NEW: [[TMP25:%.*]] = load ptr, ptr [[APM]]
383 // CHECK-NEW: [[TMP26:%.*]] = load ptr, ptr [[BPM]]
384 // CHECK-NEW-NOT: strip.invariant.group
385 // CHECK-NEW-NOT: launder.invariant.group
386 // CHECK-NEW: [[CMP:%.*]] = icmp eq ptr [[TMP25]], [[TMP26]]
392 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast1P1A(ptr
393 void testCast1(A
*a
) {
394 // Here we get rid of dynamic info
395 // CHECK-NEW: call ptr @llvm.strip.invariant.group
398 // CHECK-NEW: call ptr @llvm.strip.invariant.group
399 auto i2
= (uintptr_t)a
;
402 // CHECK-NEW-NOT: @llvm.strip.invariant.group
403 // CHECK-NEW-NOT: @llvm.launder.invariant.group
405 // The information is already stripped
406 auto i
= (uintptr_t)v
;
410 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast2P10Incomplete(ptr
411 void testCast2(Incomplete
*I
) {
412 // Here we get rid of potential dynamic info
413 // CHECK-NEW: call ptr @llvm.strip.invariant.group
416 // CHECK-NEW: call ptr @llvm.strip.invariant.group
417 auto i2
= (uintptr_t)I
;
420 // CHECK-NEW-NOT: @llvm.strip.invariant.group
421 // CHECK-NEW-NOT: @llvm.launder.invariant.group
423 // The information is already stripped
424 auto i
= (uintptr_t)v
;
427 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast3y(
428 void testCast3(uintptr_t i
) {
429 // CHECK-NEW-NOT: @llvm.strip.invariant.group
430 // CHECK-NEW: @llvm.launder.invariant.group
434 auto *v2
= (void *)i
;
436 // CHECK-NEW: @llvm.launder.invariant.group
440 // CHECK-NEW-NOT: @llvm.launder.invariant.group
441 auto *v3
= (void *)i
;
445 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast4y(
446 void testCast4(uintptr_t i
) {
447 // CHECK-NEW-NOT: @llvm.strip.invariant.group
448 // CHECK-NEW: @llvm.launder.invariant.group
449 auto *a3
= (Incomplete
*)i
;
452 // CHECK-NEW: @llvm.launder.invariant.group
453 auto *v2
= (void *)i
;
454 // CHECK-NEW-NOT: @llvm.launder.invariant.group
455 auto *a2
= (Incomplete
*)v2
;
459 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast5P1B(
460 void testCast5(B
*b
) {
461 // CHECK-NEW-NOT: @llvm.strip.invariant.group
462 // CHECK-NEW-NOT: @llvm.launder.invariant.group
470 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast6P1A(
471 void testCast6(A
*a
) {
473 // CHECK-NEW: @llvm.strip.invariant.group
474 auto *I
= (Incomplete
*)a
;
476 // CHECK-NEW: @llvm.launder.invariant.group
480 // CHECK-NEW: @llvm.strip.invariant.group
481 auto *E
= (Empty
*)a
;
484 // CHECK-NEW: @llvm.launder.invariant.group
488 // CHECK-NEW-NOT: @llvm.strip.invariant.group
489 auto i
= (uintptr_t)E
;
494 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast7P10Incomplete(
495 void testCast7(Incomplete
*I
) {
496 // CHECK-NEW-NOT: @llvm.strip.invariant.group
498 // Incomplete2 could be dynamic where Incomplete may not be dynamic, thus
499 // launder is needed. We don't strip firstly because launder is sufficient.
501 // CHECK-NEW: @llvm.launder.invariant.group
502 auto *I2
= (Incomplete2
*)I
;
504 // CHECK-NEW-LABEL: ret void
507 template <typename Base
>
508 struct PossiblyDerivingFromDynamicBase
: Base
{
511 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast8P10Incomplete(
512 void testCast8(Incomplete
*I
) {
513 // CHECK-NEW-NOT: @llvm.strip.invariant.group
514 // CHECK-NEW: @llvm.launder.invariant.group
515 auto *P
= (PossiblyDerivingFromDynamicBase
<Incomplete
> *)I
;
518 // CHECK-NEW: @llvm.launder.invariant.group
519 auto *P2
= (PossiblyDerivingFromDynamicBase
<Empty
> *)I
;
522 // CHECK-NEW: @llvm.launder.invariant.group
523 auto *P3
= (PossiblyDerivingFromDynamicBase
<A
> *)I
;
526 // CHECK-NEW-NOT: @llvm.launder.invariant.group
529 // CHECK-NEW-LABEL: ret void
532 // CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast9
533 void testCast9(PossiblyDerivingFromDynamicBase
<Incomplete
> *P
) {
534 // CHECK-NEW: @llvm.strip.invariant.group
537 // CHECK-NEW-LABEL: ret void
541 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev(
542 // CHECK-DTORS-NOT: call ptr @llvm.launder.invariant.group.p0(
543 // CHECK-DTORS-LABEL: {{^}}}
545 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic2D2Ev(
546 // CHECK-DTORS-NOT: invariant.barrier
547 // CHECK-DTORS-LABEL: {{^}}}
549 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticD2Ev
550 // CHECK-DTORS-NOT: call ptr @llvm.launder.invariant.group.p0(
551 // CHECK-DTORS-LABEL: {{^}}}
553 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleD2Ev(
555 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase2D2Ev(
556 // CHECK-DTORS: call ptr @llvm.launder.invariant.group.p0(
557 // CHECK-DTORS-LABEL: {{^}}}
559 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1D2Ev
560 // CHECK-DTORS: call ptr @llvm.launder.invariant.group.p0(
561 // CHECK-DTORS-LABEL: {{^}}}
563 // CHECK-DTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedD2Ev
564 // CHECK-DTORS-NOT: call ptr @llvm.launder.invariant.group.p0(
565 // CHECK-DTORS-LABEL: {{^}}}
567 // CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:[0-9]+]], ![[SEC:[0-9]+]]{{.*}}}
569 // CHECK-LINK-REQ: ![[FIRST]] = !{i32 1, !"StrictVTablePointers", i32 1}
570 // CHECK-LINK-REQ: ![[SEC]] = !{i32 3, !"StrictVTablePointersRequirement", ![[META:.*]]}
571 // CHECK-LINK-REQ: ![[META]] = !{!"StrictVTablePointers", i32 1}