150
|
1 // RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s --implicit-check-not='call{{.*}}dtor'
|
|
2
|
|
3 namespace std {
|
|
4 typedef decltype(sizeof(int)) size_t;
|
|
5
|
|
6 template <class E>
|
|
7 struct initializer_list {
|
|
8 const E *begin;
|
|
9 size_t size;
|
|
10 initializer_list() : begin(nullptr), size(0) {}
|
|
11 };
|
|
12 }
|
|
13
|
|
14 void then();
|
|
15
|
|
16 struct dtor {
|
|
17 ~dtor();
|
|
18 };
|
|
19
|
|
20 dtor ctor();
|
|
21
|
|
22 auto &&lambda = [a = {ctor()}] {};
|
|
23 // CHECK-LABEL: define
|
|
24 // CHECK: call {{.*}}ctor
|
|
25 // CHECK: call {{.*}}atexit{{.*}}global_array_dtor
|
|
26
|
|
27 // CHECK-LABEL: define{{.*}}global_array_dtor
|
|
28 // CHECK: call {{.*}}dtor
|
|
29
|
|
30 // [lifetime extension occurs if the object was obtained by]
|
|
31 // -- a temporary materialization conversion
|
|
32 // CHECK-LABEL: ref_binding
|
|
33 void ref_binding() {
|
|
34 // CHECK: call {{.*}}ctor
|
|
35 auto &&x = ctor();
|
|
36 // CHECK: call {{.*}}then
|
|
37 then();
|
|
38 // CHECK: call {{.*}}dtor
|
|
39 // CHECK: }
|
|
40 }
|
|
41
|
|
42 // -- ( expression )
|
|
43 // CHECK-LABEL: parens
|
|
44 void parens() {
|
|
45 // CHECK: call {{.*}}ctor
|
|
46 auto &&x = ctor();
|
|
47 // CHECK: call {{.*}}then
|
|
48 then();
|
|
49 // CHECK: call {{.*}}dtor
|
|
50 // CHECK: }
|
|
51 }
|
|
52
|
|
53 // -- subscripting of an array
|
|
54 // CHECK-LABEL: array_subscript_1
|
|
55 void array_subscript_1() {
|
|
56 using T = dtor[1];
|
|
57 // CHECK: call {{.*}}ctor
|
|
58 auto &&x = T{ctor()}[0];
|
|
59 // CHECK: call {{.*}}then
|
|
60 then();
|
|
61 // CHECK: call {{.*}}dtor
|
|
62 // CHECK: }
|
|
63 }
|
|
64 // CHECK-LABEL: array_subscript_2
|
|
65 void array_subscript_2() {
|
|
66 using T = dtor[1];
|
|
67 // CHECK: call {{.*}}ctor
|
|
68 auto &&x = ((dtor*)T{ctor()})[0];
|
|
69 // CHECK: call {{.*}}dtor
|
|
70 // CHECK: call {{.*}}then
|
|
71 then();
|
|
72 // CHECK: }
|
|
73 }
|
|
74
|
|
75 struct with_member { dtor d; ~with_member(); };
|
|
76 struct with_ref_member { dtor &&d; ~with_ref_member(); };
|
|
77
|
|
78 // -- a class member access using the . operator [...]
|
|
79 // CHECK-LABEL: member_access_1
|
|
80 void member_access_1() {
|
|
81 // CHECK: call {{.*}}ctor
|
|
82 auto &&x = with_member{ctor()}.d;
|
|
83 // CHECK: call {{.*}}then
|
|
84 then();
|
|
85 // CHECK: call {{.*}}with_member
|
|
86 // CHECK: }
|
|
87 }
|
|
88 // CHECK-LABEL: member_access_2
|
|
89 void member_access_2() {
|
|
90 // CHECK: call {{.*}}ctor
|
|
91 auto &&x = with_ref_member{ctor()}.d;
|
|
92 // CHECK: call {{.*}}with_ref_member
|
|
93 // CHECK: call {{.*}}dtor
|
|
94 // CHECK: call {{.*}}then
|
|
95 then();
|
|
96 // CHECK: }
|
|
97 }
|
|
98 // CHECK-LABEL: member_access_3
|
|
99 void member_access_3() {
|
|
100 // CHECK: call {{.*}}ctor
|
|
101 auto &&x = (&(const with_member&)with_member{ctor()})->d;
|
|
102 // CHECK: call {{.*}}with_member
|
|
103 // CHECK: call {{.*}}then
|
|
104 then();
|
|
105 // CHECK: }
|
|
106 }
|
|
107
|
|
108 // -- a pointer-to-member operation using the .* operator [...]
|
|
109 // CHECK-LABEL: member_ptr_access_1
|
|
110 void member_ptr_access_1() {
|
|
111 // CHECK: call {{.*}}ctor
|
|
112 auto &&x = with_member{ctor()}.*&with_member::d;
|
|
113 // CHECK: call {{.*}}then
|
|
114 then();
|
|
115 // CHECK: call {{.*}}with_member
|
|
116 // CHECK: }
|
|
117 }
|
|
118 // CHECK-LABEL: member_ptr_access_2
|
|
119 void member_ptr_access_2() {
|
|
120 // CHECK: call {{.*}}ctor
|
|
121 auto &&x = (&(const with_member&)with_member{ctor()})->*&with_member::d;
|
|
122 // CHECK: call {{.*}}with_member
|
|
123 // CHECK: call {{.*}}then
|
|
124 then();
|
|
125 // CHECK: }
|
|
126 }
|
|
127
|
|
128 // -- a [named] cast [...]
|
|
129 // CHECK-LABEL: static_cast
|
|
130 void test_static_cast() {
|
|
131 // CHECK: call {{.*}}ctor
|
|
132 auto &&x = static_cast<dtor&&>(ctor());
|
|
133 // CHECK: call {{.*}}then
|
|
134 then();
|
|
135 // CHECK: call {{.*}}dtor
|
|
136 // CHECK: }
|
|
137 }
|
|
138 // CHECK-LABEL: const_cast
|
|
139 void test_const_cast() {
|
|
140 // CHECK: call {{.*}}ctor
|
|
141 auto &&x = const_cast<dtor&&>(ctor());
|
|
142 // CHECK: call {{.*}}then
|
|
143 then();
|
|
144 // CHECK: call {{.*}}dtor
|
|
145 // CHECK: }
|
|
146 }
|
|
147 // CHECK-LABEL: reinterpret_cast
|
|
148 void test_reinterpret_cast() {
|
|
149 // CHECK: call {{.*}}ctor
|
|
150 auto &&x = reinterpret_cast<dtor&&>(static_cast<dtor&&>(ctor()));
|
|
151 // CHECK: call {{.*}}then
|
|
152 then();
|
|
153 // CHECK: call {{.*}}dtor
|
|
154 // CHECK: }
|
|
155 }
|
|
156 // CHECK-LABEL: dynamic_cast
|
|
157 void test_dynamic_cast() {
|
|
158 // CHECK: call {{.*}}ctor
|
|
159 auto &&x = dynamic_cast<dtor&&>(ctor());
|
|
160 // CHECK: call {{.*}}then
|
|
161 then();
|
|
162 // CHECK: call {{.*}}dtor
|
|
163 // CHECK: }
|
|
164 }
|
|
165
|
|
166 // -- [explicit cast notation is defined in terms of the above]
|
|
167 // CHECK-LABEL: c_style_cast
|
|
168 void c_style_cast() {
|
|
169 // CHECK: call {{.*}}ctor
|
|
170 auto &&x = (dtor&&)ctor();
|
|
171 // CHECK: call {{.*}}then
|
|
172 then();
|
|
173 // CHECK: call {{.*}}dtor
|
|
174 // CHECK: }
|
|
175 }
|
|
176 // CHECK-LABEL: function_style_cast
|
|
177 void function_style_cast() {
|
|
178 // CHECK: call {{.*}}ctor
|
|
179 using R = dtor&&;
|
|
180 auto &&x = R(ctor());
|
|
181 // CHECK: call {{.*}}then
|
|
182 then();
|
|
183 // CHECK: call {{.*}}dtor
|
|
184 // CHECK: }
|
|
185 }
|
|
186
|
|
187 // -- a conditional operator
|
|
188 // CHECK-LABEL: conditional
|
|
189 void conditional(bool b) {
|
|
190 // CHECK: call {{.*}}ctor
|
|
191 // CHECK: call {{.*}}ctor
|
|
192 auto &&x = b ? (dtor&&)ctor() : (dtor&&)ctor();
|
|
193 // CHECK: call {{.*}}then
|
|
194 then();
|
|
195 // CHECK: call {{.*}}dtor
|
|
196 // CHECK: call {{.*}}dtor
|
|
197 // CHECK: }
|
|
198 }
|
|
199
|
|
200 // -- a comma expression
|
|
201 // CHECK-LABEL: comma
|
|
202 void comma() {
|
|
203 // CHECK: call {{.*}}ctor
|
|
204 auto &&x = (true, (dtor&&)ctor());
|
|
205 // CHECK: call {{.*}}then
|
|
206 then();
|
|
207 // CHECK: call {{.*}}dtor
|
|
208 // CHECK: }
|
|
209 }
|
|
210
|
|
211
|
|
212 // This applies recursively: if an object is lifetime-extended and contains a
|
|
213 // reference, the referent is also extended.
|
|
214 // CHECK-LABEL: init_capture_ref
|
|
215 void init_capture_ref() {
|
|
216 // CHECK: call {{.*}}ctor
|
|
217 auto x = [&a = (const dtor&)ctor()] {};
|
|
218 // CHECK: call {{.*}}then
|
|
219 then();
|
|
220 // CHECK: call {{.*}}dtor
|
|
221 // CHECK: }
|
|
222 }
|
|
223 // CHECK-LABEL: init_capture_ref_indirect
|
|
224 void init_capture_ref_indirect() {
|
|
225 // CHECK: call {{.*}}ctor
|
|
226 auto x = [&a = (const dtor&)ctor()] {};
|
|
227 // CHECK: call {{.*}}then
|
|
228 then();
|
|
229 // CHECK: call {{.*}}dtor
|
|
230 // CHECK: }
|
|
231 }
|
|
232 // CHECK-LABEL: init_capture_init_list
|
|
233 void init_capture_init_list() {
|
|
234 // CHECK: call {{.*}}ctor
|
|
235 auto x = [a = {ctor()}] {};
|
|
236 // CHECK: call {{.*}}then
|
|
237 then();
|
|
238 // CHECK: call {{.*}}dtor
|
|
239 // CHECK: }
|
|
240 }
|