1 // RUN: %check_clang_tidy -std=c++11,c++14 %s bugprone-exception-escape %t -- \ 2 // RUN: -config="{CheckOptions: { \ 3 // RUN: bugprone-exception-escape.IgnoredExceptions: 'ignored1,ignored2', \ 4 // RUN: bugprone-exception-escape.FunctionsThatShouldNotThrow: 'enabled1,enabled2,enabled3' \ 5 // RUN: }}" \ 6 // RUN: -- -fexceptions 7 // FIXME: Fix the checker to work in C++17 or later mode. 8 9 struct throwing_destructor { 10 ~throwing_destructor() { 11 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function '~throwing_destructor' which should not throw exceptions 12 throw 1; 13 } 14 }; 15 16 struct throwing_move_constructor { 17 throwing_move_constructor(throwing_move_constructor&&) { 18 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'throwing_move_constructor' which should not throw exceptions 19 throw 1; 20 } 21 }; 22 23 struct throwing_move_assignment { 24 throwing_move_assignment& operator=(throwing_move_assignment&&) { 25 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: an exception may be thrown in function 'operator=' which should not throw exceptions 26 throw 1; 27 } 28 }; 29 30 void throwing_noexcept() noexcept { 31 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions 32 throw 1; 33 } 34 35 void throw_and_catch() noexcept { 36 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch' which should not throw exceptions 37 try { 38 throw 1; 39 } catch(int &) { 40 } 41 } 42 43 void throw_and_catch_some(int n) noexcept { 44 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_some' which should not throw exceptions 45 try { 46 if (n) throw 1; 47 throw 1.1; 48 } catch(int &) { 49 } 50 } 51 52 void throw_and_catch_each(int n) noexcept { 53 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions 54 try { 55 if (n) throw 1; 56 throw 1.1; 57 } catch(int &) { 58 } catch(double &) { 59 } 60 } 61 62 void throw_and_catch_all(int n) noexcept { 63 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_all' which should not throw exceptions 64 try { 65 if (n) throw 1; 66 throw 1.1; 67 } catch(...) { 68 } 69 } 70 71 void throw_and_rethrow() noexcept { 72 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_rethrow' which should not throw exceptions 73 try { 74 throw 1; 75 } catch(int &) { 76 throw; 77 } 78 } 79 80 void throw_catch_throw() noexcept { 81 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions 82 try { 83 throw 1; 84 } catch(int &) { 85 throw 2; 86 } 87 } 88 89 void throw_catch_rethrow_the_rest(int n) noexcept { 90 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions 91 try { 92 if (n) throw 1; 93 throw 1.1; 94 } catch(int &) { 95 } catch(...) { 96 throw; 97 } 98 } 99 100 void throw_catch_pointer_c() noexcept { 101 try { 102 int a = 1; 103 throw &a; 104 } catch(const int *) {} 105 } 106 107 void throw_catch_pointer_v() noexcept { 108 try { 109 int a = 1; 110 throw &a; 111 } catch(volatile int *) {} 112 } 113 114 void throw_catch_pointer_cv() noexcept { 115 try { 116 int a = 1; 117 throw &a; 118 } catch(const volatile int *) {} 119 } 120 121 void throw_catch_multi_ptr_1() noexcept { 122 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_multi_ptr_1' which should not throw exceptions 123 try { 124 char **p = 0; 125 throw p; 126 } catch (const char **) { 127 } 128 } 129 130 void throw_catch_multi_ptr_2() noexcept { 131 try { 132 char **p = 0; 133 throw p; 134 } catch (const char *const *) { 135 } 136 } 137 138 void throw_catch_multi_ptr_3() noexcept { 139 try { 140 char **p = 0; 141 throw p; 142 } catch (volatile char *const *) { 143 } 144 } 145 146 void throw_catch_multi_ptr_4() noexcept { 147 try { 148 char **p = 0; 149 throw p; 150 } catch (volatile const char *const *) { 151 } 152 } 153 154 // FIXME: In this case 'a' is convertible to the handler and should be caught 155 // but in reality it's thrown. Note that clang doesn't report a warning for 156 // this either. 157 void throw_catch_multi_ptr_5() noexcept { 158 try { 159 double *a[2][3]; 160 throw a; 161 } catch (double *(*)[3]) { 162 } 163 } 164 165 166 void throw_c_catch_pointer() noexcept { 167 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_c_catch_pointer' which should not throw exceptions 168 try { 169 int a = 1; 170 const int *p = &a; 171 throw p; 172 } catch(int *) {} 173 } 174 175 void throw_c_catch_pointer_v() noexcept { 176 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_c_catch_pointer_v' which should not throw exceptions 177 try { 178 int a = 1; 179 const int *p = &a; 180 throw p; 181 } catch(volatile int *) {} 182 } 183 184 void throw_v_catch_pointer() noexcept { 185 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_v_catch_pointer' which should not throw exceptions 186 try { 187 int a = 1; 188 volatile int *p = &a; 189 throw p; 190 } catch(int *) {} 191 } 192 193 void throw_v_catch_pointer_c() noexcept { 194 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_v_catch_pointer_c' which should not throw exceptions 195 try { 196 int a = 1; 197 volatile int *p = &a; 198 throw p; 199 } catch(const int *) {} 200 } 201 202 void throw_cv_catch_pointer_c() noexcept { 203 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_cv_catch_pointer_c' which should not throw exceptions 204 try { 205 int a = 1; 206 const volatile int *p = &a; 207 throw p; 208 } catch(const int *) {} 209 } 210 211 void throw_cv_catch_pointer_v() noexcept { 212 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_cv_catch_pointer_v' which should not throw exceptions 213 try { 214 int a = 1; 215 const volatile int *p = &a; 216 throw p; 217 } catch(volatile int *) {} 218 } 219 220 class base {}; 221 class derived: public base {}; 222 223 void throw_derived_catch_base() noexcept { 224 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base' which should not throw exceptions 225 try { 226 throw derived(); 227 } catch(base &) { 228 } 229 } 230 231 void throw_derived_alias_catch_base() noexcept { 232 using alias = derived; 233 234 try { 235 throw alias(); 236 } catch(base &) { 237 } 238 } 239 240 void throw_derived_catch_base_alias() noexcept { 241 using alias = base; 242 243 try { 244 throw derived(); 245 } catch(alias &) { 246 } 247 } 248 249 void throw_derived_catch_base_ptr_c() noexcept { 250 try { 251 derived d; 252 throw &d; 253 } catch(const base *) { 254 } 255 } 256 257 void throw_derived_catch_base_ptr() noexcept { 258 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ptr' which should not throw exceptions 259 try { 260 derived d; 261 const derived *p = &d; 262 throw p; 263 } catch(base *) { 264 } 265 } 266 267 class A {}; 268 class B : A {}; 269 270 // The following alias hell is deliberately created for testing. 271 using aliasedA = A; 272 class C : protected aliasedA {}; 273 274 typedef aliasedA moreAliasedA; 275 class D : public moreAliasedA {}; 276 277 using moreMoreAliasedA = moreAliasedA; 278 using aliasedD = D; 279 class E : public moreMoreAliasedA, public aliasedD {}; 280 281 void throw_derived_catch_base_private() noexcept { 282 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private' which should not throw exceptions 283 try { 284 B b; 285 throw b; 286 } catch(A) { 287 } 288 } 289 290 void throw_derived_catch_base_private_ptr() noexcept { 291 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private_ptr' which should not throw exceptions 292 try { 293 B b; 294 throw &b; 295 } catch(A *) { 296 } 297 } 298 299 void throw_derived_catch_base_protected() noexcept { 300 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected' which should not throw exceptions 301 try { 302 C c; 303 throw c; 304 } catch(A) { 305 } 306 } 307 308 void throw_derived_catch_base_protected_ptr() noexcept { 309 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected_ptr' which should not throw exceptions 310 try { 311 C c; 312 throw &c; 313 } catch(A *) { 314 } 315 } 316 317 void throw_derived_catch_base_ambiguous() noexcept { 318 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous' which should not throw exceptions 319 try { 320 E e; 321 throw e; 322 } catch(A) { 323 } 324 } 325 326 void throw_derived_catch_base_ambiguous_ptr() noexcept { 327 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' which should not throw exceptions 328 try { 329 E e; 330 throw e; 331 } catch(A) { 332 } 333 } 334 335 void throw_alias_catch_original() noexcept { 336 using alias = int; 337 338 try { 339 alias a = 3; 340 throw a; 341 } catch (int) { 342 } 343 } 344 345 void throw_alias_catch_original_warn() noexcept { 346 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_alias_catch_original_warn' which should not throw exceptions 347 using alias = float; 348 349 try { 350 alias a = 3; 351 throw a; 352 } catch (int) { 353 } 354 } 355 356 void throw_original_catch_alias() noexcept { 357 using alias = char; 358 359 try { 360 char **p = 0; 361 throw p; 362 } catch (volatile const alias *const *) { 363 } 364 } 365 366 void throw_original_catch_alias_warn() noexcept { 367 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_warn' which should not throw exceptions 368 using alias = int; 369 370 try { 371 char **p = 0; 372 throw p; 373 } catch (volatile const alias *const *) { 374 } 375 } 376 377 void throw_original_catch_alias_2() noexcept { 378 using alias = const char *const; 379 380 try { 381 char **p = 0; 382 throw p; 383 } catch (volatile alias *) { 384 } 385 } 386 387 namespace a { 388 int foo() { return 0; }; 389 390 void throw_regular_catch_regular() noexcept { 391 try { 392 throw &foo; 393 } catch(int (*)()) { 394 } 395 } 396 } 397 398 namespace b { 399 inline int foo() { return 0; }; 400 401 void throw_inline_catch_regular() noexcept { 402 try { 403 throw &foo; 404 } catch(int (*)()) { 405 } 406 } 407 } 408 409 namespace c { 410 inline int foo() noexcept { return 0; }; 411 412 void throw_noexcept_catch_regular() noexcept { 413 try { 414 throw &foo; 415 } catch(int (*)()) { 416 } 417 } 418 } 419 420 struct baseMember { 421 int *iptr; 422 virtual void foo(){}; 423 }; 424 425 struct derivedMember : baseMember { 426 void foo() override {}; 427 }; 428 429 void throw_basefn_catch_derivedfn() noexcept { 430 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basefn_catch_derivedfn' which should not throw exceptions 431 try { 432 throw &baseMember::foo; 433 } catch(void(derivedMember::*)()) { 434 } 435 } 436 437 void throw_basefn_catch_basefn() noexcept { 438 try { 439 throw &baseMember::foo; 440 } catch(void(baseMember::*)()) { 441 } 442 } 443 444 void throw_basem_catch_basem_throw() noexcept { 445 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basem_catch_basem_throw' which should not throw exceptions 446 try { 447 auto ptr = &baseMember::iptr; 448 throw &ptr; 449 } catch(const int* baseMember::* const *) { 450 } 451 } 452 453 void throw_basem_catch_basem() noexcept { 454 try { 455 auto ptr = &baseMember::iptr; 456 throw &ptr; 457 } catch(const int* const baseMember::* const *) { 458 } 459 } 460 461 void throw_basem_catch_derivedm() noexcept { 462 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basem_catch_derivedm' which should not throw exceptions 463 try { 464 auto ptr = &baseMember::iptr; 465 throw &ptr; 466 } catch(const int* const derivedMember::* const *) { 467 } 468 } 469 470 void throw_derivedm_catch_basem() noexcept { 471 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derivedm_catch_basem' which should not throw exceptions 472 try { 473 int *derivedMember::* ptr = &derivedMember::iptr; 474 throw &ptr; 475 } catch(const int* const baseMember::* const *) { 476 } 477 } 478 479 void throw_original_catch_alias_2_warn() noexcept { 480 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_2_warn' which should not throw exceptions 481 using alias = const int *const; 482 483 try { 484 char **p = 0; 485 throw p; 486 } catch (volatile alias *) { 487 } 488 } 489 490 void try_nested_try(int n) noexcept { 491 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions 492 try { 493 try { 494 if (n) throw 1; 495 throw 1.1; 496 } catch(int &) { 497 } 498 } catch(double &) { 499 } 500 } 501 502 void bad_try_nested_try(int n) noexcept { 503 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_try_nested_try' which should not throw exceptions 504 try { 505 if (n) throw 1; 506 try { 507 throw 1.1; 508 } catch(int &) { 509 } 510 } catch(double &) { 511 } 512 } 513 514 void try_nested_catch() noexcept { 515 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions 516 try { 517 try { 518 throw 1; 519 } catch(int &) { 520 throw 1.1; 521 } 522 } catch(double &) { 523 } 524 } 525 526 void catch_nested_try() noexcept { 527 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'catch_nested_try' which should not throw exceptions 528 try { 529 throw 1; 530 } catch(int &) { 531 try { 532 throw 1; 533 } catch(int &) { 534 } 535 } 536 } 537 538 void bad_catch_nested_try() noexcept { 539 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_catch_nested_try' which should not throw exceptions 540 try { 541 throw 1; 542 } catch(int &) { 543 try { 544 throw 1.1; 545 } catch(int &) { 546 } 547 } catch(double &) { 548 } 549 } 550 551 void implicit_int_thrower() { 552 throw 1; 553 } 554 555 void explicit_int_thrower() noexcept(false) { 556 throw 1; 557 } 558 559 void indirect_implicit() noexcept { 560 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions 561 implicit_int_thrower(); 562 } 563 564 void indirect_explicit() noexcept { 565 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions 566 explicit_int_thrower(); 567 } 568 569 void indirect_catch() noexcept { 570 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_catch' which should not throw exceptions 571 try { 572 implicit_int_thrower(); 573 } catch(int&) { 574 } 575 } 576 577 template<typename T> 578 void dependent_throw() noexcept(sizeof(T)<4) { 579 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'dependent_throw' which should not throw exceptions 580 if (sizeof(T) > 4) 581 throw 1; 582 } 583 584 void swap(int&, int&) { 585 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions 586 throw 1; 587 } 588 589 void iter_swap(int&, int&) { 590 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_swap' which should not throw exceptions 591 throw 1; 592 } 593 594 void iter_move(int&) { 595 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_move' which should not throw exceptions 596 throw 1; 597 } 598 599 namespace std { 600 class bad_alloc {}; 601 } 602 603 void alloc() { 604 throw std::bad_alloc(); 605 } 606 607 void allocator() noexcept { 608 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'allocator' which should not throw exceptions 609 alloc(); 610 } 611 612 void enabled1() { 613 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions 614 throw 1; 615 } 616 617 void enabled2() { 618 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions 619 enabled1(); 620 } 621 622 void enabled3() { 623 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled3' which should not throw exceptions 624 try { 625 enabled1(); 626 } catch(...) { 627 } 628 } 629 630 class ignored1 {}; 631 class ignored2 {}; 632 633 void this_does_not_count() noexcept { 634 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count' which should not throw exceptions 635 throw ignored1(); 636 } 637 638 void this_does_not_count_either(int n) noexcept { 639 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count_either' which should not throw exceptions 640 try { 641 throw 1; 642 if (n) throw ignored2(); 643 } catch(int &) { 644 } 645 } 646 647 void this_counts(int n) noexcept { 648 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_counts' which should not throw exceptions 649 if (n) throw 1; 650 throw ignored1(); 651 } 652 653 void thrower(int n) { 654 throw n; 655 } 656 657 int directly_recursive(int n) noexcept { 658 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'directly_recursive' which should not throw exceptions 659 if (n == 0) 660 thrower(n); 661 return directly_recursive(n); 662 } 663 664 int indirectly_recursive(int n) noexcept; 665 666 int recursion_helper(int n) { 667 indirectly_recursive(n); 668 } 669 670 int indirectly_recursive(int n) noexcept { 671 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions 672 if (n == 0) 673 thrower(n); 674 return recursion_helper(n); 675 } 676 677 struct super_throws { 678 super_throws() noexcept(false) { throw 42; } 679 }; 680 681 struct sub_throws : super_throws { 682 sub_throws() noexcept : super_throws() {} 683 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions 684 }; 685 686 struct init_member_throws { 687 super_throws s; 688 689 init_member_throws() noexcept : s() {} 690 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions 691 }; 692 693 struct implicit_init_member_throws { 694 super_throws s; 695 696 implicit_init_member_throws() noexcept {} 697 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions 698 }; 699 700 struct init { 701 explicit init(int, int) noexcept(false) { throw 42; } 702 }; 703 704 struct in_class_init_throws { 705 init i{1, 2}; 706 707 in_class_init_throws() noexcept {} 708 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions 709 }; 710 711 int main() { 712 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions 713 throw 1; 714 return 0; 715 } 716 717 // The following function all incorrectly throw exceptions, *but* calling them 718 // should not yield a warning because they are marked as noexcept. 719 720 void test_basic_no_throw() noexcept { throw 42; } 721 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'test_basic_no_throw' which should not throw exceptions 722 723 void test_basic_throw() noexcept(false) { throw 42; } 724 725 void only_calls_non_throwing() noexcept { 726 test_basic_no_throw(); 727 } 728 729 void calls_non_and_throwing() noexcept { 730 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'calls_non_and_throwing' which should not throw exceptions 731 test_basic_no_throw(); 732 test_basic_throw(); 733 } 734 735 namespace PR55143 { namespace PR40583 { 736 737 struct test_explicit_throw { 738 test_explicit_throw() throw(int) { throw 42; } 739 test_explicit_throw(const test_explicit_throw&) throw(int) { throw 42; } 740 test_explicit_throw(test_explicit_throw&&) throw(int) { throw 42; } 741 test_explicit_throw& operator=(const test_explicit_throw&) throw(int) { throw 42; } 742 test_explicit_throw& operator=(test_explicit_throw&&) throw(int) { throw 42; } 743 ~test_explicit_throw() throw(int) { throw 42; } 744 }; 745 746 struct test_implicit_throw { 747 test_implicit_throw() { throw 42; } 748 test_implicit_throw(const test_implicit_throw&) { throw 42; } 749 test_implicit_throw(test_implicit_throw&&) { throw 42; } 750 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'test_implicit_throw' which should not throw exceptions 751 test_implicit_throw& operator=(const test_implicit_throw&) { throw 42; } 752 test_implicit_throw& operator=(test_implicit_throw&&) { throw 42; } 753 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: an exception may be thrown in function 'operator=' which should not throw exceptions 754 ~test_implicit_throw() { throw 42; } 755 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function '~test_implicit_throw' which should not throw exceptions 756 }; 757 758 }} 759 760 void pointer_exception_can_not_escape_with_const_void_handler() noexcept { 761 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'pointer_exception_can_not_escape_with_const_void_handler' which should not throw exceptions 762 const int value = 42; 763 try { 764 throw &value; 765 } catch (const void *) { 766 } 767 } 768 769 void pointer_exception_can_not_escape_with_void_handler() noexcept { 770 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'pointer_exception_can_not_escape_with_void_handler' which should not throw exceptions 771 int value = 42; 772 try { 773 throw &value; 774 } catch (void *) { 775 } 776 } 777