parent
25ef9eeb26
commit
c8936d04f6
|
@ -1000,7 +1000,8 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope)
|
||||||
void CheckMemoryLeakNoVar::checkForUnusedReturnValue(const Scope *scope)
|
void CheckMemoryLeakNoVar::checkForUnusedReturnValue(const Scope *scope)
|
||||||
{
|
{
|
||||||
for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
|
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;
|
continue;
|
||||||
|
|
||||||
if (tok->varId())
|
if (tok->varId())
|
||||||
|
@ -1010,21 +1011,27 @@ void CheckMemoryLeakNoVar::checkForUnusedReturnValue(const Scope *scope)
|
||||||
if (allocType == No)
|
if (allocType == No)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tok != tok->next()->astOperand1())
|
if (tok != tok->next()->astOperand1() && !isNew)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (isReopenStandardStream(tok))
|
if (isReopenStandardStream(tok))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// get ast parent, skip casts
|
// 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())
|
while (parent && parent->str() == "(" && !parent->astOperand2())
|
||||||
parent = parent->astParent();
|
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
|
// Check if we are in a C++11 constructor
|
||||||
const Token * closingBrace = Token::findmatch(tok, "}|;");
|
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;
|
continue;
|
||||||
returnValueNotUsedError(tok, tok->str());
|
returnValueNotUsedError(tok, tok->str());
|
||||||
} else if (Token::Match(parent, "%comp%|!")) {
|
} else if (Token::Match(parent, "%comp%|!")) {
|
||||||
|
|
|
@ -7997,7 +7997,7 @@ void Tokenizer::simplifyInitVar()
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
if (!tok2->link() || (tok2->link()->strAt(1) == ";" && !Token::simpleMatch(tok2->linkAt(2), ") (")))
|
if (!tok2->link() || (tok2->link()->strAt(1) == ";" && !Token::simpleMatch(tok2->linkAt(2), ") (")))
|
||||||
tok = initVar(tok);
|
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);
|
Token *tok1 = tok->tokAt(5);
|
||||||
while (tok1->str() != ",")
|
while (tok1->str() != ",")
|
||||||
tok1 = tok1->next();
|
tok1 = tok1->next();
|
||||||
|
|
|
@ -2442,6 +2442,77 @@ private:
|
||||||
" unary_right_comma (a);\n"
|
" unary_right_comma (a);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void smartPointerFunctionParam() {
|
||||||
|
|
Loading…
Reference in New Issue