177 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOSIZE2// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - -Oz -disable-llvm-passes | FileCheck %s --check-prefixes=CHECK,CHECK-SIZE3 4void t1(int *a) {5 delete a;6}7 8struct S {9 int a;10};11 12// POD types.13 14// CHECK-LABEL: define{{.*}} void @_Z2t3P1S15void t3(S *s) {16 // CHECK: icmp {{.*}} null17 // CHECK: br i118 19 // CHECK: call void @_ZdlPvm20 21 // Check the delete is inside the 'if !null' check unless we're optimizing22 // for size. FIXME: We could omit the branch entirely in this case.23 // CHECK-NOSIZE-NEXT: br24 // CHECK-SIZE-NEXT: ret25 delete s;26}27 28// Non-POD29struct T {30 ~T();31 int a;32};33 34// CHECK-LABEL: define{{.*}} void @_Z2t4P1T35void t4(T *t) {36 // CHECK: call void @_ZN1TD1Ev37 // CHECK-SIZE-NEXT: br38 // CHECK: call void @_ZdlPvm39 delete t;40}41 42// PR510243template <typename T>44class A {45 public: operator T *() const;46};47 48void f() {49 A<char*> a;50 51 delete a;52}53 54namespace test0 {55 struct A {56 void *operator new(__SIZE_TYPE__ sz);57 void operator delete(void *p) { ::operator delete(p); }58 ~A() {}59 };60 61 // CHECK-LABEL: define{{.*}} void @_ZN5test04testEPNS_1AE(62 void test(A *a) {63 // CHECK: call void @_ZN5test01AD1Ev64 // CHECK-SIZE-NEXT: br65 // CHECK: call void @_ZN5test01AdlEPv66 delete a;67 }68 69 // CHECK-LABEL: define linkonce_odr void @_ZN5test01AD1Ev(ptr {{[^,]*}} %this) unnamed_addr70 // CHECK-LABEL: define linkonce_odr void @_ZN5test01AdlEPv71}72 73namespace test1 {74 struct A {75 int x;76 ~A();77 };78 79 // CHECK-LABEL: define{{.*}} void @_ZN5test11fEPA10_A20_NS_1AE(80 void f(A (*arr)[10][20]) {81 delete [] arr;82 // CHECK: icmp eq ptr [[PTR:%.*]], null83 // CHECK-NEXT: br i184 85 // CHECK: [[ALLOC:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 -886 // CHECK-NEXT: [[COUNT:%.*]] = load i64, ptr [[ALLOC]]87 // CHECK: [[END:%.*]] = getelementptr inbounds [[A:%.*]], ptr [[PTR]], i64 [[COUNT]]88 // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq ptr [[PTR]], [[END]]89 // CHECK-NEXT: br i1 [[ISEMPTY]],90 // CHECK: [[PAST:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]91 // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], ptr [[PAST]], i64 -192 // CHECK-NEXT: call void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[CUR]])93 // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[PTR]]94 // CHECK-NEXT: br i1 [[ISDONE]]95 // CHECK: [[MUL:%.*]] = mul i64 4, [[COUNT]]96 // CHECK-NEXT: [[SIZE:%.*]] = add i64 [[MUL]], 897 // CHECK-NEXT: call void @_ZdaPvm(ptr noundef [[ALLOC]], i64 noundef [[SIZE]])98 }99 100 // CHECK-LABEL: define{{.*}} void @_ZN5test11gEPA_NS_1AE(101 void g(A (*arr)[]) {102 delete [] arr;103 // CHECK: icmp eq ptr [[PTR:%.*]], null104 // CHECK-NEXT: br i1105 106 // CHECK: [[ALLOC:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 -8107 // CHECK-NEXT: [[COUNT:%.*]] = load i64, ptr [[ALLOC]]108 // CHECK: [[END:%.*]] = getelementptr inbounds [[A:%.*]], ptr [[PTR]], i64 [[COUNT]]109 // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq ptr [[PTR]], [[END]]110 // CHECK-NEXT: br i1 [[ISEMPTY]],111 // CHECK: [[PAST:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]112 // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], ptr [[PAST]], i64 -1113 // CHECK-NEXT: call void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[CUR]])114 // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[PTR]]115 // CHECK-NEXT: br i1 [[ISDONE]]116 // CHECK: call void @_ZdaPv(ptr noundef [[ALLOC]])117 }118}119 120namespace test2 {121 // CHECK-LABEL: define{{.*}} void @_ZN5test21fEPb122 void f(bool *b) {123 // CHECK: call void @_ZdlPvm(ptr{{.*}}i64124 delete b;125 // CHECK: call void @_ZdaPv(ptr126 delete [] b;127 }128}129 130namespace test3 {131 void f(int a[10][20]) {132 // CHECK: call void @_ZdaPv(ptr133 delete a;134 }135}136 137namespace test4 {138 // PR10341: ::delete with a virtual destructor139 struct X {140 virtual ~X();141 void operator delete (void *);142 };143 144 // CHECK-LABEL: define{{.*}} void @_ZN5test421global_delete_virtualEPNS_1XE145 void global_delete_virtual(X *xp) {146 // Load the offset-to-top from the vtable and apply it.147 // This has to be done first because the dtor can mess it up.148 // CHECK: [[XP:%.*]] = load ptr, ptr [[XP_ADDR:%.*]]149 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[XP]]150 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i64, ptr [[VTABLE]], i64 -2151 // CHECK-NEXT: [[OFFSET:%.*]] = load i64, ptr [[T0]], align 8152 // CHECK-NEXT: [[ALLOCATED:%.*]] = getelementptr inbounds i8, ptr [[XP]], i64 [[OFFSET]]153 // Load the complete-object destructor (not the deleting destructor)154 // and call noundef it.155 // CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[XP:%.*]]156 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0157 // CHECK-NEXT: [[DTOR:%.*]] = load ptr, ptr [[T0]]158 // CHECK-NEXT: call void [[DTOR]](ptr {{[^,]*}} [[OBJ:%.*]])159 // Call the global operator delete.160 // CHECK-NEXT: call void @_ZdlPvm(ptr noundef [[ALLOCATED]], i64 noundef 8) [[NUW:#[0-9]+]]161 ::delete xp;162 }163}164 165namespace test5 {166 struct Incomplete;167 // CHECK-LABEL: define{{.*}} void @_ZN5test523array_delete_incompleteEPNS_10IncompleteES1_168 void array_delete_incomplete(Incomplete *p1, Incomplete *p2) {169 // CHECK: call void @_ZdlPv170 delete p1;171 // CHECK: call void @_ZdaPv172 delete [] p2;173 }174}175 176// CHECK: attributes [[NUW]] = {{[{].*}} nounwind {{.*[}]}}177