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