From 529e6ace14bdfd35a35c5b70666d814adb458d42 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Mon, 26 Oct 2026 19:30:02 +0100 Subject: [PATCH 1/3] Fix #15144 FN knownConditionTrueFalse (binary or) --- lib/checkcondition.cpp | 4 +++- lib/valueflow.cpp | 13 +++++++++++-- test/testcondition.cpp | 7 +++++++ test/testvalueflow.cpp | 11 +++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index 48b2a1ae4bf..e0943a46239 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -327,8 +327,10 @@ void CheckConditionImpl::checkBadBitmaskCheck() const bool isTrue = (tok->astOperand1()->hasKnownIntValue() && tok->astOperand1()->getKnownIntValue() != 0) || (tok->astOperand2()->hasKnownIntValue() && tok->astOperand2()->getKnownIntValue() != 0); - if (isBoolean && isTrue) + if (isBoolean && isTrue) { badBitmaskCheckError(tok); + diag(tok); + } // If there are #ifdef in the expression don't warn about redundant | to avoid FP const auto& startStop = tok->findExpressionStartEndTokens(); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index c021d1d296b..bce706e73c8 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1096,7 +1096,7 @@ static void valueFlowImpossibleValues(TokenList& tokenList, const Settings& sett value.setImpossible(); setTokenValue(tok, std::move(value), settings); } - if (Token::simpleMatch(tok, "?") && Token::Match(tok->astOperand1(), "<|<=|>|>=")) { + else if (Token::simpleMatch(tok, "?") && Token::Match(tok->astOperand1(), "<|<=|>|>=")) { const Token* condTok = tok->astOperand1(); const Token* branchesTok = tok->astOperand2(); @@ -1139,11 +1139,20 @@ static void valueFlowImpossibleValues(TokenList& tokenList, const Settings& sett setTokenValue(tok, std::move(value), settings); } - } else if (Token::simpleMatch(tok, "%") && tok->astOperand2() && tok->astOperand2()->hasKnownIntValue()) { + } else if (tok->isBinaryOp() && tok->str() == "%" && tok->astOperand2()->hasKnownIntValue()) { ValueFlow::Value value{tok->astOperand2()->getKnownIntValue()}; value.bound = ValueFlow::Value::Bound::Lower; value.setImpossible(); setTokenValue(tok, std::move(value), settings); + } else if (tok->isBinaryOp() && tok->str() == "|") { + const ValueFlow::Value* opVal = tok->astOperand1()->getKnownValue(ValueFlow::Value::ValueType::INT); + if (!opVal) + opVal = tok->astOperand2()->getKnownValue(ValueFlow::Value::ValueType::INT); + if (opVal && opVal->intvalue != 0) { + ValueFlow::Value value{0}; + value.setImpossible(); + setTokenValue(tok, std::move(value), settings); + } } else if (Token::Match(tok, "abs|labs|llabs|fabs|fabsf|fabsl (")) { ValueFlow::Value value{-1}; value.bound = ValueFlow::Value::Bound::Upper; diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 93248837cb3..84d973b8f60 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -4999,6 +4999,13 @@ class TestCondition : public TestFixture { "[test.cpp:9:9]: (style) Condition '0b101010' is always true [knownConditionTrueFalse]\n" "[test.cpp:10:9]: (style) Condition '!42' is always false [knownConditionTrueFalse]\n", errout_str()); + + check("void f(int i) {\n" // #15144 + " int c = i | 1;\n" + " if (c) {}\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3:9]: (style) Condition 'c' is always true [knownConditionTrueFalse]\n", + errout_str()); } void alwaysTrueSymbolic() diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index f84f0ea0d89..25abc5639f2 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -57,6 +57,7 @@ class TestValueFlow : public TestFixture { TEST_CASE(valueFlowMove); TEST_CASE(valueFlowBitAnd); + TEST_CASE(valueFlowBitOr); TEST_CASE(valueFlowRightShift); TEST_CASE(valueFlowCalculations); @@ -4416,6 +4417,16 @@ class TestValueFlow : public TestFixture { ASSERT_EQUALS(false, testValueOfX(code,3U,16)); } + void valueFlowBitOr() { + const char *code; + + code = "int f(int a) {\n" + " int x = a | 0x80;\n" + " return x;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfXImpossible(code, 3U, 0)); + } + void valueFlowForwardInconclusiveImpossible() { const char *code; From bebcdcd96d72d2821698f215bea96919da5d3f67 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Mon, 26 Oct 2026 19:32:34 +0100 Subject: [PATCH 2/3] Format --- test/testvalueflow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 25abc5639f2..81d1336848d 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -4423,7 +4423,7 @@ class TestValueFlow : public TestFixture { code = "int f(int a) {\n" " int x = a | 0x80;\n" " return x;\n" - "}\n"; + "}\n"; ASSERT_EQUALS(true, testValueOfXImpossible(code, 3U, 0)); } From 9df444721ac586062897f63dece92c2aae33ca17 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Mon, 26 Oct 2026 21:17:43 +0100 Subject: [PATCH 3/3] Handle impossible values --- lib/valueflow.cpp | 18 ++++++++++++++---- test/testcondition.cpp | 9 ++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index bce706e73c8..f73b35e6cfa 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1145,10 +1145,20 @@ static void valueFlowImpossibleValues(TokenList& tokenList, const Settings& sett value.setImpossible(); setTokenValue(tok, std::move(value), settings); } else if (tok->isBinaryOp() && tok->str() == "|") { - const ValueFlow::Value* opVal = tok->astOperand1()->getKnownValue(ValueFlow::Value::ValueType::INT); - if (!opVal) - opVal = tok->astOperand2()->getKnownValue(ValueFlow::Value::ValueType::INT); - if (opVal && opVal->intvalue != 0) { + bool nonNull = false; + for (const Token *op : {tok->astOperand1(), tok->astOperand2()}) { + for (const ValueFlow::Value& v : op->values()) { + if (v.valueType != ValueFlow::Value::ValueType::INT) + continue; + if ((v.isKnown() && v.intvalue != 0) || (v.isImpossible() && v.intvalue == 0)) { + nonNull = true; + break; + } + } + if (nonNull) + break; + } + if (nonNull) { ValueFlow::Value value{0}; value.setImpossible(); setTokenValue(tok, std::move(value), settings); diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 84d973b8f60..9fd1e24f20e 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -5003,8 +5003,15 @@ class TestCondition : public TestFixture { check("void f(int i) {\n" // #15144 " int c = i | 1;\n" " if (c) {}\n" + "}\n" + "void g(int i, int m) {\n" + " if (m == 0)\n" + " return;\n" + " int c = i | m;\n" + " if (c) {}\n" "}\n"); - ASSERT_EQUALS("[test.cpp:3:9]: (style) Condition 'c' is always true [knownConditionTrueFalse]\n", + ASSERT_EQUALS("[test.cpp:3:9]: (style) Condition 'c' is always true [knownConditionTrueFalse]\n" + "[test.cpp:9:9]: (style) Condition 'c' is always true [knownConditionTrueFalse]\n", errout_str()); }