From 52b4aeb279bad25f9bf31aa863a97306777e6aaf Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Thu, 7 Apr 2022 10:42:57 +0200 Subject: [PATCH] Fix #10792 FP knownConditionTrueFalse with double to int cast (#3964) --- lib/astutils.cpp | 3 +++ lib/valueflow.cpp | 4 ++-- test/testcondition.cpp | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index b47d67f3f..502cc3c49 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -949,6 +949,9 @@ static const Token * followVariableExpression(const Token * tok, bool cpp, const return tok; if (isStructuredBindingVariable(var)) return tok; + // assigning a floating point value to an integer does not preserve the value + if (var->valueType() && var->valueType()->isIntegral() && varTok->valueType() && varTok->valueType()->isFloat()) + 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 const Token * endToken = (isInLoopCondition(tok) || isInLoopCondition(varTok) || var->scope() != tok->scope()) ? var->scope()->bodyEnd : lastTok; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index fcafd6bb2..27ca49126 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -253,12 +253,12 @@ const Token *parseCompareInt(const Token *tok, ValueFlow::Value &true_value, Val value1.clear(); } if (!value1.empty()) { - if (isSaturated(value1.front())) + if (isSaturated(value1.front()) || astIsFloat(tok->astOperand2(), /*unknown*/ false)) return nullptr; setConditionalValues(tok, true, value1.front(), true_value, false_value); return tok->astOperand2(); } else if (!value2.empty()) { - if (isSaturated(value2.front())) + if (isSaturated(value2.front()) || astIsFloat(tok->astOperand1(), /*unknown*/ false)) return nullptr; setConditionalValues(tok, false, value2.front(), true_value, false_value); return tok->astOperand1(); diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 27e9650f6..744b4da50 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -2491,6 +2491,14 @@ private: " if (!b && f()) {}\n" "}"); ASSERT_EQUALS("", errout.str()); + + check("void f(double d) {\n" + " if (d != 0) {\n" + " int i = d;\n" + " if (i == 0) {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void identicalInnerCondition() { @@ -4018,6 +4026,31 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:5]: (style) Condition 'w' is always true\n", errout.str()); + check("void f(double d) {\n" // #10792 + " if (d != 0) {\n" + " int i = (int)d;\n" + " if (i == 0) {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("void f(double d) {\n" + " if (0 != d) {\n" + " int i = (int)d;\n" + " if (i == 0) {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("struct A { double d; }\n" + "void f(A a) {\n" + " if (a.d != 0) {\n" + " int i = a.d;\n" + " if (i == 0) {}\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + check("void f() {\n" " if(strlen(\"abc\") == 3) {;}\n" " if(strlen(\"abc\") == 1) {;}\n"