Skip to content

Commit d6a1a65

Browse files
chrchr-githubchrchr-github
andauthored
Fix #11796 FN memleak with brace init (#5708)
Co-authored-by: chrchr-github <chrchr@github>
1 parent 237bed8 commit d6a1a65

3 files changed

Lines changed: 31 additions & 6 deletions

File tree

lib/checkleakautovar.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,8 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
328328

329329
// check each token
330330
{
331-
const Token * nextTok = checkTokenInsideExpression(tok, varInfo);
331+
const bool isInit = Token::Match(tok, "%var% {|(") && tok->variable() && tok == tok->variable()->nameToken();
332+
const Token * nextTok = isInit ? nullptr : checkTokenInsideExpression(tok, varInfo);
332333
if (nextTok) {
333334
tok = nextTok;
334335
continue;
@@ -337,26 +338,28 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
337338

338339

339340
// look for end of statement
340-
if (!Token::Match(tok, "[;{},]") || Token::Match(tok->next(), "[;{},]"))
341+
const bool isInit = Token::Match(tok->tokAt(-1), "%var% {|(") && tok->tokAt(-1)->variable() && tok->tokAt(-1) == tok->tokAt(-1)->variable()->nameToken();
342+
if ((!Token::Match(tok, "[;{},]") || Token::Match(tok->next(), "[;{},]")) && !(isInit && tok->str() == "("))
341343
continue;
342344

343345
if (Token::Match(tok, "[;{},] %var% ["))
344346
continue;
345347

346-
tok = tok->next();
348+
if (!isInit)
349+
tok = tok->next();
347350
if (!tok || tok == endToken)
348351
break;
349352

350353
if (Token::Match(tok, "const %type%"))
351354
tok = tok->tokAt(2);
352355

353-
while (tok->str() == "(")
356+
while (!isInit && tok->str() == "(")
354357
tok = tok->next();
355358
while (tok->isUnaryOp("*") && tok->astOperand1()->isUnaryOp("&"))
356359
tok = tok->astOperand1()->astOperand1();
357360

358361
// parse statement, skip to last member
359-
const Token *varTok = tok;
362+
const Token* varTok = isInit ? tok->tokAt(-1) : tok;
360363
while (Token::Match(varTok, "%name% ::|. %name% !!("))
361364
varTok = varTok->tokAt(2);
362365

@@ -381,7 +384,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
381384
};
382385

383386
// assignment..
384-
if (const Token* const tokAssignOp = isAssignment(varTok)) {
387+
if (const Token* const tokAssignOp = isInit ? varTok : isAssignment(varTok)) {
385388

386389
if (Token::simpleMatch(tokAssignOp->astOperand1(), "."))
387390
continue;

test/testclass.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6621,6 +6621,17 @@ class TestClass : public TestFixture {
66216621
ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'S::f' can be const.\n"
66226622
"[test.cpp:8]: (performance, inconclusive) Technically the member function 'S::g' can be static (but you may consider moving to unnamed namespace).\n",
66236623
errout.str());
6624+
6625+
checkConst("class C {\n" // #11653
6626+
"public:\n"
6627+
" void f(bool b) const;\n"
6628+
"};\n"
6629+
"void C::f(bool b) const {\n"
6630+
" if (b)\n"
6631+
" f(false);\n"
6632+
"}\n");
6633+
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",
6634+
errout.str());
66246635
}
66256636

66266637
void const90() { // #11637

test/testleakautovar.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class TestLeakAutoVar : public TestFixture {
8888
TEST_CASE(assign22); // #9139
8989
TEST_CASE(assign23);
9090
TEST_CASE(assign24); // #7440
91+
TEST_CASE(assign25);
9192

9293
TEST_CASE(isAutoDealloc);
9394

@@ -571,6 +572,16 @@ class TestLeakAutoVar : public TestFixture {
571572
ASSERT_EQUALS("[test.c:5]: (error) Memory leak: p\n", errout.str());
572573
}
573574

575+
void assign25() {
576+
check("void f() {\n" // #11796
577+
" int* p{ new int };\n"
578+
" int* q(new int);\n"
579+
"}", true);
580+
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: p\n"
581+
"[test.cpp:4]: (error) Memory leak: q\n",
582+
errout.str());
583+
}
584+
574585
void isAutoDealloc() {
575586
check("void f() {\n"
576587
" char *p = new char[100];"

0 commit comments

Comments
 (0)