diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 7b37a4315..9c36a28a8 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1984,9 +1984,12 @@ static bool isConditionKnown(const Token* tok, bool then) if (then) op = "&&"; const Token* parent = tok->astParent(); - while (parent && (parent->str() == op || parent->str() == "!")) + while (parent && (parent->str() == op || parent->str() == "!" || parent->isCast())) parent = parent->astParent(); - return Token::Match(parent, "(|;"); + const Token* top = tok->astTop(); + if (top && Token::Match(top->previous(), "if|while|for (")) + return parent == top || Token::simpleMatch(parent, ";"); + return parent && parent->str() != op; } static const std::string& invertAssign(const std::string& assign) @@ -6353,12 +6356,16 @@ static bool isIntegralOnlyOperator(const Token* tok) { return Token::Match(tok, "%|<<|>>|&|^|~|%or%"); } -static bool isIntegral(const Token* tok) +static bool isIntegralOrPointer(const Token* tok) { if (!tok) return false; if (astIsIntegral(tok, false)) return true; + if (astIsPointer(tok)) + return true; + if (Token::Match(tok, "NULL|nullptr")) + return true; if (tok->valueType()) return false; // These operators only work on integers @@ -6367,7 +6374,7 @@ static bool isIntegral(const Token* tok) if (isIntegralOnlyOperator(tok->astParent())) return true; if (Token::Match(tok, "+|-|*|/") && tok->isBinaryOp()) - return isIntegral(tok->astOperand1()) && isIntegral(tok->astOperand2()); + return isIntegralOrPointer(tok->astOperand1()) && isIntegralOrPointer(tok->astOperand2()); return false; } @@ -6400,7 +6407,7 @@ static void valueFlowInferCondition(TokenList* tokenlist, setTokenValue(tok, value, settings); } } - } else if (isIntegral(tok->astOperand1()) && isIntegral(tok->astOperand2())) { + } else if (isIntegralOrPointer(tok->astOperand1()) && isIntegralOrPointer(tok->astOperand2())) { std::vector result = infer(IntegralInferModel{}, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values()); for (const ValueFlow::Value& value : result) { diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 40711e5f0..eaaeb4bb7 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -1309,7 +1309,7 @@ private: check("int f(char c) {\n" " return (c <= 'a' && c >= 'z');\n" "}", "test.cpp", false); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Condition 'c>='z'' is always false\n", errout.str()); } void incorrectLogicOperator7() { // opposite expressions @@ -4714,6 +4714,11 @@ private: // #11098 check("void f(unsigned int x) { if (x == -1u) {} }\n"); ASSERT_EQUALS("", errout.str()); + + check("bool f(const int *p, const int *q) {\n" + " return p != NULL && q != NULL && p == NULL;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'p==NULL' is always false\n", errout.str()); } void alwaysTrueContainer() { diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 8acca5137..4466a5903 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -5089,6 +5089,7 @@ private: " return((n=42) && *n == 'A');\n" "}"; values = tokenValues(code, "n =="); + values.remove_if(&isNotUninitValue); ASSERT_EQUALS(true, values.empty()); // #8233