brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.1 KiB · ade8172 Raw
572 lines · cpp
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.ll2// RUN: FileCheck --check-prefix=CHECK-CTORS %s < %t.ll3// RUN: FileCheck --check-prefix=CHECK-NEW %s < %t.ll4// RUN: FileCheck --check-prefix=CHECK-DTORS %s < %t.ll5// RUN: FileCheck --check-prefix=CHECK-LINK-REQ %s < %t.ll6 7typedef __typeof__(sizeof(0)) size_t;8void *operator new(size_t, void *) throw();9using uintptr_t = unsigned long long;10 11struct NotTrivialDtor {12  ~NotTrivialDtor();13};14 15struct DynamicBase1 {16  NotTrivialDtor obj;17  virtual void foo();18};19 20struct DynamicDerived : DynamicBase1 {21  void foo() override;22};23 24struct DynamicBase2 {25  virtual void bar();26  ~DynamicBase2() {27    bar();28  }29};30 31struct DynamicDerivedMultiple : DynamicBase1, DynamicBase2 {32  void foo() override;33  void bar() override;34};35 36struct StaticBase {37  NotTrivialDtor obj;38  void bar();39};40 41struct DynamicFromStatic : StaticBase {42  virtual void bar();43};44 45struct DynamicFromVirtualStatic1 : virtual StaticBase {46};47 48struct DynamicFromVirtualStatic2 : virtual StaticBase {49};50 51struct DynamicFrom2Virtuals : DynamicFromVirtualStatic1,52                              DynamicFromVirtualStatic2 {53};54 55// CHECK-NEW-LABEL: define{{.*}} void @_Z12LocalObjectsv()56// CHECK-NEW-NOT: @llvm.launder.invariant.group.p0(57// CHECK-NEW-LABEL: {{^}}}58void 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 82struct DynamicFromVirtualStatic1;83// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic1C1Ev84// CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0(85// CHECK-CTORS-LABEL: {{^}}}86 87struct DynamicFrom2Virtuals;88// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN20DynamicFrom2VirtualsC1Ev89// CHECK-CTORS: call ptr @llvm.launder.invariant.group.p0(90// CHECK-CTORS-LABEL: {{^}}}91 92// CHECK-NEW-LABEL: define{{.*}} void @_Z9Pointers1v()93// CHECK-NEW-NOT: @llvm.launder.invariant.group.p0(94// CHECK-NEW-LABEL: call void @_ZN12DynamicBase1C1Ev(95 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: {{^}}}99void Pointers1() {100  DynamicBase1 *DB = new DynamicBase1;101  DB->foo();102 103  DynamicDerived *DD = new (DB) DynamicDerived;104  DD->foo();105  DD->~DynamicDerived();106}107 108// CHECK-NEW-LABEL: define{{.*}} void @_Z14HackingObjectsv()109// CHECK-NEW:  call void @_ZN12DynamicBase1C1Ev110// 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: {{^}}}115void HackingObjects() {116  DynamicBase1 DB;117  DB.foo();118 119  DynamicDerived *DB2 = new (&DB) DynamicDerived;120  // Using DB now is prohibited.121  DB2->foo();122  DB2->~DynamicDerived();123 124  // We have to get back to the previous type to avoid calling wrong destructor125  new (&DB) DynamicBase1;126  DB.foo();127}128 129/*** Testing Constructors ***/130struct DynamicBase1;131// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1C2Ev(132// CHECK-CTORS-NOT: call ptr @llvm.launder.invariant.group.p0(133// CHECK-CTORS-LABEL: {{^}}}134 135struct DynamicDerived;136 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]])141 142// CHECK-CTORS: store {{.*}} %[[THIS0]]143// CHECK-CTORS-LABEL: {{^}}}144 145struct DynamicDerivedMultiple;146// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleC2Ev(147 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]])151 152// CHECK-CTORS: call ptr @llvm.launder.invariant.group.p0(153 154// CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev(155// CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0156 157// CHECK-CTORS: store ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV22DynamicDerivedMultiple, i32 0, i32 0, i32 2), ptr %[[THIS0]]158// CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, ptr %[[THIS0]], i64 16159 160// CHECK-CTORS: store ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV22DynamicDerivedMultiple, i32 0, i32 1, i32 2), ptr %[[THIS_ADD]]161// CHECK-CTORS-LABEL: {{^}}}162 163struct DynamicFromStatic;164// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticC2Ev(165// CHECK-CTORS-NOT: @llvm.launder.invariant.group.p0(166// CHECK-CTORS-LABEL: {{^}}}167 168struct A {169  virtual void foo();170  int m;171};172struct B : A {173  void foo() override;174};175 176union U {177  A a;178  B b;179};180 181void changeToB(U *u);182void changeToA(U *u);183 184void g2(A *a) {185  a->foo();186}187// We have to guard access to union fields with invariant.group, because188// it is very easy to skip the barrier with unions. In this example the inlined189// g2 will produce loads with the same !invariant.group metadata, and190// u->a and u->b would use the same pointer.191// CHECK-NEW-LABEL: define{{.*}} void @_Z14UnionsBarriersP1U192void UnionsBarriers(U *u) {193  // CHECK-NEW: call void @_Z9changeToBP1U(194  changeToB(u);195  // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr196  // CHECK-NEW: call void @_Z2g2P1A(ptr197  g2(&u->b);198  // CHECK-NEW: call void @_Z9changeToAP1U(ptr199  changeToA(u);200  // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr201  // call void @_Z2g2P1A(ptr %a)202  g2(&u->a);203  // CHECK-NEW-NOT: call ptr @llvm.launder.invariant.group.p0(ptr204}205 206struct HoldingVirtuals {207  A a;208};209 210struct Empty {};211struct AnotherEmpty {212  Empty e;213};214union NoVptrs {215  int a;216  AnotherEmpty empty;217};218void take(AnotherEmpty &);219 220// CHECK-NEW-LABEL: noBarriers221void noBarriers(NoVptrs &noVptrs) {222  // CHECK-NEW-NOT: call ptr @llvm.launder.invariant.group.p0(ptr223  // CHECK-NEW: 42224  noVptrs.a += 42;225  // CHECK-NEW-NOT: call ptr @llvm.launder.invariant.group.p0(ptr226  // CHECK-NEW: call void @_Z4takeR12AnotherEmpty(227  take(noVptrs.empty);228}229 230union U2 {231  HoldingVirtuals h;232  int z;233};234void take(HoldingVirtuals &);235 236// CHECK-NEW-LABEL: define{{.*}} void @_Z15UnionsBarriers2R2U2237void UnionsBarriers2(U2 &u) {238  // CHECK-NEW-NOT: call ptr @llvm.launder.invariant.group.p0(ptr239  // CHECK-NEW: 42240  u.z += 42;241  // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr242  // CHECK-NEW: call void @_Z4takeR15HoldingVirtuals(243  take(u.h);244}245 246struct VirtualInBase : HoldingVirtuals, Empty {247};248 249struct VirtualInVBase : virtual Empty, virtual HoldingVirtuals {250};251 252// It has vtable by virtual inheritance.253struct VirtualInheritance : virtual Empty {254};255 256union U3 {257  VirtualInBase v1;258  VirtualInBase v2;259  VirtualInheritance v3;260  int z;261};262 263void take(VirtualInBase &);264void take(VirtualInVBase &);265void take(VirtualInheritance &);266 267void UnionsBarrier3(U3 &u) {268  // CHECK-NEW-NOT: call ptr @llvm.launder.invariant.group.p0(ptr269  // CHECK-NEW: 42270  u.z += 42;271  // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr272  // CHECK-NEW: call void @_Z4takeR13VirtualInBase(273  take(u.v1);274  // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr275  // CHECK-NEW: call void @_Z4takeR13VirtualInBase(276  take(u.v2);277 278  // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr279  // CHECK-NEW: call void @_Z4takeR18VirtualInheritance(280  take(u.v3);281}282 283// CHECK-NEW-LABEL: define{{.*}} void @_Z7comparev()284void compare() {285  A *a = new A;286  a->foo();287  // CHECK-NEW: call ptr @llvm.launder.invariant.group.p0(ptr288  A *b = new (a) B;289 290  // CHECK-NEW: %[[a:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr291  // CHECK-NEW: %[[b:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr292  // CHECK-NEW: %cmp = icmp eq ptr %[[a]], %[[b]]293  if (a == b)294    b->foo();295}296 297// CHECK-NEW-LABEL: compare2298bool compare2(A *a, A *a2) {299  // CHECK-NEW: %[[a:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr300  // CHECK-NEW: %[[b:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr301  // CHECK-NEW: %cmp = icmp ult ptr %[[a]], %[[b]]302  return a < a2;303}304// CHECK-NEW-LABEL: compareIntPointers305bool compareIntPointers(int *a, int *b) {306  // CHECK-NEW-NOT: call ptr @llvm.strip.invariant.group307  return a == b;308}309 310struct HoldingOtherVirtuals {311  B b;312};313 314// There is no need to add barriers for comparision of pointer to classes315// that are not dynamic.316// CHECK-NEW-LABEL: compare5317bool compare5(HoldingOtherVirtuals *a, HoldingOtherVirtuals *b) {318  // CHECK-NEW-NOT: call ptr @llvm.strip.invariant.group319  return a == b;320}321// CHECK-NEW-LABEL: compareNull322bool compareNull(A *a) {323  // CHECK-NEW-NOT: call ptr @llvm.strip.invariant.group324 325  if (a != nullptr)326    return false;327  if (!a)328    return false;329  return a == nullptr;330}331 332struct X;333// We have to also introduce the barriers if comparing pointers to incomplete334// objects335// CHECK-NEW-LABEL: define{{.*}} zeroext i1 @_Z8compare4P1XS0_336bool compare4(X *x, X *x2) {337  // CHECK-NEW: %[[x:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr338  // CHECK-NEW: %[[x2:.*]] = call ptr @llvm.strip.invariant.group.p0(ptr339  // CHECK-NEW: %cmp = icmp eq ptr %[[x]], %[[x2]]340  return x == x2;341}342 343// CHECK-NEW-LABEL: define{{.*}} void @_Z7member1P20HoldingOtherVirtuals(344void member1(HoldingOtherVirtuals *p) {345 346  // CHECK-NEW-NOT: call ptr @llvm.strip.invariant.group.p0(347  (void)p->b;348}349 350// CHECK-NEW-LABEL: member2351void member2(A *a) {352  // CHECK-NEW: call ptr @llvm.strip.invariant.group.p0353  (void)a->m;354}355 356// Check if from comparison of addresses of member we can't infer the equality357// of ap and bp.358// CHECK-NEW-LABEL: @_Z18testCompareMembersv(359void testCompareMembers() {360  // CHECK-NEW:    [[AP:%.*]] = alloca ptr361  // CHECK-NEW:    [[APM:%.*]] = alloca ptr362  // CHECK-NEW:    [[BP:%.*]] = alloca ptr363  // CHECK-NEW:    [[BPM:%.*]] = alloca ptr364 365  A *ap = new A;366  // CHECK-NEW:   call void %{{.*}}(ptr {{[^,]*}} %{{.*}})367  ap->foo();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 nuw [[STRUCT_A:%.*]], ptr [[TMP9]], i32 0, i32 1371  // CHECK-NEW:    store ptr [[M]], ptr [[APM]]372  int *const apm = &ap->m;373 374  B *bp = new (ap) B;375 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 nuw [[STRUCT_A]], ptr [[TMP23]], i32 0, i32 1379  // CHECK-NEW:    store ptr [[M4]], ptr [[BPM]]380  int *const bpm = &bp->m;381 382  // CHECK-NEW:    [[TMP25:%.*]] = load ptr, ptr [[APM]]383  // CHECK-NEW:    [[TMP26:%.*]] = load ptr, ptr [[BPM]]384  // CHECK-NEW-NOT: strip.invariant.group385  // CHECK-NEW-NOT: launder.invariant.group386  // CHECK-NEW:    [[CMP:%.*]] = icmp eq ptr [[TMP25]], [[TMP26]]387  if (apm == bpm) {388    bp->foo();389  }390}391 392// CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast1P1A(ptr393void testCast1(A *a) {394  // Here we get rid of dynamic info395  // CHECK-NEW: call ptr @llvm.strip.invariant.group396  auto *v = (void *)a;397 398  // CHECK-NEW: call ptr @llvm.strip.invariant.group399  auto i2 = (uintptr_t)a;400  (void)i2;401 402  // CHECK-NEW-NOT: @llvm.strip.invariant.group403  // CHECK-NEW-NOT: @llvm.launder.invariant.group404 405  // The information is already stripped406  auto i = (uintptr_t)v;407}408 409struct Incomplete;410// CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast2P10Incomplete(ptr411void testCast2(Incomplete *I) {412  // Here we get rid of potential dynamic info413  // CHECK-NEW: call ptr @llvm.strip.invariant.group414  auto *v = (void *)I;415 416  // CHECK-NEW: call ptr @llvm.strip.invariant.group417  auto i2 = (uintptr_t)I;418  (void)i2;419 420  // CHECK-NEW-NOT: @llvm.strip.invariant.group421  // CHECK-NEW-NOT: @llvm.launder.invariant.group422 423  // The information is already stripped424  auto i = (uintptr_t)v;425}426 427// CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast3y(428void testCast3(uintptr_t i) {429  // CHECK-NEW-NOT: @llvm.strip.invariant.group430  // CHECK-NEW: @llvm.launder.invariant.group431  A *a3 = (A *)i;432  (void)a3;433 434  auto *v2 = (void *)i;435 436  // CHECK-NEW: @llvm.launder.invariant.group437  A *a2 = (A *)v2;438  (void)a2;439 440  // CHECK-NEW-NOT: @llvm.launder.invariant.group441  auto *v3 = (void *)i;442  (void)v3;443}444 445// CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast4y(446void testCast4(uintptr_t i) {447  // CHECK-NEW-NOT: @llvm.strip.invariant.group448  // CHECK-NEW: @llvm.launder.invariant.group449  auto *a3 = (Incomplete *)i;450  (void)a3;451 452  // CHECK-NEW: @llvm.launder.invariant.group453  auto *v2 = (void *)i;454  // CHECK-NEW-NOT: @llvm.launder.invariant.group455  auto *a2 = (Incomplete *)v2;456  (void)a2;457}458 459// CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast5P1B(460void testCast5(B *b) {461  // CHECK-NEW-NOT: @llvm.strip.invariant.group462  // CHECK-NEW-NOT: @llvm.launder.invariant.group463  A *a = b;464  (void)a;465 466  auto *b2 = (B *)a;467  (void)b2;468}469 470// CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast6P1A(471void testCast6(A *a) {472 473  // CHECK-NEW: @llvm.strip.invariant.group474  auto *I = (Incomplete *)a;475  (void)I;476  // CHECK-NEW: @llvm.launder.invariant.group477  auto *a2 = (A *)I;478  (void)a2;479 480  // CHECK-NEW: @llvm.strip.invariant.group481  auto *E = (Empty *)a;482  (void)E;483 484  // CHECK-NEW: @llvm.launder.invariant.group485  auto *a3 = (A *)E;486  (void)a3;487 488  // CHECK-NEW-NOT: @llvm.strip.invariant.group489  auto i = (uintptr_t)E;490  (void)i;491}492 493class Incomplete2;494// CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast7P10Incomplete(495void testCast7(Incomplete *I) {496  // CHECK-NEW-NOT: @llvm.strip.invariant.group497 498  // Incomplete2 could be dynamic where Incomplete may not be dynamic, thus499  // launder is needed.  We don't strip firstly because launder is sufficient.500 501  // CHECK-NEW: @llvm.launder.invariant.group502  auto *I2 = (Incomplete2 *)I;503  (void)I2;504  // CHECK-NEW-LABEL: ret void505}506 507template <typename Base>508struct PossiblyDerivingFromDynamicBase : Base {509};510 511// CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast8P10Incomplete(512void testCast8(Incomplete *I) {513  // CHECK-NEW-NOT: @llvm.strip.invariant.group514  // CHECK-NEW: @llvm.launder.invariant.group515  auto *P = (PossiblyDerivingFromDynamicBase<Incomplete> *)I;516  (void)P;517 518  // CHECK-NEW: @llvm.launder.invariant.group519  auto *P2 = (PossiblyDerivingFromDynamicBase<Empty> *)I;520  (void)P2;521 522  // CHECK-NEW: @llvm.launder.invariant.group523  auto *P3 = (PossiblyDerivingFromDynamicBase<A> *)I;524  (void)P3;525 526  // CHECK-NEW-NOT: @llvm.launder.invariant.group527  auto *a3 = (A *)P3;528 529  // CHECK-NEW-LABEL: ret void530}531 532// CHECK-NEW-LABEL: define{{.*}} void @_Z9testCast9533void testCast9(PossiblyDerivingFromDynamicBase<Incomplete> *P) {534  // CHECK-NEW: @llvm.strip.invariant.group535  auto *V = (void *)P;536 537  // CHECK-NEW-LABEL: ret void538}539 540/** DTORS **/541// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN10StaticBaseD2Ev(542// CHECK-DTORS-NOT: call ptr @llvm.launder.invariant.group.p0(543// CHECK-DTORS-LABEL: {{^}}}544 545// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN25DynamicFromVirtualStatic2D2Ev(546// CHECK-DTORS-NOT: invariant.barrier547// CHECK-DTORS-LABEL: {{^}}}548 549// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN17DynamicFromStaticD2Ev550// CHECK-DTORS-NOT: call ptr @llvm.launder.invariant.group.p0(551// CHECK-DTORS-LABEL: {{^}}}552 553// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleD2Ev(554 555// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase2D2Ev(556// CHECK-DTORS: call ptr @llvm.launder.invariant.group.p0(557// CHECK-DTORS-LABEL: {{^}}}558 559// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN12DynamicBase1D2Ev560// CHECK-DTORS: call ptr @llvm.launder.invariant.group.p0(561// CHECK-DTORS-LABEL: {{^}}}562 563// CHECK-DTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedD2Ev564// CHECK-DTORS-NOT: call ptr @llvm.launder.invariant.group.p0(565// CHECK-DTORS-LABEL: {{^}}}566 567// CHECK-LINK-REQ: !llvm.module.flags = !{![[FIRST:[0-9]+]], ![[SEC:[0-9]+]]{{.*}}}568 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}572