From a8300315cdc85dc130c9db9d3e0c320ec434ed49 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:52:32 +0200 Subject: [PATCH 1/9] Update checkother.cpp --- lib/checkother.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index a03e4bd6b54..1c126279586 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -365,6 +365,50 @@ void CheckOther::cstyleCastError(const Token *tok, bool isPtr) "which kind of cast is expected.", CWE398, Certainty::normal); } +void CheckOther::suspiciousFloatingPointCast() +{ + if (!mSettings->severity.isEnabled(Severity::style) && !mSettings->isPremiumEnabled("suspiciousFloatingPointCast")) + return; + + logChecker("CheckOther::suspiciousFloatingPointCast"); // style + + const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); + for (const Scope * scope : symbolDatabase->functionScopes) { + const Token* tok = scope->bodyStart; + if (scope->function && scope->function->isConstructor()) + tok = scope->classDef; + for (; tok && tok != scope->bodyEnd; tok = tok->next()) { + + if (!tok->isCast()) + continue; + + const ValueType* vt = tok->valueType(); + if (!vt || vt->pointer || vt->reference != Reference::None || (vt->type != ValueType::FLOAT && vt->type != ValueType::DOUBLE)) + continue; + + using VTT = std::vector; + const VTT sourceTypes = vt->type == ValueType::FLOAT ? VTT{ ValueType::DOUBLE, ValueType::LONGDOUBLE } : VTT{ ValueType::LONGDOUBLE }; + + const Token* source = tok->astOperand2() ? tok->astOperand2() : tok->astOperand1(); + if (!source || !source->valueType() || std::find(sourceTypes.begin(), sourceTypes.end(), source->valueType()->type) == sourceTypes.end()) + continue; + + const Token* parent = tok->astParent(); + if (!parent || !parent->valueType() || std::find(sourceTypes.begin(), sourceTypes.end(), parent->valueType()->type) == sourceTypes.end()) + continue; + + suspiciousFloatingPointCastError(tok); + } + } +} + +void CheckOther::suspiciousFloatingPointCastError(const Token* tok) +{ + reportError(tok, Severity::style, "suspiciousFloatingPointCast", + "Floating-point cast causes loss of precision.\n" + "If this cast is not intentional, remove it to avoid loss of precision", CWE398, Certainty::normal); +} + //--------------------------------------------------------------------------- // float* f; double* d = (double*)f; <-- Pointer cast to a type with an incompatible binary data representation //--------------------------------------------------------------------------- From 9bee2aaba1407e8e6bcb7806d57b1a6addbefa85 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:53:05 +0200 Subject: [PATCH 2/9] Update checkother.h --- lib/checkother.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/checkother.h b/lib/checkother.h index 13ae3d30b2f..61f8c793e51 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -74,6 +74,7 @@ class CPPCHECKLIB CheckOther : public Check { // Checks checkOther.warningOldStylePointerCast(); + checkOther.suspiciousFloatingPointCast(); checkOther.invalidPointerCast(); checkOther.checkCharVariable(); checkOther.redundantBitwiseOperationInSwitchError(); @@ -125,6 +126,8 @@ class CPPCHECKLIB CheckOther : public Check { /** @brief Are there C-style pointer casts in a c++ file? */ void warningOldStylePointerCast(); + void suspiciousFloatingPointCast(); + /** @brief Check for pointer casts to a type with an incompatible binary data representation */ void invalidPointerCast(); @@ -241,6 +244,7 @@ class CPPCHECKLIB CheckOther : public Check { void clarifyCalculationError(const Token *tok, const std::string &op); void clarifyStatementError(const Token* tok); void cstyleCastError(const Token *tok, bool isPtr = true); + void suspiciousFloatingPointCastError(const Token *tok); void invalidPointerCastError(const Token* tok, const std::string& from, const std::string& to, bool inconclusive, bool toIsInt); void passedByValueError(const Variable* var, bool inconclusive, bool isRangeBasedFor = false); void constVariableError(const Variable *var, const Function *function); From c25379e5c4de8c3f3b65156304c40ab4bcb89d80 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:58:09 +0200 Subject: [PATCH 3/9] Update testother.cpp --- test/testother.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/testother.cpp b/test/testother.cpp index 3c488a7d013..2d8883368fd 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -124,6 +124,7 @@ class TestOther : public TestFixture { TEST_CASE(suspiciousCase); TEST_CASE(suspiciousEqualityComparison); TEST_CASE(suspiciousUnaryPlusMinus); // #8004 + TEST_CASE(suspiciousFloatingPointCast); TEST_CASE(selfAssignment); TEST_CASE(trac1132); @@ -5594,6 +5595,18 @@ class TestOther : public TestFixture { errout_str()); } + void suspiciousFloatingPointCast() { + check("double f(double a, double b, float c) {\n" // #12921 + " return a + (float)b + c;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2]: (style) Floating-point cast causes loss of precision.\n", errout_str()); + + check("long double f(long double a, long double b, float c) {\n" + " return a + (double)b + c;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2]: (style) Floating-point cast causes loss of precision.\n", errout_str()); + } + void selfAssignment() { check("void foo()\n" "{\n" From 4abb362ab7c1c63945ee3f4343e12842faef6e66 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:01:53 +0200 Subject: [PATCH 4/9] Update checkother.h --- lib/checkother.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/checkother.h b/lib/checkother.h index 61f8c793e51..3c327a5959f 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -318,6 +318,7 @@ class CPPCHECKLIB CheckOther : public Check { c.checkComparisonFunctionIsAlwaysTrueOrFalseError(nullptr, "isless","varName",false); c.checkCastIntToCharAndBackError(nullptr, "func_name"); c.cstyleCastError(nullptr); + c.suspiciousFloatingPointCastError(nullptr); c.passedByValueError(nullptr, false); c.constVariableError(nullptr, nullptr); c.constStatementError(nullptr, "type", false); From 2ba289ffa98033edadb4e34ac9522d741330d49e Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:44:33 +0200 Subject: [PATCH 5/9] Update checkother.cpp --- lib/checkother.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 1c126279586..f671f9f531b 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -396,8 +396,8 @@ void CheckOther::suspiciousFloatingPointCast() const Token* parent = tok->astParent(); if (!parent || !parent->valueType() || std::find(sourceTypes.begin(), sourceTypes.end(), parent->valueType()->type) == sourceTypes.end()) continue; - - suspiciousFloatingPointCastError(tok); + + suspiciousFloatingPointCastError(tok); } } } From 508d4ed43264955b65194951c03ff934e48a36f0 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:55:12 +0200 Subject: [PATCH 6/9] Update checkother.cpp --- lib/checkother.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index f671f9f531b..0326a1eda95 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -397,7 +397,7 @@ void CheckOther::suspiciousFloatingPointCast() if (!parent || !parent->valueType() || std::find(sourceTypes.begin(), sourceTypes.end(), parent->valueType()->type) == sourceTypes.end()) continue; - suspiciousFloatingPointCastError(tok); + suspiciousFloatingPointCastError(tok); } } } From 3f347460f47c0a0b56ad41d4dfdbade904783fe5 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 10 Jul 2024 17:18:15 +0200 Subject: [PATCH 7/9] Update checkother.cpp --- lib/checkother.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 0326a1eda95..7349f3e0bd7 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -394,7 +394,20 @@ void CheckOther::suspiciousFloatingPointCast() continue; const Token* parent = tok->astParent(); - if (!parent || !parent->valueType() || std::find(sourceTypes.begin(), sourceTypes.end(), parent->valueType()->type) == sourceTypes.end()) + if (!parent) + continue; + + const ValueType* parentVt = parent->valueType(); + if (!parentVt || parent->str() == "(") { + int argn{}; + if (const Token* ftok = getTokenArgumentFunction(tok, argn)) { + if (ftok->function()) { + if (const Variable* argVar = ftok->function()->getArgumentVar(argn)) + parentVt = argVar->valueType(); + } + } + } + if (!parentVt || std::find(sourceTypes.begin(), sourceTypes.end(), parentVt->type) == sourceTypes.end()) continue; suspiciousFloatingPointCastError(tok); From 339630baddc10136457d39dac40eac4da7e9bec0 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 10 Jul 2024 17:19:06 +0200 Subject: [PATCH 8/9] Update testother.cpp --- test/testother.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/testother.cpp b/test/testother.cpp index 2d8883368fd..3923c0f18ae 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -5596,15 +5596,30 @@ class TestOther : public TestFixture { } void suspiciousFloatingPointCast() { - check("double f(double a, double b, float c) {\n" // #12921 + check("double f(double a, double b, float c) {\n" " return a + (float)b + c;\n" "}\n"); ASSERT_EQUALS("[test.cpp:2]: (style) Floating-point cast causes loss of precision.\n", errout_str()); + check("double f(double a, double b, float c) {\n" + " return a + static_cast(b) + c;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2]: (style) Floating-point cast causes loss of precision.\n", errout_str()); + check("long double f(long double a, long double b, float c) {\n" " return a + (double)b + c;\n" "}\n"); ASSERT_EQUALS("[test.cpp:2]: (style) Floating-point cast causes loss of precision.\n", errout_str()); + + check("void g(int, double);\n" + "void h(double);\n" + "void f(double d) {\n" + " g(1, (float)d);\n" + " h((float)d);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (style) Floating-point cast causes loss of precision.\n" + "[test.cpp:5]: (style) Floating-point cast causes loss of precision.\n", + errout_str()); } void selfAssignment() { From 3b95b1d1c5bd6c36efc67d18969d0d014e826505 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:13:59 +0200 Subject: [PATCH 9/9] Update releasenotes.txt --- releasenotes.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes.txt b/releasenotes.txt index 843e590f2ac..352afff73c3 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -1,7 +1,7 @@ Release Notes for Cppcheck 2.15 New checks: -- +- suspiciousFloatingPointCast flags unnecessary floating point casts that cause loss of precision Improved checking: -