Clang Project

clang_source_code/test/CodeGenCXX/cxx2a-destroying-delete.cpp
1// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ITANIUM
2// RUN: %clang_cc1 -std=c++2a -emit-llvm %s -triple x86_64-windows -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-MSABI
3
4namespace std {
5  using size_t = decltype(sizeof(0));
6  enum class align_val_t : size_t;
7  struct destroying_delete_t {};
8}
9
10struct A {
11  void *data;
12  ~A();
13  void operator delete(A*, std::destroying_delete_t);
14};
15void delete_A(A *a) { delete a; }
16// CHECK-LABEL: define {{.*}}delete_A
17// CHECK: %[[a:.*]] = load
18// CHECK: icmp eq %{{.*}} %[[a]], null
19// CHECK: br i1
20//
21// Ensure that we call the destroying delete and not the destructor.
22// CHECK-NOT: call
23// CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]])
24// CHECK-MSABI: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8
25// CHECK-NOT: call
26// CHECK: }
27
28struct B {
29  virtual ~B();
30  void operator delete(B*, std::destroying_delete_t);
31};
32void delete_B(B *b) { delete b; }
33// CHECK-LABEL: define {{.*}}delete_B
34// CHECK: %[[b:.*]] = load
35// CHECK: icmp eq %{{.*}} %[[b]], null
36// CHECK: br i1
37//
38// Ensure that we call the virtual destructor and not the operator delete.
39// CHECK-NOT: call
40// CHECK: %[[VTABLE:.*]] = load
41// CHECK: %[[DTOR:.*]] = load
42// CHECK: call {{void|i8\*}} %[[DTOR]](%{{.*}}* %[[b]]
43// CHECK-MSABI-SAME: , i32 1)
44// CHECK-NOT: call
45// CHECK: }
46
47struct Padding {
48  virtual void f();
49};
50
51struct C : Padding, A {};
52void delete_C(C *c) { delete c; }
53// Check that we perform a derived-to-base conversion on the parameter to 'operator delete'.
54// CHECK-LABEL: define {{.*}}delete_C
55// CHECK: %[[c:.*]] = load
56// CHECK: icmp eq %{{.*}} %[[c]], null
57// CHECK: br i1
58//
59// CHECK: %[[base:.*]] = getelementptr {{.*}}, i64 8
60// CHECK: %[[castbase:.*]] = bitcast {{.*}} %[[base]]
61//
62// CHECK: %[[a:.*]] = phi {{.*}} %[[castbase]]
63// CHECK: icmp eq %{{.*}} %[[a]], null
64// CHECK: br i1
65//
66// CHECK-NOT: call
67// CHECK-ITANIUM: call void @_ZN1AdlEPS_St19destroying_delete_t(%{{.*}}* %[[a]])
68// CHECK-MSABI: call void @"??3A@@SAXPEAU0@Udestroying_delete_t@std@@@Z"(%{{.*}}* %[[a]], i8
69// CHECK-NOT: call
70// CHECK: }
71
72struct VDel { virtual ~VDel(); };
73struct D : Padding, VDel, B {};
74void delete_D(D *d) { delete d; }
75// CHECK-LABEL: define {{.*}}delete_D
76// CHECK: %[[d:.*]] = load
77// CHECK: icmp eq %{{.*}} %[[d]], null
78// CHECK: br i1
79//
80// CHECK-NOT: call
81// For MS, we don't add a new vtable slot to the primary vtable for the virtual
82// destructor. Instead we cast to the VDel base class.
83// CHECK-MSABI: bitcast {{.*}} %[[d]]
84// CHECK-MSABI-NEXT: getelementptr {{.*}}, i64 8
85// CHECK-MSABI-NEXT: %[[d:.*]] = bitcast i8*
86//
87// CHECK: %[[VTABLE:.*]] = load
88// CHECK: %[[DTOR:.*]] = load
89//
90// CHECK: call {{void|i8\*}} %[[DTOR]](%{{.*}}* %[[d]]
91// CHECK-MSABI-SAME: , i32 1)
92// CHECK-NOT: call
93// CHECK: }
94
95struct E { void *data; };
96struct F { void operator delete(F *, std::destroying_delete_t, std::size_t, std::align_val_t); void *data; };
97struct alignas(16) G : E, F { void *data; };
98
99void delete_G(G *g) { delete g; }
100// CHECK-LABEL: define {{.*}}delete_G
101// CHECK-NOT: call
102// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t(%{{.*}}* %[[a]], i64 32, i64 16)
103// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"(%{{.*}}* %[[a]], i8 {{[^,]*}}, i64 32, i64 16)
104// CHECK-NOT: call
105// CHECK: }
106
107void call_in_dtor();
108
109struct H : G { virtual ~H(); } h;
110H::~H() { call_in_dtor(); }
111// CHECK-ITANIUM-LABEL: define void @_ZN1HD0Ev(
112// CHECK-ITANIUM-NOT: call
113// CHECK-ITANIUM: getelementptr {{.*}}, i64 24
114// CHECK-ITANIUM-NOT: call
115// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t({{.*}}, i64 48, i64 16)
116// CHECK-ITANIUM-NOT: call
117// CHECK-ITANIUM: }
118
119// CHECK-MSABI: define {{.*}} @"??_GH@@UEAAPEAXI@Z"(
120// CHECK-MSABI-NOT: call{{ }}
121// CHECK-MSABI: load i32
122// CHECK-MSABI: icmp eq i32 {{.*}}, 0
123// CHECK-MSABI: br i1
124//
125// CHECK-MSABI-NOT: call{{ }}
126// CHECK-MSABI: getelementptr {{.*}}, i64 24
127// CHECK-MSABI-NOT: call{{ }}
128// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 48, i64 16)
129// CHECK-MSABI: br label %[[RETURN:.*]]
130//
131// CHECK-MSABI: call void @"??1H@@UEAA@XZ"(
132// CHECK-MSABI: br label %[[RETURN]]
133//
134// CHECK-MSABI: }
135
136struct I : H { virtual ~I(); alignas(32) char buffer[32]; } i;
137I::~I() { call_in_dtor(); }
138// CHECK-ITANIUM-LABEL: define void @_ZN1ID0Ev(
139// CHECK-ITANIUM-NOT: call
140// CHECK-ITANIUM: getelementptr {{.*}}, i64 24
141// CHECK-ITANIUM-NOT: call
142// CHECK-ITANIUM: call void @_ZN1FdlEPS_St19destroying_delete_tmSt11align_val_t({{.*}}, i64 96, i64 32)
143// CHECK-ITANIUM-NOT: call
144// CHECK-ITANIUM: }
145
146// CHECK-MSABI: define {{.*}} @"??_GI@@UEAAPEAXI@Z"(
147// CHECK-MSABI-NOT: call{{ }}
148// CHECK-MSABI: load i32
149// CHECK-MSABI: icmp eq i32 {{.*}}, 0
150// CHECK-MSABI: br i1
151//
152// CHECK-MSABI-NOT: call{{ }}
153// CHECK-MSABI: getelementptr {{.*}}, i64 24
154// CHECK-MSABI-NOT: call{{ }}
155// CHECK-MSABI: call void @"??3F@@SAXPEAU0@Udestroying_delete_t@std@@_KW4align_val_t@2@@Z"({{.*}}, i64 96, i64 32)
156// CHECK-MSABI: br label %[[RETURN:.*]]
157//
158// CHECK-MSABI: call void @"??1I@@UEAA@XZ"(
159// CHECK-MSABI: br label %[[RETURN]]
160//
161// CHECK-MSABI: }
162