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