Co-authored-by: chrchr-github <chrchr@github>
This commit is contained in:
parent
237bed8a91
commit
d6a1a657df
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];"
|
||||||
|
|
Loading…
Reference in New Issue