From 47c3ad1b7536fe055e53daf9ff6cd4ae500e7a67 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 31 Jan 2024 20:39:23 +0100 Subject: [PATCH] Partial fix for #12387 FP unsignedLessThanZero for template type (#5922) --- lib/checkcondition.cpp | 2 +- lib/checkother.cpp | 6 +++++- lib/checkother.h | 2 +- test/testother.cpp | 12 ++++++++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index f03ed2953a1..0e3fe825a21 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -1567,7 +1567,7 @@ void CheckCondition::alwaysTrueFalse() { const ValueFlow::Value *zeroValue = nullptr; const Token *nonZeroExpr = nullptr; - if (CheckOther::comparisonNonZeroExpressionLessThanZero(tok, &zeroValue, &nonZeroExpr) || + if (CheckOther::comparisonNonZeroExpressionLessThanZero(tok, &zeroValue, &nonZeroExpr, /*suppress*/ true) || CheckOther::testIfNonZeroExpressionIsPositive(tok, &zeroValue, &nonZeroExpr)) continue; } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index fa43aba816a..22a279ed87d 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2737,7 +2737,7 @@ void CheckOther::checkSignOfUnsignedVariable() } } -bool CheckOther::comparisonNonZeroExpressionLessThanZero(const Token *tok, const ValueFlow::Value **zeroValue, const Token **nonZeroExpr) +bool CheckOther::comparisonNonZeroExpressionLessThanZero(const Token *tok, const ValueFlow::Value **zeroValue, const Token **nonZeroExpr, bool suppress) { if (!tok->isComparisonOp() || !tok->astOperand1() || !tok->astOperand2()) return false; @@ -2755,6 +2755,10 @@ bool CheckOther::comparisonNonZeroExpressionLessThanZero(const Token *tok, const return false; } + if (const Variable* var = (*nonZeroExpr)->variable()) + if (var->typeStartToken()->isTemplateArg()) + return suppress; + const ValueType* vt = (*nonZeroExpr)->valueType(); return vt && (vt->pointer || vt->sign == ValueType::UNSIGNED); } diff --git a/lib/checkother.h b/lib/checkother.h index a2f440ccc73..2600bb4f329 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -56,7 +56,7 @@ class CPPCHECKLIB CheckOther : public Check { CheckOther() : Check(myName()) {} /** Is expression a comparison that checks if a nonzero (unsigned/pointer) expression is less than zero? */ - static bool comparisonNonZeroExpressionLessThanZero(const Token *tok, const ValueFlow::Value **zeroValue, const Token **nonZeroExpr); + static bool comparisonNonZeroExpressionLessThanZero(const Token *tok, const ValueFlow::Value **zeroValue, const Token **nonZeroExpr, bool suppress = false); /** Is expression a comparison that checks if a nonzero (unsigned/pointer) expression is positive? */ static bool testIfNonZeroExpressionIsPositive(const Token *tok, const ValueFlow::Value **zeroValue, const Token **nonZeroExpr); diff --git a/test/testother.cpp b/test/testother.cpp index 71a284d499d..2dbebf306d8 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -8250,6 +8250,18 @@ class TestOther : public TestFixture { " if (y < x) {}\n" "}"); ASSERT_EQUALS("[test.cpp:4]: (style) Checking if unsigned expression 'y' is less than zero.\n", errout.str()); + + // #12387 + check("template\n" + "void f(T t) {\n" + " if constexpr (std::numeric_limits::is_signed) {\n" + " if (t < 0) {}\n" + " }\n" + "}\n" + "void g() {\n" + " f(0);\n" + "}"); + ASSERT_EQUALS("", errout.str()); } void checkSignOfPointer() {