]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
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: 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: 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: define linkonce_odr void @_ZN5test01AD1Ev(%"struct.test0::A"* %this) unnamed_addr | |
58 | // CHECK: define linkonce_odr void @_ZN5test01AdlEPv | |
59 | } | |
60 | ||
61 | namespace test1 { | |
62 | struct A { | |
63 | int x; | |
64 | ~A(); | |
65 | }; | |
66 | ||
67 | // CHECK: 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]]]]* [[PTR]], i32 0, i32 0, i32 0 | |
74 | // CHECK-NEXT: [[T0:%.*]] = bitcast [[A]]* [[BEGIN]] to i8* | |
75 | // CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds i8* [[T0]], i64 -8 | |
76 | // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[ALLOC]] to i64* | |
77 | // CHECK-NEXT: [[COUNT:%.*]] = load i64* [[T1]] | |
78 | // CHECK: [[END:%.*]] = getelementptr inbounds [[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]]* [[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: 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: 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** [[T0]] | |
120 | // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds i64* [[VTABLE]], i64 -2 | |
121 | // CHECK-NEXT: [[OFFSET:%.*]] = load i64* [[T0]], align 8 | |
122 | // CHECK-NEXT: [[T0:%.*]] = bitcast [[X]]* [[XP]] to i8* | |
123 | // CHECK-NEXT: [[ALLOCATED:%.*]] = getelementptr inbounds 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]]*)*** [[T0]] | |
128 | // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds void ([[X]]*)** [[VTABLE]], i64 0 | |
129 | // CHECK-NEXT: [[DTOR:%.*]] = load 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]]) nounwind | |
133 | ::delete xp; | |
134 | } | |
135 | } | |
136 | ||
137 | namespace test5 { | |
138 | struct Incomplete; | |
139 | // CHECK: 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 | } |