Fix issue 9897: False positive: nullPointerRedundantCheck (#2805)
This commit is contained in:
parent
bb7164171c
commit
94850fec3f
|
@ -632,6 +632,8 @@ static const Token * followVariableExpression(const Token * tok, bool cpp, const
|
|||
return tok;
|
||||
if (precedes(varTok, endToken) && isAliased(varTok, endToken, tok->varId()))
|
||||
return tok;
|
||||
if (varTok->exprId() != 0 && isVariableChanged(nextAfterAstRightmostLeaf(varTok), endToken, varTok->exprId(), false, nullptr, cpp))
|
||||
return tok;
|
||||
// Start at beginning of initialization
|
||||
const Token * startToken = varTok;
|
||||
while (Token::Match(startToken, "%op%|.|(|{") && startToken->astOperand1())
|
||||
|
@ -1590,24 +1592,24 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool isVariableChanged(const Token *start, const Token *end, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth)
|
||||
bool isVariableChanged(const Token *start, const Token *end, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth)
|
||||
{
|
||||
return findVariableChanged(start, end, 0, varid, globalvar, settings, cpp, depth) != nullptr;
|
||||
return findVariableChanged(start, end, 0, exprid, globalvar, settings, cpp, depth) != nullptr;
|
||||
}
|
||||
|
||||
bool isVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth)
|
||||
bool isVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth)
|
||||
{
|
||||
return findVariableChanged(start, end, indirect, varid, globalvar, settings, cpp, depth) != nullptr;
|
||||
return findVariableChanged(start, end, indirect, exprid, globalvar, settings, cpp, depth) != nullptr;
|
||||
}
|
||||
|
||||
Token* findVariableChanged(Token *start, const Token *end, int indirect, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth)
|
||||
Token* findVariableChanged(Token *start, const Token *end, int indirect, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth)
|
||||
{
|
||||
if (!precedes(start, end))
|
||||
return nullptr;
|
||||
if (depth < 0)
|
||||
return start;
|
||||
for (Token *tok = start; tok != end; tok = tok->next()) {
|
||||
if (tok->varId() != varid) {
|
||||
if (tok->exprId() != exprid) {
|
||||
if (globalvar && Token::Match(tok, "%name% ("))
|
||||
// TODO: Is global variable really changed by function call?
|
||||
return tok;
|
||||
|
@ -1619,9 +1621,9 @@ Token* findVariableChanged(Token *start, const Token *end, int indirect, const n
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const Token* findVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth)
|
||||
const Token* findVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth)
|
||||
{
|
||||
return findVariableChanged(const_cast<Token*>(start), end, indirect, varid, globalvar, settings, cpp, depth);
|
||||
return findVariableChanged(const_cast<Token*>(start), end, indirect, exprid, globalvar, settings, cpp, depth);
|
||||
}
|
||||
|
||||
bool isVariableChanged(const Variable * var, const Settings *settings, bool cpp, int depth)
|
||||
|
|
|
@ -182,8 +182,8 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, nonneg int
|
|||
bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Settings *settings, bool *inconclusive);
|
||||
|
||||
/** Is variable changed in block of code? */
|
||||
bool isVariableChanged(const Token *start, const Token *end, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
|
||||
bool isVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
|
||||
bool isVariableChanged(const Token *start, const Token *end, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
|
||||
bool isVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
|
||||
|
||||
bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, bool cpp, int depth = 20);
|
||||
|
||||
|
@ -198,8 +198,8 @@ bool isVariablesChanged(const Token* start,
|
|||
|
||||
bool isThisChanged(const Token* start, const Token* end, int indirect, const Settings* settings, bool cpp);
|
||||
|
||||
const Token* findVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
|
||||
Token* findVariableChanged(Token *start, const Token *end, int indirect, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
|
||||
const Token* findVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
|
||||
Token* findVariableChanged(Token *start, const Token *end, int indirect, const nonneg int exprid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
|
||||
|
||||
/// If token is an alias if another variable
|
||||
bool isAliasOf(const Token *tok, nonneg int varid);
|
||||
|
|
|
@ -99,6 +99,7 @@ private:
|
|||
TEST_CASE(nullpointer56); // #9701
|
||||
TEST_CASE(nullpointer57); // #9751
|
||||
TEST_CASE(nullpointer58); // #9807
|
||||
TEST_CASE(nullpointer59); // #9897
|
||||
TEST_CASE(nullpointer_addressOf); // address of
|
||||
TEST_CASE(nullpointerSwitch); // #2626
|
||||
TEST_CASE(nullpointer_cast); // #4692
|
||||
|
@ -1862,6 +1863,21 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void nullpointer59() {
|
||||
check("struct Box {\n"
|
||||
" struct Box* prev;\n"
|
||||
" struct Box* next;\n"
|
||||
"};\n"
|
||||
"void foo(Box** pfreeboxes) {\n"
|
||||
" Box *b = *pfreeboxes;\n"
|
||||
" *pfreeboxes = b->next;\n"
|
||||
" if( *pfreeboxes )\n"
|
||||
" (*pfreeboxes)->prev = nullptr;\n"
|
||||
" b->next = nullptr;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void nullpointer_addressOf() { // address of
|
||||
check("void f() {\n"
|
||||
" struct X *x = 0;\n"
|
||||
|
|
Loading…
Reference in New Issue