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;
initializer_liststd::initializer_list10     initializer_list() : begin(nullptr), size(0) {}
11   };
12 }
13 
14 void then();
15 
16 struct dtor {
17   ~dtor();
18 };
19 
20 dtor ctor();
21 
__anonbb00a32c0102null22 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
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
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
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
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
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
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
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
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
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
test_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
test_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
test_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
test_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
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
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
conditional(bool b)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
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
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
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
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