CheckLeakAutoVar: Distinguish between new and new[] (#888)
This commit is contained in:
parent
04b9076af3
commit
54959d1932
|
@ -285,7 +285,9 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
alloctype[varTok->varId()].status = VarInfo::ALLOC;
|
alloctype[varTok->varId()].status = VarInfo::ALLOC;
|
||||||
}
|
}
|
||||||
} else if (_tokenizer->isCPP() && varTok->strAt(2) == "new") {
|
} else if (_tokenizer->isCPP() && varTok->strAt(2) == "new") {
|
||||||
alloctype[varTok->varId()].type = -1;
|
const Token* tok2 = varTok->tokAt(2)->astOperand1();
|
||||||
|
bool arrayNew = (tok2 && (tok2->str() == "[" || (tok2->str() == "(" && tok2->astOperand1() && tok2->astOperand1()->str() == "[")));
|
||||||
|
alloctype[varTok->varId()].type = arrayNew ? -2 : -1;
|
||||||
alloctype[varTok->varId()].status = VarInfo::ALLOC;
|
alloctype[varTok->varId()].status = VarInfo::ALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,14 +471,15 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
|
||||||
|
|
||||||
// delete
|
// delete
|
||||||
else if (_tokenizer->isCPP() && tok->str() == "delete") {
|
else if (_tokenizer->isCPP() && tok->str() == "delete") {
|
||||||
if (tok->strAt(1) == "[")
|
bool arrayDelete = (tok->strAt(1) == "[");
|
||||||
|
if (arrayDelete)
|
||||||
tok = tok->tokAt(3);
|
tok = tok->tokAt(3);
|
||||||
else
|
else
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
while (Token::Match(tok, "%name% ::|."))
|
while (Token::Match(tok, "%name% ::|."))
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
if (tok->varId() && tok->strAt(1) != "[") {
|
if (tok->varId() && tok->strAt(1) != "[") {
|
||||||
VarInfo::AllocInfo allocation(-1, VarInfo::DEALLOC);
|
VarInfo::AllocInfo allocation(arrayDelete ? -2 : -1, VarInfo::DEALLOC);
|
||||||
changeAllocStatus(varInfo, allocation, tok, tok);
|
changeAllocStatus(varInfo, allocation, tok, tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ private:
|
||||||
TEST_CASE(loop1);
|
TEST_CASE(loop1);
|
||||||
|
|
||||||
// mismatching allocation/deallocation
|
// mismatching allocation/deallocation
|
||||||
TEST_CASE(mismatch_fopen_free);
|
TEST_CASE(mismatchAllocDealloc);
|
||||||
|
|
||||||
// Execution reaches a 'return'
|
// Execution reaches a 'return'
|
||||||
TEST_CASE(return1);
|
TEST_CASE(return1);
|
||||||
|
@ -994,12 +994,28 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void mismatch_fopen_free() {
|
void mismatchAllocDealloc() {
|
||||||
check("void f() {\n"
|
check("void f() {\n"
|
||||||
" FILE*f=fopen(fname,a);\n"
|
" FILE*f=fopen(fname,a);\n"
|
||||||
" free(f);\n"
|
" free(f);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.c:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
ASSERT_EQUALS("[test.c:3]: (error) Mismatching allocation and deallocation: f\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char *cPtr = new char[100];\n"
|
||||||
|
" delete[] cPtr;\n"
|
||||||
|
" cPtr = new char[100]('x');\n"
|
||||||
|
" delete[] cPtr;\n"
|
||||||
|
" cPtr = new char[100];\n"
|
||||||
|
" delete cPtr;\n"
|
||||||
|
"}", true);
|
||||||
|
ASSERT_EQUALS("[test.cpp:7]: (error) Mismatching allocation and deallocation: cPtr\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char *cPtr = new char[100];\n"
|
||||||
|
" free(cPtr);\n"
|
||||||
|
"}", true);
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Mismatching allocation and deallocation: cPtr\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void return1() {
|
void return1() {
|
||||||
|
|
Loading…
Reference in New Issue