Fix issue 9897: False positive: nullPointerRedundantCheck (#2805)

This commit is contained in:
Paul Fultz II 2020-09-14 02:17:29 -05:00 committed by GitHub
parent bb7164171c
commit 94850fec3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 12 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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"