1 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOSIZE
2 // RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-apple-darwin10 %s -emit-llvm -o - -Oz -disable-llvm-passes | FileCheck %s --check-prefixes=CHECK,CHECK-SIZE
3
t1(int * a)4 void t1(int *a) {
5 delete a;
6 }
7
8 struct S {
9 int a;
10 };
11
12 // POD types.
13
14 // CHECK-LABEL: define{{.*}} void @_Z2t3P1S
t3(S * s)15 void t3(S *s) {
16 // CHECK: icmp {{.*}} null
17 // CHECK: br i1
18
19 // CHECK: bitcast
20 // CHECK-NEXT: call void @_ZdlPv
21
22 // Check the delete is inside the 'if !null' check unless we're optimizing
23 // for size. FIXME: We could omit the branch entirely in this case.
24 // CHECK-NOSIZE-NEXT: br
25 // CHECK-SIZE-NEXT: ret
26 delete s;
27 }
28
29 // Non-POD
30 struct T {
31 ~T();
32 int a;
33 };
34
35 // CHECK-LABEL: define{{.*}} void @_Z2t4P1T
t4(T * t)36 void t4(T *t) {
37 // CHECK: call void @_ZN1TD1Ev
38 // CHECK-NOSIZE-NEXT: bitcast
39 // CHECK-SIZE-NEXT: br
40 // CHECK-SIZE: bitcast
41 // CHECK-NEXT: call void @_ZdlPv
42 delete t;
43 }
44
45 // PR5102
46 template <typename T>
47 class A {
48 public: operator T *() const;
49 };
50
f()51 void f() {
52 A<char*> a;
53
54 delete a;
55 }
56
57 namespace test0 {
58 struct A {
59 void *operator new(__SIZE_TYPE__ sz);
operator deletetest0::A60 void operator delete(void *p) { ::operator delete(p); }
~Atest0::A61 ~A() {}
62 };
63
64 // CHECK-LABEL: define{{.*}} void @_ZN5test04testEPNS_1AE(
test(A * a)65 void test(A *a) {
66 // CHECK: call void @_ZN5test01AD1Ev
67 // CHECK-NOSIZE-NEXT: bitcast
68 // CHECK-SIZE-NEXT: br
69 // CHECK-SIZE: bitcast
70 // CHECK-NEXT: call void @_ZN5test01AdlEPv
71 delete a;
72 }
73
74 // CHECK-LABEL: define linkonce_odr void @_ZN5test01AD1Ev(%"struct.test0::A"* {{[^,]*}} %this) unnamed_addr
75 // CHECK-LABEL: define linkonce_odr void @_ZN5test01AdlEPv
76 }
77
78 namespace test1 {
79 struct A {
80 int x;
81 ~A();
82 };
83
84 // CHECK-LABEL: define{{.*}} void @_ZN5test14testEPA10_A20_NS_1AE(
test(A (* arr)[10][20])85 void test(A (*arr)[10][20]) {
86 delete [] arr;
87 // CHECK: icmp eq [10 x [20 x [[A:%.*]]]]* [[PTR:%.*]], null
88 // CHECK-NEXT: br i1
89
90 // CHECK: [[BEGIN:%.*]] = getelementptr inbounds [10 x [20 x [[A]]]], [10 x [20 x [[A]]]]* [[PTR]], i32 0, i32 0, i32 0
91 // CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[BEGIN]] to i8*
92 // CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 -8
93 // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[ALLOC]] to i64*
94 // CHECK-NEXT: [[COUNT:%.*]] = load i64, i64* [[T1]]
95 // CHECK: [[END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[BEGIN]], i64 [[COUNT]]
96 // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq [[A]]* [[BEGIN]], [[END]]
97 // CHECK-NEXT: br i1 [[ISEMPTY]],
98 // CHECK: [[PAST:%.*]] = phi [[A]]* [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ]
99 // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], [[A]]* [[PAST]], i64 -1
100 // CHECK-NEXT: call void @_ZN5test11AD1Ev([[A]]* {{[^,]*}} [[CUR]])
101 // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]]
102 // CHECK-NEXT: br i1 [[ISDONE]]
103 // CHECK: call void @_ZdaPv(i8* noundef [[ALLOC]])
104 }
105 }
106
107 namespace test2 {
108 // CHECK-LABEL: define{{.*}} void @_ZN5test21fEPb
f(bool * b)109 void f(bool *b) {
110 // CHECK: call void @_ZdlPv(i8*
111 delete b;
112 // CHECK: call void @_ZdaPv(i8*
113 delete [] b;
114 }
115 }
116
117 namespace test3 {
f(int a[10][20])118 void f(int a[10][20]) {
119 // CHECK: call void @_ZdaPv(i8*
120 delete a;
121 }
122 }
123
124 namespace test4 {
125 // PR10341: ::delete with a virtual destructor
126 struct X {
127 virtual ~X();
128 void operator delete (void *);
129 };
130
131 // CHECK-LABEL: define{{.*}} void @_ZN5test421global_delete_virtualEPNS_1XE
global_delete_virtual(X * xp)132 void global_delete_virtual(X *xp) {
133 // Load the offset-to-top from the vtable and apply it.
134 // This has to be done first because the dtor can mess it up.
135 // CHECK: [[T0:%.*]] = bitcast [[X:%.*]]* [[XP:%.*]] to i64**
136 // CHECK-NEXT: [[VTABLE:%.*]] = load i64*, i64** [[T0]]
137 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i64, i64* [[VTABLE]], i64 -2
138 // CHECK-NEXT: [[OFFSET:%.*]] = load i64, i64* [[T0]], align 8
139 // CHECK-NEXT: [[T0:%.*]] = bitcast [[X]]* [[XP]] to i8*
140 // CHECK-NEXT: [[ALLOCATED:%.*]] = getelementptr inbounds i8, i8* [[T0]], i64 [[OFFSET]]
141 // Load the complete-object destructor (not the deleting destructor)
142 // and call noundef it.
143 // CHECK-NEXT: [[T0:%.*]] = bitcast [[X:%.*]]* [[XP:%.*]] to void ([[X]]*)***
144 // CHECK-NEXT: [[VTABLE:%.*]] = load void ([[X]]*)**, void ([[X]]*)*** [[T0]]
145 // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds void ([[X]]*)*, void ([[X]]*)** [[VTABLE]], i64 0
146 // CHECK-NEXT: [[DTOR:%.*]] = load void ([[X]]*)*, void ([[X]]*)** [[T0]]
147 // CHECK-NEXT: call void [[DTOR]]([[X]]* {{[^,]*}} [[OBJ:%.*]])
148 // Call the global operator delete.
149 // CHECK-NEXT: call void @_ZdlPv(i8* noundef [[ALLOCATED]]) [[NUW:#[0-9]+]]
150 ::delete xp;
151 }
152 }
153
154 namespace test5 {
155 struct Incomplete;
156 // CHECK-LABEL: define{{.*}} void @_ZN5test523array_delete_incompleteEPNS_10IncompleteES1_
array_delete_incomplete(Incomplete * p1,Incomplete * p2)157 void array_delete_incomplete(Incomplete *p1, Incomplete *p2) {
158 // CHECK: call void @_ZdlPv
159 delete p1;
160 // CHECK: call void @_ZdaPv
161 delete [] p2;
162 }
163 }
164
165 // CHECK: attributes [[NUW]] = {{[{].*}} nounwind {{.*[}]}}
166