759 lines
20 KiB
C++
759 lines
20 KiB
C++
|
// RUN: %check_clang_tidy -std=c++11,c++14 %s bugprone-exception-escape %t -- \
|
||
|
// RUN: -config="{CheckOptions: { \
|
||
|
// RUN: bugprone-exception-escape.IgnoredExceptions: 'ignored1,ignored2', \
|
||
|
// RUN: bugprone-exception-escape.FunctionsThatShouldNotThrow: 'enabled1,enabled2,enabled3' \
|
||
|
// RUN: }}" \
|
||
|
// RUN: -- -fexceptions
|
||
|
// FIXME: Fix the checker to work in C++17 or later mode.
|
||
|
|
||
|
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 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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_catch_pointer_c() noexcept {
|
||
|
try {
|
||
|
int a = 1;
|
||
|
throw &a;
|
||
|
} catch(const int *) {}
|
||
|
}
|
||
|
|
||
|
void throw_catch_pointer_v() noexcept {
|
||
|
try {
|
||
|
int a = 1;
|
||
|
throw &a;
|
||
|
} catch(volatile int *) {}
|
||
|
}
|
||
|
|
||
|
void throw_catch_pointer_cv() noexcept {
|
||
|
try {
|
||
|
int a = 1;
|
||
|
throw &a;
|
||
|
} catch(const volatile int *) {}
|
||
|
}
|
||
|
|
||
|
void throw_catch_multi_ptr_1() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_multi_ptr_1' which should not throw exceptions
|
||
|
try {
|
||
|
char **p = 0;
|
||
|
throw p;
|
||
|
} catch (const char **) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_catch_multi_ptr_2() noexcept {
|
||
|
try {
|
||
|
char **p = 0;
|
||
|
throw p;
|
||
|
} catch (const char *const *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_catch_multi_ptr_3() noexcept {
|
||
|
try {
|
||
|
char **p = 0;
|
||
|
throw p;
|
||
|
} catch (volatile char *const *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_catch_multi_ptr_4() noexcept {
|
||
|
try {
|
||
|
char **p = 0;
|
||
|
throw p;
|
||
|
} catch (volatile const char *const *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// FIXME: In this case 'a' is convertible to the handler and should be caught
|
||
|
// but in reality it's thrown. Note that clang doesn't report a warning for
|
||
|
// this either.
|
||
|
void throw_catch_multi_ptr_5() noexcept {
|
||
|
try {
|
||
|
double *a[2][3];
|
||
|
throw a;
|
||
|
} catch (double *(*)[3]) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void throw_c_catch_pointer() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_c_catch_pointer' which should not throw exceptions
|
||
|
try {
|
||
|
int a = 1;
|
||
|
const int *p = &a;
|
||
|
throw p;
|
||
|
} catch(int *) {}
|
||
|
}
|
||
|
|
||
|
void throw_c_catch_pointer_v() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_c_catch_pointer_v' which should not throw exceptions
|
||
|
try {
|
||
|
int a = 1;
|
||
|
const int *p = &a;
|
||
|
throw p;
|
||
|
} catch(volatile int *) {}
|
||
|
}
|
||
|
|
||
|
void throw_v_catch_pointer() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_v_catch_pointer' which should not throw exceptions
|
||
|
try {
|
||
|
int a = 1;
|
||
|
volatile int *p = &a;
|
||
|
throw p;
|
||
|
} catch(int *) {}
|
||
|
}
|
||
|
|
||
|
void throw_v_catch_pointer_c() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_v_catch_pointer_c' which should not throw exceptions
|
||
|
try {
|
||
|
int a = 1;
|
||
|
volatile int *p = &a;
|
||
|
throw p;
|
||
|
} catch(const int *) {}
|
||
|
}
|
||
|
|
||
|
void throw_cv_catch_pointer_c() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_cv_catch_pointer_c' which should not throw exceptions
|
||
|
try {
|
||
|
int a = 1;
|
||
|
const volatile int *p = &a;
|
||
|
throw p;
|
||
|
} catch(const int *) {}
|
||
|
}
|
||
|
|
||
|
void throw_cv_catch_pointer_v() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_cv_catch_pointer_v' which should not throw exceptions
|
||
|
try {
|
||
|
int a = 1;
|
||
|
const volatile int *p = &a;
|
||
|
throw p;
|
||
|
} catch(volatile int *) {}
|
||
|
}
|
||
|
|
||
|
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 throw_derived_alias_catch_base() noexcept {
|
||
|
using alias = derived;
|
||
|
|
||
|
try {
|
||
|
throw alias();
|
||
|
} catch(base &) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_derived_catch_base_alias() noexcept {
|
||
|
using alias = base;
|
||
|
|
||
|
try {
|
||
|
throw derived();
|
||
|
} catch(alias &) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_derived_catch_base_ptr_c() noexcept {
|
||
|
try {
|
||
|
derived d;
|
||
|
throw &d;
|
||
|
} catch(const base *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_derived_catch_base_ptr() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ptr' which should not throw exceptions
|
||
|
try {
|
||
|
derived d;
|
||
|
const derived *p = &d;
|
||
|
throw p;
|
||
|
} catch(base *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class A {};
|
||
|
class B : A {};
|
||
|
|
||
|
// The following alias hell is deliberately created for testing.
|
||
|
using aliasedA = A;
|
||
|
class C : protected aliasedA {};
|
||
|
|
||
|
typedef aliasedA moreAliasedA;
|
||
|
class D : public moreAliasedA {};
|
||
|
|
||
|
using moreMoreAliasedA = moreAliasedA;
|
||
|
using aliasedD = D;
|
||
|
class E : public moreMoreAliasedA, public aliasedD {};
|
||
|
|
||
|
void throw_derived_catch_base_private() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private' which should not throw exceptions
|
||
|
try {
|
||
|
B b;
|
||
|
throw b;
|
||
|
} catch(A) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_derived_catch_base_private_ptr() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private_ptr' which should not throw exceptions
|
||
|
try {
|
||
|
B b;
|
||
|
throw &b;
|
||
|
} catch(A *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_derived_catch_base_protected() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected' which should not throw exceptions
|
||
|
try {
|
||
|
C c;
|
||
|
throw c;
|
||
|
} catch(A) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_derived_catch_base_protected_ptr() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected_ptr' which should not throw exceptions
|
||
|
try {
|
||
|
C c;
|
||
|
throw &c;
|
||
|
} catch(A *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_derived_catch_base_ambiguous() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous' which should not throw exceptions
|
||
|
try {
|
||
|
E e;
|
||
|
throw e;
|
||
|
} catch(A) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_derived_catch_base_ambiguous_ptr() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' which should not throw exceptions
|
||
|
try {
|
||
|
E e;
|
||
|
throw e;
|
||
|
} catch(A) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_alias_catch_original() noexcept {
|
||
|
using alias = int;
|
||
|
|
||
|
try {
|
||
|
alias a = 3;
|
||
|
throw a;
|
||
|
} catch (int) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_alias_catch_original_warn() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_alias_catch_original_warn' which should not throw exceptions
|
||
|
using alias = float;
|
||
|
|
||
|
try {
|
||
|
alias a = 3;
|
||
|
throw a;
|
||
|
} catch (int) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_original_catch_alias() noexcept {
|
||
|
using alias = char;
|
||
|
|
||
|
try {
|
||
|
char **p = 0;
|
||
|
throw p;
|
||
|
} catch (volatile const alias *const *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_original_catch_alias_warn() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_warn' which should not throw exceptions
|
||
|
using alias = int;
|
||
|
|
||
|
try {
|
||
|
char **p = 0;
|
||
|
throw p;
|
||
|
} catch (volatile const alias *const *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_original_catch_alias_2() noexcept {
|
||
|
using alias = const char *const;
|
||
|
|
||
|
try {
|
||
|
char **p = 0;
|
||
|
throw p;
|
||
|
} catch (volatile alias *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
namespace a {
|
||
|
int foo() { return 0; };
|
||
|
|
||
|
void throw_regular_catch_regular() noexcept {
|
||
|
try {
|
||
|
throw &foo;
|
||
|
} catch(int (*)()) {
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
namespace b {
|
||
|
inline int foo() { return 0; };
|
||
|
|
||
|
void throw_inline_catch_regular() noexcept {
|
||
|
try {
|
||
|
throw &foo;
|
||
|
} catch(int (*)()) {
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
namespace c {
|
||
|
inline int foo() noexcept { return 0; };
|
||
|
|
||
|
void throw_noexcept_catch_regular() noexcept {
|
||
|
try {
|
||
|
throw &foo;
|
||
|
} catch(int (*)()) {
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
struct baseMember {
|
||
|
int *iptr;
|
||
|
virtual void foo(){};
|
||
|
};
|
||
|
|
||
|
struct derivedMember : baseMember {
|
||
|
void foo() override {};
|
||
|
};
|
||
|
|
||
|
void throw_basefn_catch_derivedfn() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basefn_catch_derivedfn' which should not throw exceptions
|
||
|
try {
|
||
|
throw &baseMember::foo;
|
||
|
} catch(void(derivedMember::*)()) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_basefn_catch_basefn() noexcept {
|
||
|
try {
|
||
|
throw &baseMember::foo;
|
||
|
} catch(void(baseMember::*)()) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_basem_catch_basem_throw() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basem_catch_basem_throw' which should not throw exceptions
|
||
|
try {
|
||
|
auto ptr = &baseMember::iptr;
|
||
|
throw &ptr;
|
||
|
} catch(const int* baseMember::* const *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_basem_catch_basem() noexcept {
|
||
|
try {
|
||
|
auto ptr = &baseMember::iptr;
|
||
|
throw &ptr;
|
||
|
} catch(const int* const baseMember::* const *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_basem_catch_derivedm() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_basem_catch_derivedm' which should not throw exceptions
|
||
|
try {
|
||
|
auto ptr = &baseMember::iptr;
|
||
|
throw &ptr;
|
||
|
} catch(const int* const derivedMember::* const *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_derivedm_catch_basem() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derivedm_catch_basem' which should not throw exceptions
|
||
|
try {
|
||
|
int *derivedMember::* ptr = &derivedMember::iptr;
|
||
|
throw &ptr;
|
||
|
} catch(const int* const baseMember::* const *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void throw_original_catch_alias_2_warn() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_2_warn' which should not throw exceptions
|
||
|
using alias = const int *const;
|
||
|
|
||
|
try {
|
||
|
char **p = 0;
|
||
|
throw p;
|
||
|
} catch (volatile alias *) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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() noexcept(false) {
|
||
|
throw 1;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
void iter_swap(int&, int&) {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_swap' which should not throw exceptions
|
||
|
throw 1;
|
||
|
}
|
||
|
|
||
|
void iter_move(int&) {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_move' 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;
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
struct super_throws {
|
||
|
super_throws() noexcept(false) { throw 42; }
|
||
|
};
|
||
|
|
||
|
struct sub_throws : super_throws {
|
||
|
sub_throws() noexcept : super_throws() {}
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions
|
||
|
};
|
||
|
|
||
|
struct init_member_throws {
|
||
|
super_throws s;
|
||
|
|
||
|
init_member_throws() noexcept : s() {}
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions
|
||
|
};
|
||
|
|
||
|
struct implicit_init_member_throws {
|
||
|
super_throws s;
|
||
|
|
||
|
implicit_init_member_throws() noexcept {}
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions
|
||
|
};
|
||
|
|
||
|
struct init {
|
||
|
explicit init(int, int) noexcept(false) { throw 42; }
|
||
|
};
|
||
|
|
||
|
struct in_class_init_throws {
|
||
|
init i{1, 2};
|
||
|
|
||
|
in_class_init_throws() noexcept {}
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions
|
||
|
};
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
// The following function all incorrectly throw exceptions, *but* calling them
|
||
|
// should not yield a warning because they are marked as noexcept.
|
||
|
|
||
|
void test_basic_no_throw() noexcept { throw 42; }
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'test_basic_no_throw' which should not throw exceptions
|
||
|
|
||
|
void test_basic_throw() noexcept(false) { throw 42; }
|
||
|
|
||
|
void only_calls_non_throwing() noexcept {
|
||
|
test_basic_no_throw();
|
||
|
}
|
||
|
|
||
|
void calls_non_and_throwing() noexcept {
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'calls_non_and_throwing' which should not throw exceptions
|
||
|
test_basic_no_throw();
|
||
|
test_basic_throw();
|
||
|
}
|
||
|
|
||
|
namespace PR55143 { namespace PR40583 {
|
||
|
|
||
|
struct test_explicit_throw {
|
||
|
test_explicit_throw() throw(int) { throw 42; }
|
||
|
test_explicit_throw(const test_explicit_throw&) throw(int) { throw 42; }
|
||
|
test_explicit_throw(test_explicit_throw&&) throw(int) { throw 42; }
|
||
|
test_explicit_throw& operator=(const test_explicit_throw&) throw(int) { throw 42; }
|
||
|
test_explicit_throw& operator=(test_explicit_throw&&) throw(int) { throw 42; }
|
||
|
~test_explicit_throw() throw(int) { throw 42; }
|
||
|
};
|
||
|
|
||
|
struct test_implicit_throw {
|
||
|
test_implicit_throw() { throw 42; }
|
||
|
test_implicit_throw(const test_implicit_throw&) { throw 42; }
|
||
|
test_implicit_throw(test_implicit_throw&&) { throw 42; }
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'test_implicit_throw' which should not throw exceptions
|
||
|
test_implicit_throw& operator=(const test_implicit_throw&) { throw 42; }
|
||
|
test_implicit_throw& operator=(test_implicit_throw&&) { throw 42; }
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: an exception may be thrown in function 'operator=' which should not throw exceptions
|
||
|
~test_implicit_throw() { throw 42; }
|
||
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function '~test_implicit_throw' which should not throw exceptions
|
||
|
};
|
||
|
|
||
|
}}
|