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 | } |
241 | |