Fix #11238 FP knownConditionTrueFalse with constexpr? (#4341)

This commit is contained in:
chrchr-github 2022-08-07 19:06:19 +02:00 committed by GitHub
parent fc6b79a5e6
commit 078a6d7804
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 23 additions and 11 deletions

View File

@ -2768,35 +2768,37 @@ bool isCPPCast(const Token* tok)
return tok && Token::simpleMatch(tok->previous(), "> (") && tok->astOperand2() && tok->astOperand1() && isCPPCastKeyword(tok->astOperand1());
}
bool isConstVarExpression(const Token *tok, const char* skipMatch)
bool isConstVarExpression(const Token *tok, std::function<bool(const Token*)> skipPredicate)
{
if (!tok)
return false;
if (tok->str() == "?" && tok->astOperand2() && tok->astOperand2()->str() == ":") // ternary operator
return isConstVarExpression(tok->astOperand2()->astOperand1()) && isConstVarExpression(tok->astOperand2()->astOperand2()); // left and right of ":"
if (skipMatch && Token::Match(tok, skipMatch))
if (skipPredicate && skipPredicate(tok))
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))
if (Token::simpleMatch(tok->astOperand1(), ".") && !isConstVarExpression(tok->astOperand1(), skipPredicate))
return false;
std::vector<const Token *> args = getArguments(tok);
if (args.empty() && tok->previous()->function() && tok->previous()->function()->isConstexpr())
return true;
return std::all_of(args.begin(), args.end(), [&](const Token* t) {
return isConstVarExpression(t, skipMatch);
return isConstVarExpression(t, skipPredicate);
});
}
if (isCPPCast(tok)) {
return isConstVarExpression(tok->astOperand2(), skipMatch);
return isConstVarExpression(tok->astOperand2(), skipPredicate);
}
if (Token::Match(tok, "( %type%"))
return isConstVarExpression(tok->astOperand1(), skipMatch);
return isConstVarExpression(tok->astOperand1(), skipPredicate);
if (tok->str() == "::" && tok->hasKnownValue())
return isConstVarExpression(tok->astOperand2(), skipMatch);
return isConstVarExpression(tok->astOperand2(), skipPredicate);
if (Token::Match(tok, "%cop%|[|.")) {
if (tok->astOperand1() && !isConstVarExpression(tok->astOperand1(), skipMatch))
if (tok->astOperand1() && !isConstVarExpression(tok->astOperand1(), skipPredicate))
return false;
if (tok->astOperand2() && !isConstVarExpression(tok->astOperand2(), skipMatch))
if (tok->astOperand2() && !isConstVarExpression(tok->astOperand2(), skipPredicate))
return false;
return true;
}

View File

@ -383,7 +383,7 @@ bool isLikelyStreamRead(bool cpp, const Token *op);
bool isCPPCast(const Token* tok);
bool isConstVarExpression(const Token *tok, const char * skipMatch = nullptr);
bool isConstVarExpression(const Token* tok, std::function<bool(const Token*)> skipPredicate = nullptr);
const Variable *getLHSVariable(const Token *tok);

View File

@ -1497,7 +1497,9 @@ void CheckCondition::alwaysTrueFalse()
continue;
if (tok->isComparisonOp() && isSameExpression(mTokenizer->isCPP(), true, tok->astOperand1(), tok->astOperand2(), mSettings->library, true, true))
continue;
if (isConstVarExpression(tok, "[|(|&|+|-|*|/|%|^|>>|<<"))
if (isConstVarExpression(tok, [](const Token* tok) {
return Token::Match(tok, "[|(|&|+|-|*|/|%|^|>>|<<") && !Token::simpleMatch(tok, "( )");
}))
continue;
// there are specific warnings about nonzero expressions (pointer/unsigned)

View File

@ -4281,6 +4281,14 @@ private:
" }\n"
"};\n");
ASSERT_EQUALS("", errout.str());
check("constexpr int f() {\n" // #11238
" return 1;\n"
"}\n"
"constexpr bool g() {\n"
" return f() == 1;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void alwaysTrueSymbolic()