Fix #3886 New Check : Return value of "new" ignored (#3884)

This commit is contained in:
chrchr-github 2022-04-09 19:06:32 +02:00 committed by GitHub
parent 25ef9eeb26
commit c8936d04f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 6 deletions

View File

@ -1000,7 +1000,8 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope)
void CheckMemoryLeakNoVar::checkForUnusedReturnValue(const Scope *scope)
{
for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
if (!Token::Match(tok, "%name% ("))
const bool isNew = mTokenizer->isCPP() && tok->str() == "new";
if (!isNew && !Token::Match(tok, "%name% ("))
continue;
if (tok->varId())
@ -1010,21 +1011,27 @@ void CheckMemoryLeakNoVar::checkForUnusedReturnValue(const Scope *scope)
if (allocType == No)
continue;
if (tok != tok->next()->astOperand1())
if (tok != tok->next()->astOperand1() && !isNew)
continue;
if (isReopenStandardStream(tok))
continue;
// get ast parent, skip casts
const Token *parent = tok->next()->astParent();
const Token *parent = isNew ? tok->astParent() : tok->next()->astParent();
while (parent && parent->str() == "(" && !parent->astOperand2())
parent = parent->astParent();
if (!parent) {
bool warn = true;
if (isNew) {
const Token* typeTok = tok->next();
warn = typeTok && (typeTok->isStandardType() || mSettings->library.detectContainer(typeTok));
}
if (!parent && warn) {
// Check if we are in a C++11 constructor
const Token * closingBrace = Token::findmatch(tok, "}|;");
if (closingBrace->str() == "}" && Token::Match(closingBrace->link()->tokAt(-1), "%name%"))
if (closingBrace->str() == "}" && Token::Match(closingBrace->link()->tokAt(-1), "%name%") && (!isNew && precedes(tok, closingBrace->link())))
continue;
returnValueNotUsedError(tok, tok->str());
} else if (Token::Match(parent, "%comp%|!")) {

View File

@ -7997,7 +7997,7 @@ void Tokenizer::simplifyInitVar()
tok2 = tok2->next();
if (!tok2->link() || (tok2->link()->strAt(1) == ";" && !Token::simpleMatch(tok2->linkAt(2), ") (")))
tok = initVar(tok);
} else if (Token::Match(tok, "class|struct|union| %type% *| %name% ( &| %any% ) ,")) {
} else if (Token::Match(tok, "class|struct|union| %type% *| %name% ( &| %any% ) ,") && tok->str() != "new") {
Token *tok1 = tok->tokAt(5);
while (tok1->str() != ",")
tok1 = tok1->next();

View File

@ -2442,6 +2442,77 @@ private:
" unary_right_comma (a);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f() {\n"
" new int[10];\n"
" new int[10][5];\n"
" new int[10]();\n"
" new int[10]{};\n"
" new int[] { 1, 2, 3 };\n"
" new std::string;\n"
" new int;\n"
" new int();\n"
" new int(1);\n"
" new int{};\n"
" new int{ 1 };\n"
" new uint8_t[4];\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:3]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:4]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:5]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:6]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:7]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:8]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:9]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:10]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:11]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:12]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:13]: (error) Return value of allocation function 'new' is not stored.\n",
errout.str());
check("void f(int* p) {\n"
" new auto('c');\n"
" new(p) int;\n"
"}");
TODO_ASSERT_EQUALS("[test.cpp:2]: (error) Return value of allocation function 'new' is not stored.\n"
"[test.cpp:3]: (error) Return value of allocation function 'new' is not stored.\n",
"",
errout.str());
check("void g(int* p) {\n"
" new QWidget;\n"
" new QWidget();\n"
" new QWidget{ this };\n"
" h(new int[10], 1);\n"
" h(new int[10][5], 1);\n"
" h(new int[10](), 1);\n"
" h(new int[10]{}, 1);\n"
" h(new int[] { 1, 2, 3 }, 1);\n"
" h(new auto('c'), 1);\n"
" h(new std::string, 1);\n"
" h(new int, 1);\n"
" h(new int{}, 1);\n"
" h(new int(), 1);\n"
" h(new int{ 1 }, 1);\n"
" h(new int(1), 1);\n"
" h(new(p) int, 1);\n"
" h(new QWidget, 1);\n"
" C{ new int[10], 1 };\n"
" C{ new int[10](), 1 };\n"
" C{ new int[10]{}, 1 };\n"
" C{ new int[] { 1, 2, 3 }, 1 };\n"
" C{ new auto('c'), 1 };\n"
" C{ new std::string, 1 };\n"
" C{ new int, 1 };\n"
" C{ new int{}, 1 };\n"
" C{ new int(), 1 };\n"
" C{ new int{ 1 }, 1 };\n"
" C{ new int(1), 1 };\n"
" C{ new(p) int, 1 };\n"
" C{ new QWidget, 1 };\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void smartPointerFunctionParam() {