parent
25ef9eeb26
commit
c8936d04f6
|
@ -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%|!")) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue