Fix issue 8737: FP with identical inner condition due to followVar (#1371)
This commit is contained in:
parent
7fdd039bee
commit
cb03b9883f
|
@ -147,14 +147,26 @@ static bool isInLoopCondition(const Token * tok)
|
||||||
return Token::Match(tok->astTop()->previous(), "for|while (");
|
return Token::Match(tok->astTop()->previous(), "for|while (");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If tok2 comes after tok1
|
||||||
|
static bool precedes(const Token * tok1, const Token * tok2)
|
||||||
|
{
|
||||||
|
if(!tok1)
|
||||||
|
return false;
|
||||||
|
if(!tok2)
|
||||||
|
return false;
|
||||||
|
return tok1->progressValue() < tok2->progressValue();
|
||||||
|
}
|
||||||
|
|
||||||
/// This takes a token that refers to a variable and it will return the token
|
/// This takes a token that refers to a variable and it will return the token
|
||||||
/// to the expression that the variable is assigned to. If its not valid to
|
/// to the expression that the variable is assigned to. If its not valid to
|
||||||
/// make such substitution then it will return the original token.
|
/// make such substitution then it will return the original token.
|
||||||
static const Token * followVariableExpression(const Token * tok, bool cpp)
|
static const Token * followVariableExpression(const Token * tok, bool cpp, const Token * end = nullptr)
|
||||||
{
|
{
|
||||||
if (!tok)
|
if (!tok)
|
||||||
return tok;
|
return tok;
|
||||||
|
// Skip following variables that is across multiple files
|
||||||
|
if(end && end->fileIndex() != tok->fileIndex())
|
||||||
|
return tok;
|
||||||
// Skip array access
|
// Skip array access
|
||||||
if (Token::Match(tok, "%var% ["))
|
if (Token::Match(tok, "%var% ["))
|
||||||
return tok;
|
return tok;
|
||||||
|
@ -182,8 +194,9 @@ static const Token * followVariableExpression(const Token * tok, bool cpp)
|
||||||
return tok;
|
return tok;
|
||||||
if (var->isArgument())
|
if (var->isArgument())
|
||||||
return tok;
|
return tok;
|
||||||
|
const Token * lastTok = precedes(tok, end) ? end : tok;
|
||||||
// If this is in a loop then check if variables are modified in the entire scope
|
// If this is in a loop then check if variables are modified in the entire scope
|
||||||
const Token * endToken = (isInLoopCondition(tok) || isInLoopCondition(varTok) || var->scope() != tok->scope()) ? var->scope()->bodyEnd : tok;
|
const Token * endToken = (isInLoopCondition(tok) || isInLoopCondition(varTok) || var->scope() != tok->scope()) ? var->scope()->bodyEnd : lastTok;
|
||||||
if (!var->isConst() && isVariableChanged(varTok, endToken, tok->varId(), false, nullptr, cpp))
|
if (!var->isConst() && isVariableChanged(varTok, endToken, tok->varId(), false, nullptr, cpp))
|
||||||
return tok;
|
return tok;
|
||||||
// Start at beginning of initialization
|
// Start at beginning of initialization
|
||||||
|
@ -254,12 +267,12 @@ bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2
|
||||||
return isSameExpression(cpp, macro, tok1, tok2->astOperand1()->astOperand1(), library, pure, errors);
|
return isSameExpression(cpp, macro, tok1, tok2->astOperand1()->astOperand1(), library, pure, errors);
|
||||||
}
|
}
|
||||||
if (tok1->str() != tok2->str() && (Token::Match(tok1, "%var%") || Token::Match(tok2, "%var%"))) {
|
if (tok1->str() != tok2->str() && (Token::Match(tok1, "%var%") || Token::Match(tok2, "%var%"))) {
|
||||||
const Token * varTok1 = followVariableExpression(tok1, cpp);
|
const Token * varTok1 = followVariableExpression(tok1, cpp, tok2);
|
||||||
if (varTok1->str() == tok2->str()) {
|
if (varTok1->str() == tok2->str()) {
|
||||||
followVariableExpressionError(tok1, varTok1, errors);
|
followVariableExpressionError(tok1, varTok1, errors);
|
||||||
return isSameExpression(cpp, macro, varTok1, tok2, library, pure, errors);
|
return isSameExpression(cpp, macro, varTok1, tok2, library, pure, errors);
|
||||||
}
|
}
|
||||||
const Token * varTok2 = followVariableExpression(tok2, cpp);
|
const Token * varTok2 = followVariableExpression(tok2, cpp, tok1);
|
||||||
if (tok1->str() == varTok2->str()) {
|
if (tok1->str() == varTok2->str()) {
|
||||||
followVariableExpressionError(tok2, varTok2, errors);
|
followVariableExpressionError(tok2, varTok2, errors);
|
||||||
return isSameExpression(cpp, macro, tok1, varTok2, library, pure, errors);
|
return isSameExpression(cpp, macro, tok1, varTok2, library, pure, errors);
|
||||||
|
|
|
@ -2032,6 +2032,18 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Identical inner 'if' condition is always true.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Identical inner 'if' condition is always true.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" uint32_t value;\n"
|
||||||
|
" get_value(&value);\n"
|
||||||
|
" int opt_function_capable = (value >> 28) & 1;\n"
|
||||||
|
" if (opt_function_capable) {\n"
|
||||||
|
" value = 0;\n"
|
||||||
|
" get_value (&value);\n"
|
||||||
|
" if ((value >> 28) & 1) {}\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void identicalConditionAfterEarlyExit() {
|
void identicalConditionAfterEarlyExit() {
|
||||||
|
|
Loading…
Reference in New Issue