From 078a6d780441794cd484d5c561edba66ccbdf87c Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sun, 7 Aug 2022 19:06:19 +0200 Subject: [PATCH] Fix #11238 FP knownConditionTrueFalse with constexpr? (#4341) --- lib/astutils.cpp | 20 +++++++++++--------- lib/astutils.h | 2 +- lib/checkcondition.cpp | 4 +++- test/testcondition.cpp | 8 ++++++++ 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 00658a6d8..e947dc4bc 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -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 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 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; } diff --git a/lib/astutils.h b/lib/astutils.h index c30242f3b..9fbf706a8 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -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 skipPredicate = nullptr); const Variable *getLHSVariable(const Token *tok); diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 44d8b2cbd..1c88ba038 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -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) diff --git a/test/testcondition.cpp b/test/testcondition.cpp index cb508786d..42a57e186 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -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()