diff --git a/lib/checkexceptionsafety.cpp b/lib/checkexceptionsafety.cpp index 12aa3f1dac5..9d89cb4171c 100644 --- a/lib/checkexceptionsafety.cpp +++ b/lib/checkexceptionsafety.cpp @@ -71,9 +71,8 @@ void CheckExceptionSafety::destructors() tok = tok->linkAt(1); // end of if ( ... ) tok = tok->linkAt(1); // end of { ... } } - // throw found within a destructor - else if (tok->str() == "throw") { + else if (tok->str() == "throw" && function->isNoExcept()) { destructorsError(tok, scope->className); break; } @@ -296,8 +295,7 @@ void CheckExceptionSafety::nothrowThrows() continue; // check noexcept and noexcept(true) functions - if (function->isNoExcept() && - (!function->noexceptArg || function->noexceptArg->str() == "true")) { + if (function->isNoExcept()) { const Token *throws = functionThrows(function); if (throws) noexceptThrowError(throws); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 9bdff3f622c..1ba1b11161d 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2532,8 +2532,10 @@ Function::Function(const Token *tok, tokenDef->str().size() > scope->className.size() + 1 && tokenDef->str()[scope->className.size() + 1] == '<'))) { // destructor - if (tokenDef->strAt(-1) == "~") + if (tokenDef->strAt(-1) == "~") { type = Function::eDestructor; + isNoExcept(true); + } // constructor of any kind else type = Function::eConstructor; diff --git a/test/testexceptionsafety.cpp b/test/testexceptionsafety.cpp index 03f7c6a6815..0c43cb6c689 100644 --- a/test/testexceptionsafety.cpp +++ b/test/testexceptionsafety.cpp @@ -76,7 +76,8 @@ class TestExceptionSafety : public TestFixture { " throw e;\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:3]: (warning) Class x is not safe, destructor throws exception\n", errout_str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Class x is not safe, destructor throws exception\n" + "[test.cpp:3]: (error) Exception thrown in function declared not to throw exceptions.\n", errout_str()); check("class x {\n" " ~x();\n" @@ -84,7 +85,8 @@ class TestExceptionSafety : public TestFixture { "x::~x() {\n" " throw e;\n" "}"); - ASSERT_EQUALS("[test.cpp:5]: (warning) Class x is not safe, destructor throws exception\n", errout_str()); + ASSERT_EQUALS("[test.cpp:5]: (warning) Class x is not safe, destructor throws exception\n" + "[test.cpp:5]: (error) Exception thrown in function declared not to throw exceptions.\n", errout_str()); // #3858 - throwing exception in try block in destructor. check("class x {\n" @@ -104,6 +106,15 @@ class TestExceptionSafety : public TestFixture { " }\n" " }\n" "}"); + ASSERT_EQUALS("[test.cpp:4]: (error) Exception thrown in function declared not to throw exceptions.\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()); }