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

View File

@ -383,7 +383,7 @@ bool isLikelyStreamRead(bool cpp, const Token *op);
bool isCPPCast(const Token* tok); 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); const Variable *getLHSVariable(const Token *tok);

View File

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

View File

@ -4281,6 +4281,14 @@ private:
" }\n" " }\n"
"};\n"); "};\n");
ASSERT_EQUALS("", errout.str()); 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() void alwaysTrueSymbolic()