ASSERT_EQUALS("[test.cpp:3:9]: (warning) Class x is not safe, destructor throws exception [exceptThrowInDestructor]\n"
"[test.cpp:3:9]: (error) Exception thrown in function declared not to throw exceptions. [throwInNoexceptFunction]\n", errout_str());
check("class x {\n"
" ~x();\n"
"};\n"
"x::~x() {\n"
" throw e;\n"
"}");
ASSERT_EQUALS("[test.cpp:5:5]: (warning) Class x is not safe, destructor throws exception [exceptThrowInDestructor]\n"
"[test.cpp:5:5]: (error) Exception thrown in function declared not to throw exceptions. [throwInNoexceptFunction]\n", errout_str());
// #3858 - throwing exception in try block in destructor.
check("class x {\n"
" ~x() {\n"
" try {\n"
" throw e;\n"
" } catch (...) {\n"
" }\n"
" }\n"
"}");
ASSERT_EQUALS("", errout_str());
check("class x {\n"
" ~x() {\n"
" if(!std::uncaught_exception()) {\n"
" throw e;\n"
" }\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:4:13]: (error) Exception thrown in function declared not to throw exceptions. [throwInNoexceptFunction]\n", errout_str());
// #11031 should not warn when noexcept false
check("class A {\n"
"public:\n"
" ~A() noexcept(false) {\n"
" throw 30;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout_str());
}
voiddeallocThrow1() {
check("int * p;\n"
"void f(int x) {\n"
" delete p;\n"
" if (x)\n"
" throw 123;\n"
" p = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:5:9]: (warning) Exception thrown in invalid state, 'p' points at deallocated memory. [exceptDeallocThrow]\n", errout_str());
check("void f() {\n"
" static int* p = foo;\n"
" delete p;\n"
" if (foo)\n"
" throw 1;\n"
" p = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:5:9]: (warning) Exception thrown in invalid state, 'p' points at deallocated memory. [exceptDeallocThrow]\n", errout_str());
}
voiddeallocThrow2() {
check("void f() {\n"
" int* p = 0;\n"
" delete p;\n"
" if (foo)\n"
" throw 1;\n"
" p = new int;\n"
"}", dinit(CheckOptions, $.inconclusive = true));
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" static int* p = 0;\n"
" delete p;\n"
" reset(p);\n"
" throw 1;\n"
"}", dinit(CheckOptions, $.inconclusive = true));
ASSERT_EQUALS("", errout_str());
}
voiddeallocThrow3() {
check("void f() {\n"
" static int* p = 0;\n"
" delete p;\n"
" throw 1;\n"
"}");
ASSERT_EQUALS("", errout_str());
check("void f() {\n"
" static int* p = 0;\n"
" delete p;\n"
" throw 1;\n"
"}", dinit(CheckOptions, $.inconclusive = true));
ASSERT_EQUALS("[test.cpp:4:5]: (warning) Exception thrown in invalid state, 'p' points at deallocated memory. [exceptDeallocThrow]\n", errout_str());
}
voidrethrowCopy1() {
check("void f() {\n"
" try\n"
" {\n"
" foo();\n"
" }\n"
" catch(const exception& err)\n"
" {\n"
" throw err;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:8:9]: (style) Throwing a copy of the caught exception instead of rethrowing the original exception. [exceptRethrowCopy]\n", errout_str());
}
voidrethrowCopy2() {
check("void f() {\n"
" try\n"
" {\n"
" foo();\n"
" }\n"
" catch(exception& err)\n"
" {\n"
" throw err;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:8:9]: (style) Throwing a copy of the caught exception instead of rethrowing the original exception. [exceptRethrowCopy]\n", errout_str());
}
voidrethrowCopy3() {
check("void f() {\n"
" try {\n"
" foo();\n"
" }\n"
" catch(std::runtime_error& err) {\n"
" throw err;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:6:9]: (style) Throwing a copy of the caught exception instead of rethrowing the original exception. [exceptRethrowCopy]\n", errout_str());
}
voidrethrowCopy4() {
check("void f() {\n"
" try\n"
" {\n"
" foo();\n"
" }\n"
" catch(const exception& err)\n"
" {\n"
" exception err2;\n"
" throw err2;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout_str());
}
voidrethrowCopy5() {
check("void f() {\n"
" try {\n"
" foo();\n"
" }\n"
" catch(const exception& outer) {\n"
" try {\n"
" foo(outer);\n"
" }\n"
" catch(const exception& inner) {\n"
" throw inner;\n"
" }\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:10:13]: (style) Throwing a copy of the caught exception instead of rethrowing the original exception. [exceptRethrowCopy]\n", errout_str());
check("void f() {\n"
" try {\n"
" foo();\n"
" }\n"
" catch(const exception& outer) {\n"
" try {\n"
" foo(outer);\n"
" }\n"
" catch(const exception& inner) {\n"
" throw outer;\n"
" }\n"
" }\n"
"}");
ASSERT_EQUALS("", errout_str());
}
voidcatchExceptionByValue() {
check("void f() {\n"
" try {\n"
" bar();\n"
" }\n"
" catch( ::std::exception err) {\n"
" foo(err);\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:5:5]: (style) Exception should be caught by reference. [catchExceptionByValue]\n", errout_str());
check("void f() {\n"
" try {\n"
" bar();\n"
" }\n"
" catch(const exception err) {\n"
" foo(err);\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:5:5]: (style) Exception should be caught by reference. [catchExceptionByValue]\n", errout_str());
ASSERT_EQUALS("[test.cpp:1:46]: (error) Rethrowing current exception with 'throw;', it seems there is no current exception to rethrow."
" If there is no current exception this calls std::terminate(). More: https://isocpp.org/wiki/faq/exceptions#throw-without-an-object [rethrowNoCurrentException]\n", errout_str());
ASSERT_EQUALS("[test.cpp:1:43]: (error) Rethrowing current exception with 'throw;', it seems there is no current exception to rethrow."
" If there is no current exception this calls std::terminate(). More: https://isocpp.org/wiki/faq/exceptions#throw-without-an-object [rethrowNoCurrentException]\n", errout_str());