diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index e8271f9eed0..e5220e701a3 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -342,6 +342,8 @@ bool CheckLeakAutoVarImpl::checkScope(const Token * const startToken, } } + if (tok == tok->scope()->bodyEnd && tok->scope()->type == ScopeType::eUnconditional) + ret(tok, varInfo, /*isEndOfScope*/ true); // look for end of statement const bool isInit = Token::Match(tok->tokAt(-1), "%var% {|(") && tok->tokAt(-1)->variable() && tok->tokAt(-1) == tok->tokAt(-1)->variable()->nameToken(); diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index b7f8b024a8c..6b6397851fb 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -211,6 +211,7 @@ class TestLeakAutoVar : public TestFixture { TEST_CASE(inlineFunction); // #3989 TEST_CASE(smartPtrInContainer); // #8262 + TEST_CASE(unconditionalScope); TEST_CASE(functionCallCastConfig); // #9652 TEST_CASE(functionCallLeakIgnoreConfig); // #7923 @@ -3178,6 +3179,34 @@ class TestLeakAutoVar : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void unconditionalScope() { + check("void f() {\n" // #14945 + " {\n" + " int* p = new int;\n" + " *p = 1;\n" + " }\n" + " {\n" + " int* q = new int;\n" + " *q = 2;\n" + " delete q;\n" + " }\n" + " int* r = new int;\n" + " *r = 3;\n" + " delete r;\n" + "}\n", dinit(CheckOptions, $.cpp = true)); + ASSERT_EQUALS("[test.cpp:5:5]: (error) Memory leak: p [memleak]\n", errout_str()); + + check("void f() {\n" + " int* p = new int;\n" + " {\n" + " (void)p;\n" + " }\n" + " *p = 1;\n" + " delete p;\n" + "}\n", dinit(CheckOptions, $.cpp = true)); + ASSERT_EQUALS("", errout_str()); + } + void functionCallCastConfig() { // #9652 constexpr char xmldata[] = "\n" "\n"