xref: /llvm-project/clang/test/CXX/special/class.temporary/p6.cpp (revision 25d9688c43d37c0c918e9b8ab2f67be35b0fb75f)
1 // RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s --implicit-check-not='call{{.*}}dtor'
2 // RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK-CXX23,CHECK-CXX23-NEXT,CHECK-CXX23-LABEL
3 
4 namespace std {
5   typedef decltype(sizeof(int)) size_t;
6 
7   template <class E>
8   struct initializer_list {
9     const E *begin;
10     size_t   size;
11     initializer_list() : begin(nullptr), size(0) {}
12   };
13 
14   template <typename E>
15   struct list {
16     list() {}
17     ~list() {}
18     E *begin();
19     E *end();
20     const E *begin() const;
21     const E *end() const;
22   };
23 
24   template <typename E>
25   struct vector {
26     vector() {}
27     vector(std::initializer_list<E>) {}
28     ~vector() {}
29     E *begin();
30     E *end();
31     const E *begin() const;
32     const E *end() const;
33   };
34 
35   template <typename T>
36   struct lock_guard {
37     lock_guard(T) {}
38     ~lock_guard() {}
39   };
40 
41   struct mutex {};
42 } // namespace std
43 
44 void then();
45 
46 struct dtor {
47   ~dtor();
48 };
49 
50 dtor ctor();
51 
52 auto &&lambda = [a = {ctor()}] {};
53 // CHECK-LABEL: define
54 // CHECK: call {{.*}}ctor
55 // CHECK: call {{.*}}atexit{{.*}}global_array_dtor
56 
57 // CHECK-LABEL: define{{.*}}global_array_dtor
58 // CHECK: call {{.*}}dtor
59 
60 // [lifetime extension occurs if the object was obtained by]
61 //  -- a temporary materialization conversion
62 // CHECK-LABEL: ref_binding
63 void ref_binding() {
64   // CHECK: call {{.*}}ctor
65   auto &&x = ctor();
66   // CHECK: call {{.*}}then
67   then();
68   // CHECK: call {{.*}}dtor
69   // CHECK: }
70 }
71 
72 //  -- ( expression )
73 // CHECK-LABEL: parens
74 void parens() {
75   // CHECK: call {{.*}}ctor
76   auto &&x = ctor();
77   // CHECK: call {{.*}}then
78   then();
79   // CHECK: call {{.*}}dtor
80   // CHECK: }
81 }
82 
83 //  -- subscripting of an array
84 // CHECK-LABEL: array_subscript_1
85 void array_subscript_1() {
86   using T = dtor[1];
87   // CHECK: call {{.*}}ctor
88   auto &&x = T{ctor()}[0];
89   // CHECK: call {{.*}}then
90   then();
91   // CHECK: call {{.*}}dtor
92   // CHECK: }
93 }
94 // CHECK-LABEL: array_subscript_2
95 void array_subscript_2() {
96   using T = dtor[1];
97   // CHECK: call {{.*}}ctor
98   auto &&x = ((dtor*)T{ctor()})[0];
99   // CHECK: call {{.*}}dtor
100   // CHECK: call {{.*}}then
101   then();
102   // CHECK: }
103 }
104 
105 struct with_member { dtor d; ~with_member(); };
106 struct with_ref_member { dtor &&d; ~with_ref_member(); };
107 
108 //  -- a class member access using the . operator [...]
109 // CHECK-LABEL: member_access_1
110 void member_access_1() {
111   // CHECK: call {{.*}}ctor
112   auto &&x = with_member{ctor()}.d;
113   // CHECK: call {{.*}}then
114   then();
115   // CHECK: call {{.*}}with_member
116   // CHECK: }
117 }
118 // CHECK-LABEL: member_access_2
119 void member_access_2() {
120   // CHECK: call {{.*}}ctor
121   auto &&x = with_ref_member{ctor()}.d;
122   // CHECK: call {{.*}}with_ref_member
123   // CHECK: call {{.*}}dtor
124   // CHECK: call {{.*}}then
125   then();
126   // CHECK: }
127 }
128 // CHECK-LABEL: member_access_3
129 void member_access_3() {
130   // CHECK: call {{.*}}ctor
131   auto &&x = (&(const with_member&)with_member{ctor()})->d;
132   // CHECK: call {{.*}}with_member
133   // CHECK: call {{.*}}then
134   then();
135   // CHECK: }
136 }
137 
138 //  -- a pointer-to-member operation using the .* operator [...]
139 // CHECK-LABEL: member_ptr_access_1
140 void member_ptr_access_1() {
141   // CHECK: call {{.*}}ctor
142   auto &&x = with_member{ctor()}.*&with_member::d;
143   // CHECK: call {{.*}}then
144   then();
145   // CHECK: call {{.*}}with_member
146   // CHECK: }
147 }
148 // CHECK-LABEL: member_ptr_access_2
149 void member_ptr_access_2() {
150   // CHECK: call {{.*}}ctor
151   auto &&x = (&(const with_member&)with_member{ctor()})->*&with_member::d;
152   // CHECK: call {{.*}}with_member
153   // CHECK: call {{.*}}then
154   then();
155   // CHECK: }
156 }
157 
158 //  -- a [named] cast [...]
159 // CHECK-LABEL: static_cast
160 void test_static_cast() {
161   // CHECK: call {{.*}}ctor
162   auto &&x = static_cast<dtor&&>(ctor());
163   // CHECK: call {{.*}}then
164   then();
165   // CHECK: call {{.*}}dtor
166   // CHECK: }
167 }
168 // CHECK-LABEL: const_cast
169 void test_const_cast() {
170   // CHECK: call {{.*}}ctor
171   auto &&x = const_cast<dtor&&>(ctor());
172   // CHECK: call {{.*}}then
173   then();
174   // CHECK: call {{.*}}dtor
175   // CHECK: }
176 }
177 // CHECK-LABEL: reinterpret_cast
178 void test_reinterpret_cast() {
179   // CHECK: call {{.*}}ctor
180   auto &&x = reinterpret_cast<dtor&&>(static_cast<dtor&&>(ctor()));
181   // CHECK: call {{.*}}then
182   then();
183   // CHECK: call {{.*}}dtor
184   // CHECK: }
185 }
186 // CHECK-LABEL: dynamic_cast
187 void test_dynamic_cast() {
188   // CHECK: call {{.*}}ctor
189   auto &&x = dynamic_cast<dtor&&>(ctor());
190   // CHECK: call {{.*}}then
191   then();
192   // CHECK: call {{.*}}dtor
193   // CHECK: }
194 }
195 
196 //  -- [explicit cast notation is defined in terms of the above]
197 // CHECK-LABEL: c_style_cast
198 void c_style_cast() {
199   // CHECK: call {{.*}}ctor
200   auto &&x = (dtor&&)ctor();
201   // CHECK: call {{.*}}then
202   then();
203   // CHECK: call {{.*}}dtor
204   // CHECK: }
205 }
206 // CHECK-LABEL: function_style_cast
207 void function_style_cast() {
208   // CHECK: call {{.*}}ctor
209   using R = dtor&&;
210   auto &&x = R(ctor());
211   // CHECK: call {{.*}}then
212   then();
213   // CHECK: call {{.*}}dtor
214   // CHECK: }
215 }
216 
217 //  -- a conditional operator
218 // CHECK-LABEL: conditional
219 void conditional(bool b) {
220   // CHECK: call {{.*}}ctor
221   // CHECK: call {{.*}}ctor
222   auto &&x = b ? (dtor&&)ctor() : (dtor&&)ctor();
223   // CHECK: call {{.*}}then
224   then();
225   // CHECK: call {{.*}}dtor
226   // CHECK: call {{.*}}dtor
227   // CHECK: }
228 }
229 
230 //  -- a comma expression
231 // CHECK-LABEL: comma
232 void comma() {
233   // CHECK: call {{.*}}ctor
234   auto &&x = (true, (dtor&&)ctor());
235   // CHECK: call {{.*}}then
236   then();
237   // CHECK: call {{.*}}dtor
238   // CHECK: }
239 }
240 
241 
242 // This applies recursively: if an object is lifetime-extended and contains a
243 // reference, the referent is also extended.
244 // CHECK-LABEL: init_capture_ref
245 void init_capture_ref() {
246   // CHECK: call {{.*}}ctor
247   auto x = [&a = (const dtor&)ctor()] {};
248   // CHECK: call {{.*}}then
249   then();
250   // CHECK: call {{.*}}dtor
251   // CHECK: }
252 }
253 // CHECK-LABEL: init_capture_ref_indirect
254 void init_capture_ref_indirect() {
255   // CHECK: call {{.*}}ctor
256   auto x = [&a = (const dtor&)ctor()] {};
257   // CHECK: call {{.*}}then
258   then();
259   // CHECK: call {{.*}}dtor
260   // CHECK: }
261 }
262 // CHECK-LABEL: init_capture_init_list
263 void init_capture_init_list() {
264   // CHECK: call {{.*}}ctor
265   auto x = [a = {ctor()}] {};
266   // CHECK: call {{.*}}then
267   then();
268   // CHECK: call {{.*}}dtor
269   // CHECK: }
270 }
271 
272 void check_dr1815() { // dr1815: yes
273 #if __cplusplus >= 201402L
274 
275   struct A {
276     int &&r = 0;
277     ~A() {}
278   };
279 
280   struct B {
281     A &&a = A{};
282     ~B() {}
283   };
284   B a = {};
285 
286   // CHECK: call {{.*}}block_scope_begin_function
287   extern void block_scope_begin_function();
288   extern void block_scope_end_function();
289   block_scope_begin_function();
290   {
291     // CHECK: call void @_ZZ12check_dr1815vEN1BD1Ev
292     // CHECK: call void @_ZZ12check_dr1815vEN1AD1Ev
293     B b = {};
294   }
295   // CHECK: call {{.*}}block_scope_end_function
296   block_scope_end_function();
297 
298   // CHECK: call {{.*}}some_other_function
299   extern void some_other_function();
300   some_other_function();
301   // CHECK: call void @_ZZ12check_dr1815vEN1BD1Ev
302   // CHECK: call void @_ZZ12check_dr1815vEN1AD1Ev
303 #endif
304 }
305 
306 namespace P2718R0 {
307 namespace basic {
308 template <typename E> using T2 = std::list<E>;
309 template <typename E> const T2<E> &f1_temp(const T2<E> &t)  { return t; }
310 template <typename E> const T2<E> &f2_temp(T2<E> t)         { return t; }
311 template <typename E> T2<E> g_temp()                        { return T2<E>{}; }
312 
313 template <typename E>
314 void foo_dependent_context1() {
315   // CHECK-CXX23: void @_ZN7P2718R05basic22foo_dependent_context1IiEEvv()
316   // CHECK-CXX23: for.cond.cleanup:
317   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
318   for (auto e : f1_temp(g_temp<E>())) {}  // OK, lifetime of return value of g() extended
319 }
320 
321 template <typename E>
322 void foo_dependent_context2() {
323   // CHECK-CXX23: void @_ZN7P2718R05basic22foo_dependent_context2IiEEvv()
324   // CHECK-CXX23-NEXT: entry:
325   // CHECK-CXX23-NEXT: call void @_ZN7P2718R05basic6g_tempIiEESt4listIT_Ev(
326   // CHECK-CXX23-NEXT: call {{.*}} @_ZN7P2718R05basic7f2_tempIiEERKSt4listIT_ES4_(
327   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
328   // CHECK-CXX23: call {{.*}} @_ZNKSt4listIiE5beginEv(
329   // CHECK-CXX23: call {{.*}} @_ZNKSt4listIiE3endEv(
330   for (auto e : f2_temp(g_temp<E>())) {}  // undefined behavior
331 }
332 
333 template void foo_dependent_context1<int>();
334 template void foo_dependent_context2<int>();
335 } // namespace basic
336 
337 namespace discard_value_expression {
338 template <typename T>
339 void f_dependent_context1() {
340   std::vector<T> v = { 42, 17, 13 };
341   std::mutex m;
342   // CHECK-CXX23: void @_ZN7P2718R024discard_value_expression20f_dependent_context1IiEEvv()
343   // CHECK-CXX23-LABEL: for.cond.cleanup:
344   // CHECK-CXX23-NEXT: call void @_ZNSt10lock_guardISt5mutexED1Ev(
345   for (T x : std::lock_guard<std::mutex>(m), v)  // lock released in C++ 2023
346     std::lock_guard<std::mutex> guard(m);  // OK in C++ 2023, now deadlocks
347 }
348 
349 template <typename T>
350 void f_dependent_context2() {
351   std::vector<T> v = { 42, 17, 13 };
352   std::mutex m;
353   // CHECK-CXX23: void @_ZN7P2718R024discard_value_expression20f_dependent_context2IiEEvv()
354   // CHECK-CXX23-LABEL: for.cond.cleanup:
355   // CHECK-CXX23-NEXT: call void @_ZNSt10lock_guardISt5mutexED1Ev(
356   for (T x : (void)std::lock_guard<std::mutex>(m), v)  // lock released in C++ 2023
357     std::lock_guard<std::mutex> guard(m);  // OK in C++ 2023, now deadlocks
358 }
359 
360 template <typename T>
361 void f_dependent_context3() {
362   std::vector<T> v = { 42, 17, 13 };
363   std::mutex m;
364   // CHECK-CXX23: void @_ZN7P2718R024discard_value_expression20f_dependent_context3IiEEvv()
365   // CHECK-CXX23-LABEL: for.cond.cleanup:
366   // CHECK-CXX23-NEXT: call void @_ZNSt10lock_guardISt5mutexED1Ev(
367   for (T x : static_cast<void>(std::lock_guard<std::mutex>(m)), v)  // lock released in C++ 2023
368     std::lock_guard<std::mutex> guard(m);  // OK in C++ 2023, now deadlocks
369 }
370 
371 template void f_dependent_context1<int>();
372 template void f_dependent_context2<int>();
373 template void f_dependent_context3<int>();
374 } // namespace discard_value_expression
375 
376 namespace member_call {
377 template <typename T>
378 struct ListWrapper {
379   std::list<T> list;
380   ListWrapper() {}
381   ~ListWrapper() {}
382   const T *begin() const { return list.begin(); }
383   const T *end() const { return list.end(); }
384   ListWrapper& r() { return *this; }
385   ListWrapper g() { return ListWrapper(); }
386 };
387 
388 template <typename E>
389 ListWrapper<E> g_temp() { return ListWrapper<E>{}; }
390 
391 template <typename T>
392 void member_call_dependent_context() {
393   // CHECK-CXX23: void @_ZN7P2718R011member_call29member_call_dependent_contextIiEEvv()
394   // CHECK-CXX23-LABEL: for.cond.cleanup:
395   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011member_call11ListWrapperIiED1Ev(
396   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011member_call11ListWrapperIiED1Ev(
397   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011member_call11ListWrapperIiED1Ev(
398   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011member_call11ListWrapperIiED1Ev(
399   for (auto e : g_temp<T>().r().g().r().g().r().g()) {}
400 }
401 
402 template void member_call_dependent_context<int>();
403 } // namespace member_call
404 
405 namespace default_arg {
406 template <typename T>
407 struct DefaultArg {
408   DefaultArg() {}
409   DefaultArg(int) {}
410   ~DefaultArg() {}
411 };
412 
413 template <typename T>
414 struct C2 : public std::list<T> {
415   C2() {}
416   C2(int, const C2 &, const DefaultArg<T> &Default = DefaultArg<T>{}) {}
417 };
418 
419 template <typename T>
420 std::list<T> temp_foo(const std::list<T>&, const DefaultArg<T> &Default = DefaultArg<T>{}) {
421   return std::list<T>{};
422 }
423 
424 template <typename T>
425 void default_arg_dependent_context1() {
426   // CHECK-CXX23: void @_ZN7P2718R011default_arg30default_arg_dependent_context1IiEEvv()
427   // CHECK-CXX23-LABEL: for.cond.cleanup:
428   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
429   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
430   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
431   for (auto e : temp_foo(std::list<T>{})) {}
432 }
433 
434 template <typename T>
435 void default_arg_dependent_context2() {
436   // CHECK-CXX23: void @_ZN7P2718R011default_arg30default_arg_dependent_context2IiEEvv()
437   // CHECK-CXX23-LABEL: for.cond.cleanup:
438   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
439   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
440   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
441   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
442   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
443   for (auto e : temp_foo(temp_foo(std::list<T>{}))) {}
444 }
445 
446 template <typename T>
447 void default_arg_dependent_context3() {
448   // CHECK-CXX23: void @_ZN7P2718R011default_arg30default_arg_dependent_context3IiEEvv()
449   // CHECK-CXX23-LABEL: for.cond.cleanup:
450   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg2C2IiED1Ev(
451   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
452   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg2C2IiED1Ev(
453   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
454   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg2C2IiED1Ev(
455   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
456   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg2C2IiED1Ev(
457 
458   for (auto e : C2<T>(0, C2<T>(0, C2<T>(0, C2<T>())))) {}
459 }
460 
461 template void default_arg_dependent_context1<int>();
462 template void default_arg_dependent_context2<int>();
463 template void default_arg_dependent_context3<int>();
464 } // namespace default_arg
465 
466 namespace default_init {
467 template <class T>
468 struct DepA {
469   T arr[1];
470   ~DepA() {}
471 };
472 
473 template <class T>
474 struct DepB {
475   int x;
476   const DepA<T> &a = DepA<T>{{0}};
477   ~DepB() {}
478   const int *begin() { return a.arr; }
479   const int *end() { return &a.arr[1]; }
480 };
481 
482 template <typename T>
483 void default_init1_dependent() {
484   // CHECK-CXX23: void @_ZN7P2718R012default_init23default_init1_dependentINS0_4DepBIiEEEEvv()
485   // CHECK-CXX23-LABEL: for.cond.cleanup:
486   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init4DepBIiED1Ev(
487   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init4DepAIiED1Ev(
488   for (auto &&x : T{0}) {}
489 }
490 
491 template <typename T>
492 void default_init2_dependent() {
493   // CHECK-CXX23: void @_ZN7P2718R012default_init23default_init2_dependentINS0_4DepBIiEEEEvv()
494   // CHECK-CXX23-LABEL: for.cond.cleanup:
495   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init4DepBIiED1Ev(
496   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init4DepAIiED1Ev(
497   for (auto &&x : T{0}.a.arr) {}
498 }
499 
500 template void default_init1_dependent<DepB<int>>();
501 template void default_init2_dependent<DepB<int>>();
502 } // namespace default_init
503 
504 // -- Examples from https://wg21.link/p2718r0
505 extern void block_scope_begin_function();
506 extern void block_scope_end_function();
507 namespace std_examples {
508 using T = std::list<int>;
509 const T& f1(const T& t) { return t; }
510 const T& f2(T t)        { return t; }
511 T g();
512 void foo() {
513   // CHECK-CXX23: define {{.*}} void @_ZN7P2718R012std_examples3fooEv()
514   // CHECK-CXX23: call void @_ZN7P2718R026block_scope_begin_functionEv
515   block_scope_begin_function();
516   {
517     // CHECK-CXX23-NEXT: call void @_ZN7P2718R012std_examples1gEv
518     // CHECK-CXX23-NEXT: call {{.*}} @_ZN7P2718R012std_examples2f1ERKSt4listIiE
519     // CHECK-CXX23: for.cond.cleanup:
520     // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev
521     for (auto e : f1(g())) {}  // OK, lifetime of return value of g() extended
522   }
523   // CHECK-CXX23: call void @_ZN7P2718R024block_scope_end_functionEv
524   block_scope_end_function();
525 
526   // The lifetime of temporary returned by g() in this case will not be extended.
527   // CHECK-CXX23: call void @_ZN7P2718R026block_scope_begin_functionEv
528   block_scope_begin_function();
529   {
530     // CHECK-CXX23-NEXT: call void @_ZN7P2718R012std_examples1gEv
531     // CHECK-CXX23-NEXT: call {{.*}} @_ZN7P2718R012std_examples2f2ESt4listIiE
532     // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev
533     for (auto e : f2(g())) {}  // undefined behavior
534   }
535   // CHECK-CXX23: call void @_ZN7P2718R024block_scope_end_functionEv
536   block_scope_end_function();
537 }
538 } // namespace std_examples
539 
540 namespace basic {
541 using T = std::list<int>;
542 const T& f1(const T& t) { return t; }
543 const T& f2(T t)        { return t; }
544 T g()                   { return T{}; }
545 
546 void foo1() {
547   // CHECK-CXX23: void @_ZN7P2718R05basic4foo1Ev()
548   // CHECK-CXX23: for.cond.cleanup:
549   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
550   for (auto e : f1(g())) {}  // OK, lifetime of return value of g() extended
551 }
552 
553 void foo2() {
554   // CHECK-CXX23: void @_ZN7P2718R05basic4foo2Ev()
555   // CHECK-CXX23-NEXT: call void @_ZN7P2718R05basic1gEv(
556   // CHECK-CXX23-NEXT: call {{.*}} @_ZN7P2718R05basic2f2ESt4listIiE(
557   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
558   for (auto e : f2(g())) {}  // undefined behavior
559 }
560 } // namespace basic
561 
562 namespace discard_value_expression {
563 void f1() {
564   std::vector<int> v = { 42, 17, 13 };
565   std::mutex m;
566   // CHECK-CXX23: void @_ZN7P2718R024discard_value_expression2f1Ev()
567   // CHECK-CXX23-LABEL: for.cond.cleanup:
568   // CHECK-CXX23-NEXT: call void @_ZNSt10lock_guardISt5mutexED1Ev(
569   for (int x : std::lock_guard<std::mutex>(m), v)  // lock released in C++ 2023
570     std::lock_guard<std::mutex> guard(m);  // OK in C++ 2023, now deadlocks
571 }
572 
573 void f2() {
574   std::vector<int> v = { 42, 17, 13 };
575   std::mutex m;
576   // CHECK-CXX23: void @_ZN7P2718R024discard_value_expression2f2Ev()
577   // CHECK-CXX23-LABEL: for.cond.cleanup:
578   // CHECK-CXX23-NEXT: call void @_ZNSt10lock_guardISt5mutexED1Ev(
579   for (int x : (void)std::lock_guard<std::mutex>(m), v)  // lock released in C++ 2023
580     std::lock_guard<std::mutex> guard(m);  // OK in C++ 2023, now deadlocks
581 }
582 
583 void f3() {
584   std::vector<int> v = { 42, 17, 13 };
585   std::mutex m;
586   // CHECK-CXX23: void @_ZN7P2718R024discard_value_expression2f3Ev()
587   // CHECK-CXX23-LABEL: for.cond.cleanup:
588   // CHECK-CXX23-NEXT: call void @_ZNSt10lock_guardISt5mutexED1Ev(
589   for (int x : static_cast<void>(std::lock_guard<std::mutex>(m)), v)  // lock released in C++ 2023
590     std::lock_guard<std::mutex> guard(m);  // OK in C++ 2023, now deadlocks
591 }
592 } // namespace discard_value_expression
593 
594 namespace member_call {
595 using A = ListWrapper<int>;
596 
597 A g() { return A(); }
598 const A &f1(const A &t) { return t; }
599 
600 void member_call() {
601   // CHECK-CXX23: void @_ZN7P2718R011member_call11member_callEv()
602   // CHECK-CXX23-LABEL: for.cond.cleanup:
603   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011member_call11ListWrapperIiED1Ev(
604   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011member_call11ListWrapperIiED1Ev(
605   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011member_call11ListWrapperIiED1Ev(
606   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011member_call11ListWrapperIiED1Ev(
607   for (auto e : g().r().g().r().g().r().g()) {}
608 }
609 } // namespace member_call
610 
611 namespace default_arg {
612 using A = std::list<int>;
613 using DefaultA = DefaultArg<int>;
614 struct C : public A {
615   C() {}
616   C(int, const C &, const DefaultA & = DefaultA()) {}
617 };
618 
619 A foo(const A&, const DefaultA &Default = DefaultA()) {
620   return A();
621 }
622 
623 int (&some_func(const A & = A{}))[3];
624 
625 void default_arg1() {
626   // CHECK-CXX23: void @_ZN7P2718R011default_arg12default_arg1Ev()
627   // CHECK-CXX23-LABEL: for.cond.cleanup:
628   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
629   for (auto e : some_func()) {}
630 }
631 
632 void default_arg2() {
633   // CHECK-CXX23: void @_ZN7P2718R011default_arg12default_arg2Ev()
634   // CHECK-CXX23-LABEL: for.cond.cleanup:
635   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
636   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
637   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
638   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
639   // CHECK-CXX23-NEXT: call void @_ZNSt4listIiED1Ev(
640   for (auto e : some_func(foo(foo(A())))) {}
641 }
642 
643 void default_arg3() {
644   // CHECK-CXX23: void @_ZN7P2718R011default_arg12default_arg3Ev()
645   // CHECK-CXX23-LABEL: for.cond.cleanup:
646   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg1CD1Ev(
647   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
648   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg1CD1Ev(
649   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
650   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg1CD1Ev(
651   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg10DefaultArgIiED1Ev(
652   // CHECK-CXX23-NEXT: call void @_ZN7P2718R011default_arg1CD1Ev(
653   for (auto e : C(0, C(0, C(0, C())))) {}
654 }
655 } // namespace default_arg
656 
657 namespace default_init {
658 struct X {
659   int x;
660   ~X() {}
661 };
662 
663 struct Y {
664   int y;
665   const X &x = X{1};
666   ~Y() {}
667 };
668 
669 struct A {
670   int arr[1];
671   const Y &y = Y{1};
672   ~A() {}
673 };
674 
675 struct B {
676   int x;
677   const A &a = A{{0}};
678   ~B() {}
679   const int *begin() { return a.arr; }
680   const int *end() { return &a.arr[1]; }
681 };
682 
683 void default_init1() {
684   // CHECK-CXX23: void @_ZN7P2718R012default_init13default_init1Ev()
685   // CHECK-CXX23-LABEL: for.cond.cleanup:
686   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1BD1Ev(
687   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1AD1Ev(
688   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1YD1Ev(
689   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1XD1Ev(
690   for (auto &&x : B{0}) {}
691 }
692 
693 void default_init2() {
694   // CHECK-CXX23: void @_ZN7P2718R012default_init13default_init2Ev()
695   // CHECK-CXX23-LABEL: for.cond.cleanup:
696   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1BD1Ev(
697   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1AD1Ev(
698   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1YD1Ev(
699   // CHECK-CXX23-NEXT: call void @_ZN7P2718R012default_init1XD1Ev(
700   for (auto &&x : B{0}.a.arr) {}
701 }
702 } // namespace default_init
703 } // namespace P2718R0
704