1010 lines · cpp
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: -- -fexceptions7// FIXME: Fix the checker to work in C++17 or later mode.8 9struct 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 exceptions12 throw 1;13 }14};15// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~throwing_destructor' here16 17struct throwing_move_constructor {18 throwing_move_constructor(throwing_move_constructor&&) {19 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'throwing_move_constructor' which should not throw exceptions20 throw 1;21 }22};23// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throwing_move_constructor' here24 25struct throwing_move_assignment {26 throwing_move_assignment& operator=(throwing_move_assignment&&) {27 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: an exception may be thrown in function 'operator=' which should not throw exceptions28 throw 1;29 }30};31// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator=' here32 33void throwing_noexcept() noexcept {34 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions35 throw 1;36}37// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throwing_noexcept' here38 39void throw_and_catch() noexcept {40 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch' which should not throw exceptions41 try {42 throw 1;43 } catch(int &) {44 }45}46 47void throw_and_catch_some(int n) noexcept {48 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_some' which should not throw exceptions49 try {50 if (n) throw 1;51 throw 1.1;52 } catch(int &) {53 }54}55// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'double' may be thrown in function 'throw_and_catch_some' here56 57void throw_and_catch_each(int n) noexcept {58 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions59 try {60 if (n) throw 1;61 throw 1.1;62 } catch(int &) {63 } catch(double &) {64 }65}66 67void throw_and_catch_all(int n) noexcept {68 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_all' which should not throw exceptions69 try {70 if (n) throw 1;71 throw 1.1;72 } catch(...) {73 }74}75 76void throw_and_rethrow() noexcept {77 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_rethrow' which should not throw exceptions78 try {79 throw 1;80 } catch(int &) {81 throw;82 }83}84// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_and_rethrow' here85 86void throw_catch_throw() noexcept {87 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions88 try {89 throw 1;90 } catch(int &) {91 throw 2;92 }93}94// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_catch_throw' here95 96void throw_catch_rethrow_the_rest(int n) noexcept {97 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions98 try {99 if (n) throw 1;100 throw 1.1;101 } catch(int &) {102 } catch(...) {103 throw;104 }105}106// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: unhandled exception of type 'double' may be thrown in function 'throw_catch_rethrow_the_rest' here107 108void throw_catch_pointer_c() noexcept {109 try {110 int a = 1;111 throw &a;112 } catch(const int *) {}113}114 115void throw_catch_pointer_v() noexcept {116 try {117 int a = 1;118 throw &a;119 } catch(volatile int *) {}120}121 122void throw_catch_pointer_cv() noexcept {123 try {124 int a = 1;125 throw &a;126 } catch(const volatile int *) {}127}128 129void throw_catch_multi_ptr_1() noexcept {130 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_multi_ptr_1' which should not throw exceptions131 try {132 char **p = 0;133 throw p;134 } catch (const char **) {135 }136}137// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'char **' may be thrown in function 'throw_catch_multi_ptr_1' here138 139void throw_catch_multi_ptr_2() noexcept {140 try {141 char **p = 0;142 throw p;143 } catch (const char *const *) {144 }145}146 147void throw_catch_multi_ptr_3() noexcept {148 try {149 char **p = 0;150 throw p;151 } catch (volatile char *const *) {152 }153}154 155void throw_catch_multi_ptr_4() noexcept {156 try {157 char **p = 0;158 throw p;159 } catch (volatile const char *const *) {160 }161}162 163// FIXME: In this case 'a' is convertible to the handler and should be caught164// but in reality it's thrown. Note that clang doesn't report a warning for165// this either.166void throw_catch_multi_ptr_5() noexcept {167 try {168 double *a[2][3];169 throw a;170 } catch (double *(*)[3]) {171 }172}173 174 175void throw_c_catch_pointer() noexcept {176 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_c_catch_pointer' which should not throw exceptions177 try {178 int a = 1;179 const int *p = &a;180 throw p;181 } catch(int *) {}182}183// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const int *' may be thrown in function 'throw_c_catch_pointer' here184 185void throw_c_catch_pointer_v() noexcept {186 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_c_catch_pointer_v' which should not throw exceptions187 try {188 int a = 1;189 const int *p = &a;190 throw p;191 } catch(volatile int *) {}192}193// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const int *' may be thrown in function 'throw_c_catch_pointer_v' here194 195void throw_v_catch_pointer() noexcept {196 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_v_catch_pointer' which should not throw exceptions197 try {198 int a = 1;199 volatile int *p = &a;200 throw p;201 } catch(int *) {}202}203// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'volatile int *' may be thrown in function 'throw_v_catch_pointer' here204 205void throw_v_catch_pointer_c() noexcept {206 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_v_catch_pointer_c' which should not throw exceptions207 try {208 int a = 1;209 volatile int *p = &a;210 throw p;211 } catch(const int *) {}212}213// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'volatile int *' may be thrown in function 'throw_v_catch_pointer_c' here214 215void throw_cv_catch_pointer_c() noexcept {216 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_cv_catch_pointer_c' which should not throw exceptions217 try {218 int a = 1;219 const volatile int *p = &a;220 throw p;221 } catch(const int *) {}222}223// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const volatile int *' may be thrown in function 'throw_cv_catch_pointer_c' here224 225void throw_cv_catch_pointer_v() noexcept {226 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_cv_catch_pointer_v' which should not throw exceptions227 try {228 int a = 1;229 const volatile int *p = &a;230 throw p;231 } catch(volatile int *) {}232}233// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const volatile int *' may be thrown in function 'throw_cv_catch_pointer_v' here234 235class base {};236class derived: public base {};237 238void throw_derived_catch_base() noexcept {239 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base' which should not throw exceptions240 try {241 throw derived();242 } catch(base &) {243 }244}245 246void throw_derived_alias_catch_base() noexcept {247 using alias = derived;248 249 try {250 throw alias();251 } catch(base &) {252 }253}254 255void throw_derived_catch_base_alias() noexcept {256 using alias = base;257 258 try {259 throw derived();260 } catch(alias &) {261 }262}263 264void throw_derived_catch_base_ptr_c() noexcept {265 try {266 derived d;267 throw &d;268 } catch(const base *) {269 }270}271 272void throw_derived_catch_base_ptr() noexcept {273 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ptr' which should not throw exceptions274 try {275 derived d;276 const derived *p = &d;277 throw p;278 } catch(base *) {279 }280}281// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'const derived *' may be thrown in function 'throw_derived_catch_base_ptr' here282 283class A {};284class B : A {};285 286// The following alias hell is deliberately created for testing.287using aliasedA = A;288class C : protected aliasedA {};289 290typedef aliasedA moreAliasedA;291class D : public moreAliasedA {};292 293using moreMoreAliasedA = moreAliasedA;294using aliasedD = D;295class E : public moreMoreAliasedA, public aliasedD {};296 297void throw_derived_catch_base_private() noexcept {298 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private' which should not throw exceptions299 try {300 B b;301 throw b;302 } catch(A) {303 }304}305// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'B' may be thrown in function 'throw_derived_catch_base_private' here306 307void throw_derived_catch_base_private_ptr() noexcept {308 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private_ptr' which should not throw exceptions309 try {310 B b;311 throw &b;312 } catch(A *) {313 }314}315// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'B *' may be thrown in function 'throw_derived_catch_base_private_ptr' here316 317void throw_derived_catch_base_protected() noexcept {318 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected' which should not throw exceptions319 try {320 C c;321 throw c;322 } catch(A) {323 }324}325// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'C' may be thrown in function 'throw_derived_catch_base_protected' here326 327void throw_derived_catch_base_protected_ptr() noexcept {328 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected_ptr' which should not throw exceptions329 try {330 C c;331 throw &c;332 } catch(A *) {333 }334}335// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'C *' may be thrown in function 'throw_derived_catch_base_protected_ptr' here336 337void throw_derived_catch_base_ambiguous() noexcept {338 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous' which should not throw exceptions339 try {340 E e;341 throw e;342 } catch(A) {343 }344}345// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'E' may be thrown in function 'throw_derived_catch_base_ambiguous' here346 347void throw_derived_catch_base_ambiguous_ptr() noexcept {348 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' which should not throw exceptions349 try {350 E e;351 throw e;352 } catch(A) {353 }354}355// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'E' may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' here356 357void throw_alias_catch_original() noexcept {358 using alias = int;359 360 try {361 alias a = 3;362 throw a;363 } catch (int) {364 }365}366 367void throw_alias_catch_original_warn() noexcept {368 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_alias_catch_original_warn' which should not throw exceptions369 using alias = float;370 371 try {372 alias a = 3;373 throw a;374 } catch (int) {375 }376}377// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'float' may be thrown in function 'throw_alias_catch_original_warn' here378 379void throw_original_catch_alias() noexcept {380 using alias = char;381 382 try {383 char **p = 0;384 throw p;385 } catch (volatile const alias *const *) {386 }387}388 389void throw_original_catch_alias_warn() noexcept {390 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_warn' which should not throw exceptions391 using alias = int;392 393 try {394 char **p = 0;395 throw p;396 } catch (volatile const alias *const *) {397 }398}399// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'char **' may be thrown in function 'throw_original_catch_alias_warn' here400 401void throw_original_catch_alias_2() noexcept {402 using alias = const char *const;403 404 try {405 char **p = 0;406 throw p;407 } catch (volatile alias *) {408 }409}410 411namespace a {412 int foo() { return 0; };413 414 void throw_regular_catch_regular() noexcept {415 try {416 throw &foo;417 } catch(int (*)()) {418 }419 }420}421 422namespace b {423 inline int foo() { return 0; };424 425 void throw_inline_catch_regular() noexcept {426 try {427 throw &foo;428 } catch(int (*)()) {429 }430 }431}432 433namespace c {434 inline int foo() noexcept { return 0; };435 436 void throw_noexcept_catch_regular() noexcept {437 try {438 throw &foo;439 } catch(int (*)()) {440 }441 }442}443 444struct baseMember {445 int *iptr;446 virtual void foo(){};447};448 449struct derivedMember : baseMember {450 void foo() override {};451};452 453void throw_basefn_catch_derivedfn() noexcept {454 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basefn_catch_derivedfn' which should not throw exceptions455 try {456 throw &baseMember::foo;457 } catch(void(derivedMember::*)()) {458 }459}460// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'void (baseMember::*)()' may be thrown in function 'throw_basefn_catch_derivedfn' here461 462void throw_basefn_catch_basefn() noexcept {463 try {464 throw &baseMember::foo;465 } catch(void(baseMember::*)()) {466 }467}468 469void throw_basem_catch_basem_throw() noexcept {470 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basem_catch_basem_throw' which should not throw exceptions471 try {472 auto ptr = &baseMember::iptr;473 throw &ptr;474 } catch(const int* baseMember::* const *) {475 }476}477// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int *baseMember::**' may be thrown in function 'throw_basem_catch_basem_throw' here478 479void throw_basem_catch_basem() noexcept {480 try {481 auto ptr = &baseMember::iptr;482 throw &ptr;483 } catch(const int* const baseMember::* const *) {484 }485}486 487void throw_basem_catch_derivedm() noexcept {488 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basem_catch_derivedm' which should not throw exceptions489 try {490 auto ptr = &baseMember::iptr;491 throw &ptr;492 } catch(const int* const derivedMember::* const *) {493 }494}495// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int *baseMember::**' may be thrown in function 'throw_basem_catch_derivedm' here496 497void throw_derivedm_catch_basem() noexcept {498 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derivedm_catch_basem' which should not throw exceptions499 try {500 int *derivedMember::* ptr = &derivedMember::iptr;501 throw &ptr;502 } catch(const int* const baseMember::* const *) {503 }504}505// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int *derivedMember::**' may be thrown in function 'throw_derivedm_catch_basem' here506 507void throw_original_catch_alias_2_warn() noexcept {508 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_2_warn' which should not throw exceptions509 using alias = const int *const;510 511 try {512 char **p = 0;513 throw p;514 } catch (volatile alias *) {515 }516}517// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'char **' may be thrown in function 'throw_original_catch_alias_2_warn' here518 519void try_nested_try(int n) noexcept {520 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions521 try {522 try {523 if (n) throw 1;524 throw 1.1;525 } catch(int &) {526 }527 } catch(double &) {528 }529}530 531void bad_try_nested_try(int n) noexcept {532 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_try_nested_try' which should not throw exceptions533 try {534 if (n) throw 1;535 try {536 throw 1.1;537 } catch(int &) {538 }539 } catch(double &) {540 }541}542// CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #0: unhandled exception of type 'int' may be thrown in function 'bad_try_nested_try' here543 544void try_nested_catch() noexcept {545 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions546 try {547 try {548 throw 1;549 } catch(int &) {550 throw 1.1;551 }552 } catch(double &) {553 }554}555 556void catch_nested_try() noexcept {557 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'catch_nested_try' which should not throw exceptions558 try {559 throw 1;560 } catch(int &) {561 try {562 throw 1;563 } catch(int &) {564 }565 }566}567 568void bad_catch_nested_try() noexcept {569 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_catch_nested_try' which should not throw exceptions570 try {571 throw 1;572 } catch(int &) {573 try {574 throw 1.1;575 } catch(int &) {576 }577 } catch(double &) {578 }579}580// CHECK-MESSAGES: :[[@LINE-6]]:7: note: frame #0: unhandled exception of type 'double' may be thrown in function 'bad_catch_nested_try' here581 582void implicit_int_thrower() {583 throw 1;584}585 586void explicit_int_thrower() noexcept(false) {587 throw 1;588}589 590void indirect_implicit() noexcept {591 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions592 implicit_int_thrower();593}594// CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'implicit_int_thrower' here595// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_implicit' calls function 'implicit_int_thrower' here596 597void indirect_explicit() noexcept {598 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions599 explicit_int_thrower();600}601// CHECK-MESSAGES: :[[@LINE-14]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'explicit_int_thrower' here602// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_explicit' calls function 'explicit_int_thrower' here603 604void indirect_catch() noexcept {605 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_catch' which should not throw exceptions606 try {607 implicit_int_thrower();608 } catch(int&) {609 }610}611 612template<typename T>613void dependent_throw() noexcept(sizeof(T)<4) {614 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'dependent_throw' which should not throw exceptions615 if (sizeof(T) > 4)616 throw 1;617}618 619void swap(int&, int&) {620 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions621 throw 1;622}623// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'swap' here624 625void iter_swap(int&, int&) {626 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_swap' which should not throw exceptions627 throw 1;628}629// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'iter_swap' here630 631void iter_move(int&) {632 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_move' which should not throw exceptions633 throw 1;634}635// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'iter_move' here636 637namespace std {638class bad_alloc {};639}640 641void alloc() {642 throw std::bad_alloc();643}644 645void allocator() noexcept {646 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'allocator' which should not throw exceptions647 alloc();648}649 650void enabled1() {651 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions652 throw 1;653}654// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'enabled1' here655 656void enabled2() {657 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions658 enabled1();659}660// CHECK-MESSAGES: :[[@LINE-8]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'enabled1' here661// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'enabled2' calls function 'enabled1' here662 663void enabled3() {664 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled3' which should not throw exceptions665 try {666 enabled1();667 } catch(...) {668 }669}670 671void deep_level3_thrower() {672 throw 42;673}674 675void deep_level2_caller() {676 deep_level3_thrower();677}678 679void deep_level1_caller() {680 deep_level2_caller();681}682 683void deep_stack_test() noexcept {684// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'deep_stack_test' which should not throw exceptions685 deep_level1_caller();686}687// CHECK-MESSAGES: :[[@LINE-15]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'deep_level3_thrower' here688// CHECK-MESSAGES: :[[@LINE-12]]:3: note: frame #1: function 'deep_level2_caller' calls function 'deep_level3_thrower' here689// CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #2: function 'deep_level1_caller' calls function 'deep_level2_caller' here690// CHECK-MESSAGES: :[[@LINE-5]]:3: note: frame #3: function 'deep_stack_test' calls function 'deep_level1_caller' here691 692// Template function call stack693template<typename T>694void template_thrower(T t) {695 throw T{};696}697 698template<typename T>699void template_caller(T t) {700 template_thrower<T>(t);701}702 703void template_stack_test() noexcept {704// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'template_stack_test' which should not throw exceptions705 template_caller<char>('a');706}707// CHECK-MESSAGES: :[[@LINE-12]]:3: note: frame #0: unhandled exception of type 'char' may be thrown in function 'template_thrower<char>' here708// CHECK-MESSAGES: :[[@LINE-8]]:3: note: frame #1: function 'template_caller<char>' calls function 'template_thrower<char>' here709// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #2: function 'template_stack_test' calls function 'template_caller<char>' here710 711// template function without instantiation is not warned712template<typename T>713void template_function_stack_test(T t) noexcept {714 template_thrower(t);715}716 717void multiple_exception_types(int choice) noexcept {718// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'multiple_exception_types' which should not throw exceptions719 if (choice == 1) {720 throw 42;721 } else if (choice == 2) {722 throw 3.14;723 } else if (choice == 3) {724 throw "string";725 }726}727// CHECK-MESSAGES: note: frame #0: unhandled exception of type '{{(int|double|const char \*)}}' may be thrown in function 'multiple_exception_types' here728 729class ignored1 {};730class ignored2 {};731 732void this_does_not_count() noexcept {733 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count' which should not throw exceptions734 throw ignored1();735}736 737void this_does_not_count_either(int n) noexcept {738 // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count_either' which should not throw exceptions739 try {740 throw 1;741 if (n) throw ignored2();742 } catch(int &) {743 }744}745 746void this_counts(int n) noexcept {747 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_counts' which should not throw exceptions748 if (n) throw 1;749 throw ignored1();750}751// CHECK-MESSAGES: :[[@LINE-3]]:10: note: frame #0: unhandled exception of type 'int' may be thrown in function 'this_counts' here752 753void thrower(int n) {754 throw n;755}756 757int directly_recursive(int n) noexcept {758 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'directly_recursive' which should not throw exceptions759 if (n == 0)760 thrower(n);761 return directly_recursive(n);762}763// CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here764// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #1: function 'directly_recursive' calls function 'thrower' here765 766int indirectly_recursive(int n) noexcept;767 768int recursion_helper(int n) {769 indirectly_recursive(n);770 return 0;771}772 773int indirectly_recursive(int n) noexcept {774 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions775 if (n == 0)776 thrower(n);777 return recursion_helper(n);778}779// CHECK-MESSAGES: :[[@LINE-25]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here780// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #1: function 'indirectly_recursive' calls function 'thrower' here781 782struct super_throws {783 super_throws() noexcept(false) { throw 42; }784};785 786struct sub_throws : super_throws {787 sub_throws() noexcept : super_throws() {}788 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions789};790// CHECK-MESSAGES: :[[@LINE-7]]:36: note: frame #0: unhandled exception of type 'int' may be thrown in function 'super_throws' here791// CHECK-MESSAGES: :[[@LINE-4]]:27: note: frame #1: function 'sub_throws' calls function 'super_throws' here792 793struct init_member_throws {794 super_throws s;795 796 init_member_throws() noexcept : s() {}797 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions798};799// CHECK-MESSAGES: :[[@LINE-16]]:36: note: frame #0: unhandled exception of type 'int' may be thrown in function 'super_throws' here800// CHECK-MESSAGES: :[[@LINE-4]]:35: note: frame #1: function 'init_member_throws' calls function 'super_throws' here801 802struct implicit_init_member_throws {803 super_throws s;804 805 implicit_init_member_throws() noexcept {}806 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions807};808// CHECK-MESSAGES: :[[@LINE-25]]:36: note: frame #0: unhandled exception of type 'int' may be thrown in function 'super_throws' here809// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #1: function 'implicit_init_member_throws' calls function 'super_throws'810 811struct init {812 explicit init(int, int) noexcept(false) { throw 42; }813};814 815struct in_class_init_throws {816 init i{1, 2};817 818 in_class_init_throws() noexcept {}819 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions820};821// CHECK-MESSAGES: :[[@LINE-9]]:45: note: frame #0: unhandled exception of type 'int' may be thrown in function 'init' here822// CHECK-MESSAGES: :[[@LINE-6]]:9: note: frame #1: function 'in_class_init_throws' calls function 'init' here823 824int main() {825 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions826 throw 1;827 return 0;828}829// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'main' here830 831// The following function all incorrectly throw exceptions, *but* calling them832// should not yield a warning because they are marked as noexcept.833 834void test_basic_no_throw() noexcept { throw 42; }835// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'test_basic_no_throw' which should not throw exceptions836// CHECK-MESSAGES: :[[@LINE-2]]:39: note: frame #0: unhandled exception of type 'int' may be thrown in function 'test_basic_no_throw' here837 838void test_basic_throw() noexcept(false) { throw 42; }839 840void only_calls_non_throwing() noexcept {841 test_basic_no_throw();842}843 844void calls_non_and_throwing() noexcept {845// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'calls_non_and_throwing' which should not throw exceptions846 test_basic_no_throw();847 test_basic_throw();848}849// CHECK-MESSAGES: :[[@LINE-11]]:43: note: frame #0: unhandled exception of type 'int' may be thrown in function 'test_basic_throw' here850// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'calls_non_and_throwing' calls function 'test_basic_throw' here851 852namespace PR55143 { namespace PR40583 {853 854struct test_explicit_throw {855 test_explicit_throw() throw(int) { throw 42; }856 test_explicit_throw(const test_explicit_throw&) throw(int) { throw 42; }857 test_explicit_throw(test_explicit_throw&&) throw(int) { throw 42; }858 test_explicit_throw& operator=(const test_explicit_throw&) throw(int) { throw 42; }859 test_explicit_throw& operator=(test_explicit_throw&&) throw(int) { throw 42; }860 ~test_explicit_throw() throw(int) { throw 42; }861};862 863struct test_implicit_throw {864 test_implicit_throw() { throw 42; }865 test_implicit_throw(const test_implicit_throw&) { throw 42; }866 test_implicit_throw(test_implicit_throw&&) { throw 42; }867 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'test_implicit_throw' which should not throw exceptions868 // CHECK-MESSAGES: :[[@LINE-2]]:50: note: frame #0: unhandled exception of type 'int' may be thrown in function 'test_implicit_throw' here869 test_implicit_throw& operator=(const test_implicit_throw&) { throw 42; }870 test_implicit_throw& operator=(test_implicit_throw&&) { throw 42; }871 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: an exception may be thrown in function 'operator=' which should not throw exceptions872 // CHECK-MESSAGES: :[[@LINE-2]]:61: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator='873 ~test_implicit_throw() { throw 42; }874 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function '~test_implicit_throw' which should not throw exceptions875 // CHECK-MESSAGES: :[[@LINE-2]]:30: note: frame #0: unhandled exception of type 'int' may be thrown in function '~test_implicit_throw' here876};877 878}}879 880void pointer_exception_can_not_escape_with_const_void_handler() noexcept {881 // 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 exceptions882 const int value = 42;883 try {884 throw &value;885 } catch (const void *) {886 }887}888 889void pointer_exception_can_not_escape_with_void_handler() noexcept {890 // 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 exceptions891 int value = 42;892 try {893 throw &value;894 } catch (void *) {895 }896}897 898void throw_in_uninvoked_lambda() noexcept {899 [] { throw 42; };900}901 902void throw_in_lambda() noexcept {903 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_in_lambda' which should not throw exceptions904 [] { throw 42; }();905 // CHECK-MESSAGES: :[[@LINE-1]]:8: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here906 // CHECK-MESSAGES: :[[@LINE-2]]:19: note: frame #1: function 'throw_in_lambda' calls function 'operator()' here907}908 909struct copy_constructor_throws {910 copy_constructor_throws(const copy_constructor_throws&) { throw 42; }911};912 913void throw_in_lambda_default_by_value_capture(const copy_constructor_throws& a) noexcept {914 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_in_lambda_default_by_value_capture' which should not throw exceptions915 [=] { a; };916 // CHECK-MESSAGES: :[[@LINE-6]]:61: note: frame #0: unhandled exception of type 'int' may be thrown in function 'copy_constructor_throws' here917 // CHECK-MESSAGES: :[[@LINE-2]]:4: note: frame #1: function 'throw_in_lambda_default_by_value_capture' calls function 'copy_constructor_throws' here918}919 920void throw_in_lambda_explicit_by_value_capture(const copy_constructor_throws& a) noexcept {921 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_in_lambda_explicit_by_value_capture' which should not throw exceptions922 [a] {};923 // CHECK-MESSAGES: :[[@LINE-13]]:61: note: frame #0: unhandled exception of type 'int' may be thrown in function 'copy_constructor_throws' here924 // CHECK-MESSAGES: :[[@LINE-2]]:4: note: frame #1: function 'throw_in_lambda_explicit_by_value_capture' calls function 'copy_constructor_throws' here925}926 927void no_throw_in_lambda_by_reference_capture(const copy_constructor_throws& a) noexcept {928 [&] { a; };929 [&a] {};930}931 932void throw_in_lambda_init_capture() noexcept {933 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_in_lambda_init_capture' which should not throw exceptions934 [a = [] { throw 42; return 0; }()] {};935 // CHECK-MESSAGES: :[[@LINE-1]]:13: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here936 // CHECK-MESSAGES: :[[@LINE-2]]:34: note: frame #1: function 'throw_in_lambda_init_capture' calls function 'operator()' here937}938 939void throw_from_nested_lambda() noexcept {940 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_from_nested_lambda' which should not throw exceptions941 [] { [] { throw 42; }(); }();942 // CHECK-MESSAGES: :[[@LINE-1]]:13: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here943 // CHECK-MESSAGES: :[[@LINE-2]]:24: note: frame #1: function 'operator()' calls function 'operator()' here944 // CHECK-MESSAGES: :[[@LINE-3]]:29: note: frame #2: function 'throw_from_nested_lambda' calls function 'operator()' here945}946 947const auto throw_in_noexcept_lambda = [] () noexcept { throw 42; };948// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: an exception may be thrown in function 'operator()' which should not throw exceptions949// CHECK-MESSAGES: :[[@LINE-2]]:56: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here950 951int thrower() {952 throw 42;953}954 955const auto indirect_throw_in_noexcept_lambda = [] () noexcept { thrower(); };956// CHECK-MESSAGES: :[[@LINE-1]]:48: warning: an exception may be thrown in function 'operator()' which should not throw exceptions957// CHECK-MESSAGES: :[[@LINE-5]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here958// CHECK-MESSAGES: :[[@LINE-3]]:65: note: frame #1: function 'operator()' calls function 'thrower' here959 960int f(int);961void throw_in_function_arg() noexcept {962// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_in_function_arg' which should not throw exceptions963 f(false ? 0 : throw 1);964}965// CHECK-MESSAGES: :[[@LINE-2]]:17: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_in_function_arg' here966 967int g(int, int, int);968void throw_in_last_function_arg() noexcept {969// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_in_last_function_arg' which should not throw exceptions970 g(42, 67, false ? 0 : throw 1);971}972// CHECK-MESSAGES: :[[@LINE-2]]:25: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_in_last_function_arg' here973 974void indirect_throw_in_function_arg() noexcept {975// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_throw_in_function_arg' which should not throw exceptions976 f(thrower());977}978// CHECK-MESSAGES: :[[@LINE-26]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here979// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #1: function 'indirect_throw_in_function_arg' calls function 'thrower' here980 981void indirect_throw_from_lambda_in_function_arg() noexcept {982// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_throw_from_lambda_in_function_arg' which should not throw exceptions983 f([] { throw 1; return 0; }());984}985// CHECK-MESSAGES: :[[@LINE-2]]:10: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here986// CHECK-MESSAGES: :[[@LINE-3]]:30: note: frame #1: function 'indirect_throw_from_lambda_in_function_arg' calls function 'operator()' here987 988struct S {989 S(int) noexcept {}990};991 992void throw_in_constructor_arg() noexcept {993// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_in_constructor_arg' which should not throw exceptions994 S s(false ? 0 : throw 1);995}996// CHECK-MESSAGES: :[[@LINE-2]]:19: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_in_constructor_arg' here997 998void indirect_throw_in_constructor_arg() noexcept {999// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_throw_in_constructor_arg' which should not throw exceptions1000 S s = thrower();1001}1002// CHECK-MESSAGES: :[[@LINE-50]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here1003// CHECK-MESSAGES: :[[@LINE-3]]:9: note: frame #1: function 'indirect_throw_in_constructor_arg' calls function 'thrower' here1004 1005void weird_throw_in_call_subexpression() noexcept {1006// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'weird_throw_in_call_subexpression' which should not throw exceptions1007 (false ? []{} : throw 1)();1008}1009// CHECK-MESSAGES: :[[@LINE-2]]:19: note: frame #0: unhandled exception of type 'int' may be thrown in function 'weird_throw_in_call_subexpression' here1010