Fix #11796 FN memleak with brace init (#5708)

Co-authored-by: chrchr-github <chrchr@github>
This commit is contained in:
chrchr-github 2023-12-01 15:39:16 +01:00 committed by GitHub
parent 237bed8a91
commit d6a1a657df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 6 deletions

View File

@ -328,7 +328,8 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
// check each token // 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) { if (nextTok) {
tok = nextTok; tok = nextTok;
continue; continue;
@ -337,26 +338,28 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
// look for end of statement // 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; continue;
if (Token::Match(tok, "[;{},] %var% [")) if (Token::Match(tok, "[;{},] %var% ["))
continue; continue;
tok = tok->next(); if (!isInit)
tok = tok->next();
if (!tok || tok == endToken) if (!tok || tok == endToken)
break; break;
if (Token::Match(tok, "const %type%")) if (Token::Match(tok, "const %type%"))
tok = tok->tokAt(2); tok = tok->tokAt(2);
while (tok->str() == "(") while (!isInit && tok->str() == "(")
tok = tok->next(); tok = tok->next();
while (tok->isUnaryOp("*") && tok->astOperand1()->isUnaryOp("&")) while (tok->isUnaryOp("*") && tok->astOperand1()->isUnaryOp("&"))
tok = tok->astOperand1()->astOperand1(); tok = tok->astOperand1()->astOperand1();
// parse statement, skip to last member // parse statement, skip to last member
const Token *varTok = tok; const Token* varTok = isInit ? tok->tokAt(-1) : tok;
while (Token::Match(varTok, "%name% ::|. %name% !!(")) while (Token::Match(varTok, "%name% ::|. %name% !!("))
varTok = varTok->tokAt(2); varTok = varTok->tokAt(2);
@ -381,7 +384,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
}; };
// assignment.. // assignment..
if (const Token* const tokAssignOp = isAssignment(varTok)) { if (const Token* const tokAssignOp = isInit ? varTok : isAssignment(varTok)) {
if (Token::simpleMatch(tokAssignOp->astOperand1(), ".")) if (Token::simpleMatch(tokAssignOp->astOperand1(), "."))
continue; continue;

View File

@ -6621,6 +6621,17 @@ private:
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'S::f' can be const.\n" 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", "[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()); 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 void const90() { // #11637

View File

@ -88,6 +88,7 @@ private:
TEST_CASE(assign22); // #9139 TEST_CASE(assign22); // #9139
TEST_CASE(assign23); TEST_CASE(assign23);
TEST_CASE(assign24); // #7440 TEST_CASE(assign24); // #7440
TEST_CASE(assign25);
TEST_CASE(isAutoDealloc); TEST_CASE(isAutoDealloc);
@ -571,6 +572,16 @@ private:
ASSERT_EQUALS("[test.c:5]: (error) Memory leak: p\n", errout.str()); 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() { void isAutoDealloc() {
check("void f() {\n" check("void f() {\n"
" char *p = new char[100];" " char *p = new char[100];"