diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index d99a28d03..61079e36b 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -328,7 +328,8 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, // check each token { - const Token * nextTok = checkTokenInsideExpression(tok, varInfo); + const bool isInit = Token::Match(tok, "%var% {|(") && tok->variable() && tok == tok->variable()->nameToken(); + const Token * nextTok = isInit ? nullptr : checkTokenInsideExpression(tok, varInfo); if (nextTok) { tok = nextTok; continue; @@ -337,26 +338,28 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, // look for end of statement - if (!Token::Match(tok, "[;{},]") || Token::Match(tok->next(), "[;{},]")) + const bool isInit = Token::Match(tok->tokAt(-1), "%var% {|(") && tok->tokAt(-1)->variable() && tok->tokAt(-1) == tok->tokAt(-1)->variable()->nameToken(); + if ((!Token::Match(tok, "[;{},]") || Token::Match(tok->next(), "[;{},]")) && !(isInit && tok->str() == "(")) continue; if (Token::Match(tok, "[;{},] %var% [")) continue; - tok = tok->next(); + if (!isInit) + tok = tok->next(); if (!tok || tok == endToken) break; if (Token::Match(tok, "const %type%")) tok = tok->tokAt(2); - while (tok->str() == "(") + while (!isInit && tok->str() == "(") tok = tok->next(); while (tok->isUnaryOp("*") && tok->astOperand1()->isUnaryOp("&")) tok = tok->astOperand1()->astOperand1(); // parse statement, skip to last member - const Token *varTok = tok; + const Token* varTok = isInit ? tok->tokAt(-1) : tok; while (Token::Match(varTok, "%name% ::|. %name% !!(")) varTok = varTok->tokAt(2); @@ -381,7 +384,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, }; // assignment.. - if (const Token* const tokAssignOp = isAssignment(varTok)) { + if (const Token* const tokAssignOp = isInit ? varTok : isAssignment(varTok)) { if (Token::simpleMatch(tokAssignOp->astOperand1(), ".")) continue; diff --git a/test/testclass.cpp b/test/testclass.cpp index 04a3f2f70..df4a5b531 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -6621,6 +6621,17 @@ private: ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'S::f' can be const.\n" "[test.cpp:8]: (performance, inconclusive) Technically the member function 'S::g' can be static (but you may consider moving to unnamed namespace).\n", errout.str()); + + checkConst("class C {\n" // #11653 + "public:\n" + " void f(bool b) const;\n" + "};\n" + "void C::f(bool b) const {\n" + " if (b)\n" + " f(false);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'C::f' can be static (but you may consider moving to unnamed namespace).\n", + errout.str()); } void const90() { // #11637 diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 700292c9c..09891cf66 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -88,6 +88,7 @@ private: TEST_CASE(assign22); // #9139 TEST_CASE(assign23); TEST_CASE(assign24); // #7440 + TEST_CASE(assign25); TEST_CASE(isAutoDealloc); @@ -571,6 +572,16 @@ private: ASSERT_EQUALS("[test.c:5]: (error) Memory leak: p\n", errout.str()); } + void assign25() { + check("void f() {\n" // #11796 + " int* p{ new int };\n" + " int* q(new int);\n" + "}", true); + ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: p\n" + "[test.cpp:4]: (error) Memory leak: q\n", + errout.str()); + } + void isAutoDealloc() { check("void f() {\n" " char *p = new char[100];"