Fix false positives in knownConditionTrueFalse when using expressions with const variables (#2469)
This commit is contained in:
parent
41caf28c6f
commit
dd05839a7e
|
@ -1411,27 +1411,31 @@ bool isCPPCast(const Token* tok)
|
|||
return tok && Token::simpleMatch(tok->previous(), "> (") && tok->astOperand2() && tok->astOperand1() && tok->astOperand1()->str().find("_cast") != std::string::npos;
|
||||
}
|
||||
|
||||
bool isConstVarExpression(const Token *tok)
|
||||
bool isConstVarExpression(const Token *tok, const char* skipMatch)
|
||||
{
|
||||
if (!tok)
|
||||
return false;
|
||||
if (skipMatch && Token::Match(tok, skipMatch))
|
||||
return false;
|
||||
if (Token::simpleMatch(tok->previous(), "sizeof ("))
|
||||
return true;
|
||||
if (Token::Match(tok->previous(), "%name% (")) {
|
||||
if (Token::simpleMatch(tok->astOperand1(), ".") && !isConstVarExpression(tok->astOperand1(), skipMatch))
|
||||
return false;
|
||||
std::vector<const Token *> args = getArguments(tok);
|
||||
return std::all_of(args.begin(), args.end(), &isConstVarExpression);
|
||||
return std::all_of(args.begin(), args.end(), [&](const Token* t) { return isConstVarExpression(t, skipMatch); });
|
||||
}
|
||||
if (isCPPCast(tok)) {
|
||||
return isConstVarExpression(tok->astOperand2());
|
||||
return isConstVarExpression(tok->astOperand2(), skipMatch);
|
||||
}
|
||||
if (Token::Match(tok, "( %type%"))
|
||||
return isConstVarExpression(tok->astOperand1());
|
||||
return isConstVarExpression(tok->astOperand1(), skipMatch);
|
||||
if (tok->str() == "::" && tok->hasKnownValue())
|
||||
return isConstVarExpression(tok->astOperand2());
|
||||
return isConstVarExpression(tok->astOperand2(), skipMatch);
|
||||
if (Token::Match(tok, "%cop%|[|.")) {
|
||||
if (tok->astOperand1() && !isConstVarExpression(tok->astOperand1()))
|
||||
if (tok->astOperand1() && !isConstVarExpression(tok->astOperand1(), skipMatch))
|
||||
return false;
|
||||
if (tok->astOperand2() && !isConstVarExpression(tok->astOperand2()))
|
||||
if (tok->astOperand2() && !isConstVarExpression(tok->astOperand2(), skipMatch))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -1440,7 +1444,7 @@ bool isConstVarExpression(const Token *tok)
|
|||
if (tok->isEnumerator())
|
||||
return true;
|
||||
if (tok->variable())
|
||||
return tok->variable()->isConst();
|
||||
return tok->variable()->isConst() && tok->variable()->nameToken() && tok->variable()->nameToken()->hasKnownValue();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ bool isLikelyStreamRead(bool cpp, const Token *op);
|
|||
|
||||
bool isCPPCast(const Token* tok);
|
||||
|
||||
bool isConstVarExpression(const Token *tok);
|
||||
bool isConstVarExpression(const Token *tok, const char * skipMatch = nullptr);
|
||||
|
||||
const Variable *getLHSVariable(const Token *tok);
|
||||
|
||||
|
|
|
@ -1378,6 +1378,8 @@ void CheckCondition::alwaysTrueFalse()
|
|||
continue;
|
||||
if (Token::Match(tok, "%comp%") && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true))
|
||||
continue;
|
||||
if (isConstVarExpression(tok, "[|(|&|+|-|*|/|%|^|>>|<<"))
|
||||
continue;
|
||||
|
||||
const bool constIfWhileExpression =
|
||||
tok->astParent() && Token::Match(tok->astTop()->astOperand1(), "if|while") && !tok->astTop()->astOperand1()->isConstexpr() &&
|
||||
|
|
|
@ -3000,6 +3000,9 @@ static bool isVariableExpression(const Token* tok)
|
|||
if (Token::simpleMatch(tok, "."))
|
||||
return isVariableExpression(tok->astOperand1()) &&
|
||||
isVariableExpression(tok->astOperand2());
|
||||
if (Token::simpleMatch(tok, "["))
|
||||
return isVariableExpression(tok->astOperand1()) &&
|
||||
tok->astOperand2() && tok->astOperand2()->hasKnownIntValue();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -3329,6 +3329,24 @@ private:
|
|||
" return;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("int f(int a, int b) {\n"
|
||||
" static const int x = 10;\n"
|
||||
" return x == 1 ? a : b;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("const bool x = false;\n"
|
||||
"void f() {\n"
|
||||
" if (x) {}\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("const bool x = false;\n"
|
||||
"void f() {\n"
|
||||
" if (!x) {}\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void alwaysTrueInfer() {
|
||||
|
|
Loading…
Reference in New Issue