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