| // RUN: %check_clang_tidy %s bugprone-exception-escape %t -- -extra-arg=-std=c++11 -extra-arg=-fexceptions -config="{CheckOptions: [{key: bugprone-exception-escape.IgnoredExceptions, value: 'ignored1,ignored2'}, {key: bugprone-exception-escape.FunctionsThatShouldNotThrow, value: 'enabled1,enabled2,enabled3'}]}" -- |
| |
| struct throwing_destructor { |
| ~throwing_destructor() { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function '~throwing_destructor' which should not throw exceptions |
| throw 1; |
| } |
| }; |
| |
| struct throwing_move_constructor { |
| throwing_move_constructor(throwing_move_constructor&&) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'throwing_move_constructor' which should not throw exceptions |
| throw 1; |
| } |
| }; |
| |
| struct throwing_move_assignment { |
| throwing_move_assignment& operator=(throwing_move_assignment&&) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: an exception may be thrown in function 'operator=' which should not throw exceptions |
| throw 1; |
| } |
| }; |
| |
| void throwing_noexcept() noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions |
| throw 1; |
| } |
| |
| void throwing_throw_nothing() throw() { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_throw_nothing' which should not throw exceptions |
| throw 1; |
| } |
| |
| void throw_and_catch() noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch' which should not throw exceptions |
| try { |
| throw 1; |
| } catch(int &) { |
| } |
| } |
| |
| void throw_and_catch_some(int n) noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_some' which should not throw exceptions |
| try { |
| if (n) throw 1; |
| throw 1.1; |
| } catch(int &) { |
| } |
| } |
| |
| void throw_and_catch_each(int n) noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions |
| try { |
| if (n) throw 1; |
| throw 1.1; |
| } catch(int &) { |
| } catch(double &) { |
| } |
| } |
| |
| void throw_and_catch_all(int n) noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_all' which should not throw exceptions |
| try { |
| if (n) throw 1; |
| throw 1.1; |
| } catch(...) { |
| } |
| } |
| |
| void throw_and_rethrow() noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_rethrow' which should not throw exceptions |
| try { |
| throw 1; |
| } catch(int &) { |
| throw; |
| } |
| } |
| |
| void throw_catch_throw() noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions |
| try { |
| throw 1; |
| } catch(int &) { |
| throw 2; |
| } |
| } |
| |
| void throw_catch_rethrow_the_rest(int n) noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions |
| try { |
| if (n) throw 1; |
| throw 1.1; |
| } catch(int &) { |
| } catch(...) { |
| throw; |
| } |
| } |
| |
| class base {}; |
| class derived: public base {}; |
| |
| void throw_derived_catch_base() noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base' which should not throw exceptions |
| try { |
| throw derived(); |
| } catch(base &) { |
| } |
| } |
| |
| void try_nested_try(int n) noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions |
| try { |
| try { |
| if (n) throw 1; |
| throw 1.1; |
| } catch(int &) { |
| } |
| } catch(double &) { |
| } |
| } |
| |
| void bad_try_nested_try(int n) noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_try_nested_try' which should not throw exceptions |
| try { |
| if (n) throw 1; |
| try { |
| throw 1.1; |
| } catch(int &) { |
| } |
| } catch(double &) { |
| } |
| } |
| |
| void try_nested_catch() noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions |
| try { |
| try { |
| throw 1; |
| } catch(int &) { |
| throw 1.1; |
| } |
| } catch(double &) { |
| } |
| } |
| |
| void catch_nested_try() noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'catch_nested_try' which should not throw exceptions |
| try { |
| throw 1; |
| } catch(int &) { |
| try { |
| throw 1; |
| } catch(int &) { |
| } |
| } |
| } |
| |
| void bad_catch_nested_try() noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'bad_catch_nested_try' which should not throw exceptions |
| try { |
| throw 1; |
| } catch(int &) { |
| try { |
| throw 1.1; |
| } catch(int &) { |
| } |
| } catch(double &) { |
| } |
| } |
| |
| void implicit_int_thrower() { |
| throw 1; |
| } |
| |
| void explicit_int_thrower() throw(int); |
| |
| void indirect_implicit() noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions |
| implicit_int_thrower(); |
| } |
| |
| void indirect_explicit() noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions |
| explicit_int_thrower(); |
| } |
| |
| void indirect_catch() noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_catch' which should not throw exceptions |
| try { |
| implicit_int_thrower(); |
| } catch(int&) { |
| } |
| } |
| |
| template<typename T> |
| void dependent_throw() noexcept(sizeof(T)<4) { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'dependent_throw' which should not throw exceptions |
| if (sizeof(T) > 4) |
| throw 1; |
| } |
| |
| void swap(int&, int&) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions |
| throw 1; |
| } |
| |
| namespace std { |
| class bad_alloc {}; |
| } |
| |
| void alloc() { |
| throw std::bad_alloc(); |
| } |
| |
| void allocator() noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'allocator' which should not throw exceptions |
| alloc(); |
| } |
| |
| void enabled1() { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions |
| throw 1; |
| } |
| |
| void enabled2() { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions |
| enabled1(); |
| } |
| |
| void enabled3() { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled3' which should not throw exceptions |
| try { |
| enabled1(); |
| } catch(...) { |
| } |
| } |
| |
| class ignored1 {}; |
| class ignored2 {}; |
| |
| void this_does_not_count() noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count' which should not throw exceptions |
| throw ignored1(); |
| } |
| |
| void this_does_not_count_either(int n) noexcept { |
| // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_does_not_count_either' which should not throw exceptions |
| try { |
| throw 1; |
| if (n) throw ignored2(); |
| } catch(int &) { |
| } |
| } |
| |
| void this_counts(int n) noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'this_counts' which should not throw exceptions |
| if (n) throw 1; |
| throw ignored1(); |
| } |
| |
| void thrower(int n) { |
| throw n; |
| } |
| |
| int directly_recursive(int n) noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'directly_recursive' which should not throw exceptions |
| if (n == 0) |
| thrower(n); |
| return directly_recursive(n); |
| } |
| |
| int indirectly_recursive(int n) noexcept; |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions |
| |
| int recursion_helper(int n) { |
| indirectly_recursive(n); |
| } |
| |
| int indirectly_recursive(int n) noexcept { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'indirectly_recursive' which should not throw exceptions |
| if (n == 0) |
| thrower(n); |
| return recursion_helper(n); |
| } |
| |
| int main() { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions |
| throw 1; |
| return 0; |
| } |