diff --git a/lib/checkother.cpp b/lib/checkother.cpp index bc1a3415a..a31339ab9 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1894,57 +1894,57 @@ void CheckOther::checkMathFunctions() bool isInt = MathLib::isInt(tok->strAt(2)); bool isFloat = MathLib::isFloat(tok->strAt(2)); if (isNegative && isInt && MathLib::toLongNumber(tok->strAt(2)) <= 0) { - mathfunctionCallError(tok); // case log(-2) + mathfunctionCallWarning(tok); // case log(-2) } else if (isNegative && isFloat && MathLib::toDoubleNumber(tok->strAt(2)) <= 0.) { - mathfunctionCallError(tok); // case log(-2.0) + mathfunctionCallWarning(tok); // case log(-2.0) } else if (!isNegative && isFloat && MathLib::toDoubleNumber(tok->strAt(2)) <= 0.) { - mathfunctionCallError(tok); // case log(0.0) + mathfunctionCallWarning(tok); // case log(0.0) } else if (!isNegative && isInt && MathLib::toLongNumber(tok->strAt(2)) <= 0) { - mathfunctionCallError(tok); // case log(0) + mathfunctionCallWarning(tok); // case log(0) } } // acos( x ), asin( x ) where x is defined for interval [-1,+1], but not beyond else if (Token::Match(tok, "acos|acosl|acosf|asin|asinf|asinl ( %num% )") && std::fabs(MathLib::toDoubleNumber(tok->strAt(2))) > 1.0) { - mathfunctionCallError(tok); + mathfunctionCallWarning(tok); } // sqrt( x ): if x is negative the result is undefined else if (Token::Match(tok, "sqrt|sqrtf|sqrtl ( %num% )") && MathLib::isNegative(tok->strAt(2))) { - mathfunctionCallError(tok); + mathfunctionCallWarning(tok); } // atan2 ( x , y): x and y can not be zero, because this is mathematically not defined else if (Token::Match(tok, "atan2|atan2f|atan2l ( %num% , %num% )") && MathLib::isNullValue(tok->strAt(2)) && MathLib::isNullValue(tok->strAt(4))) { - mathfunctionCallError(tok, 2); + mathfunctionCallWarning(tok, 2); } // fmod ( x , y) If y is zero, then either a range error will occur or the function will return zero (implementation-defined). else if (Token::Match(tok, "fmod|fmodf|fmodl ( %any%")) { const Token* nextArg = tok->tokAt(2)->nextArgument(); if (nextArg && nextArg->isNumber() && MathLib::isNullValue(nextArg->str())) - mathfunctionCallError(tok, 2); + mathfunctionCallWarning(tok, 2); } // pow ( x , y) If x is zero, and y is negative --> division by zero else if (Token::Match(tok, "pow|powf|powl ( %num% , %num% )") && MathLib::isNullValue(tok->strAt(2)) && MathLib::isNegative(tok->strAt(4))) { - mathfunctionCallError(tok, 2); + mathfunctionCallWarning(tok, 2); } } } } -void CheckOther::mathfunctionCallError(const Token *tok, const unsigned int numParam) +void CheckOther::mathfunctionCallWarning(const Token *tok, const unsigned int numParam) { if (tok) { if (numParam == 1) - reportError(tok, Severity::error, "wrongmathcall", "Passing value " + tok->strAt(2) + " to " + tok->str() + "() leads to undefined result."); + reportError(tok, Severity::warning, "wrongmathcall", "Passing value " + tok->strAt(2) + " to " + tok->str() + "() leads to implementation-defined result."); else if (numParam == 2) - reportError(tok, Severity::error, "wrongmathcall", "Passing values " + tok->strAt(2) + " and " + tok->strAt(4) + " to " + tok->str() + "() leads to undefined result."); + reportError(tok, Severity::warning, "wrongmathcall", "Passing values " + tok->strAt(2) + " and " + tok->strAt(4) + " to " + tok->str() + "() leads to implementation-defined result."); } else - reportError(tok, Severity::error, "wrongmathcall", "Passing value '#' to #() leads to undefined result."); + reportError(tok, Severity::warning, "wrongmathcall", "Passing value '#' to #() leads to implementation-defined result."); } //--------------------------------------------------------------------------- diff --git a/lib/checkother.h b/lib/checkother.h index 12ea6de43..ec7290fbc 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -257,7 +257,7 @@ private: void zerodivError(const Token *tok, bool inconclusive); void zerodivcondError(const Token *tokcond, const Token *tokdiv, bool inconclusive); void nanInArithmeticExpressionError(const Token *tok); - void mathfunctionCallError(const Token *tok, const unsigned int numParam = 1); + void mathfunctionCallWarning(const Token *tok, const unsigned int numParam = 1); void redundantAssignmentError(const Token *tok1, const Token* tok2, const std::string& var, bool inconclusive); void redundantAssignmentInSwitchError(const Token *tok1, const Token *tok2, const std::string &var); void redundantCopyError(const Token *tok1, const Token* tok2, const std::string& var); @@ -299,7 +299,6 @@ private: c.udivError(0, false); c.zerodivError(0, false); c.zerodivcondError(0,0,false); - c.mathfunctionCallError(0); c.misusedScopeObjectError(NULL, "varname"); c.doubleFreeError(0, "varname"); c.invalidPointerCastError(0, "float", "double", false); @@ -326,6 +325,7 @@ private: c.suspiciousCaseInSwitchError(0, "||"); c.suspiciousEqualityComparisonError(0); c.selfAssignmentError(0, "varname"); + c.mathfunctionCallWarning(0); c.memsetZeroBytesError(0, "varname"); c.memsetFloatError(0, "varname"); c.memsetValueOutOfRangeError(0, "varname"); diff --git a/test/testother.cpp b/test/testother.cpp index fdbbd7316..46740bf29 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -1336,9 +1336,18 @@ private: " std::cout << sqrtf(-1) << std::endl;\n" " std::cout << sqrtl(-1) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -1 to sqrt() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing value -1 to sqrtf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing value -1 to sqrtl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -1 to sqrt() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing value -1 to sqrtf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing value -1 to sqrtl() leads to implementation-defined result.\n", errout.str()); + + // implementation-defined behaviour for "finite values of x<0" only: + check("void foo()\n" + "{\n" + " std::cout << sqrt(-0.) << std::endl;\n" + " std::cout << sqrtf(-0.) << std::endl;\n" + " std::cout << sqrtl(-0.) << std::endl;\n" + "}"); + ASSERT_EQUALS("", errout.str()); check("void foo()\n" "{\n" @@ -1357,9 +1366,9 @@ private: " std::cout << logf(-2) << std::endl;\n" " std::cout << logl(-2) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -2 to log() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing value -2 to logf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing value -2 to logl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -2 to log() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing value -2 to logf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing value -2 to logl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" @@ -1367,9 +1376,9 @@ private: " std::cout << logf(-1) << std::endl;\n" " std::cout << logl(-1) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -1 to log() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing value -1 to logf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing value -1 to logl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -1 to log() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing value -1 to logf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing value -1 to logl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" @@ -1377,9 +1386,9 @@ private: " std::cout << logf(-1.0) << std::endl;\n" " std::cout << logl(-1.0) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -1.0 to log() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing value -1.0 to logf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing value -1.0 to logl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -1.0 to log() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing value -1.0 to logf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing value -1.0 to logl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" @@ -1387,9 +1396,9 @@ private: " std::cout << logf(-0.1) << std::endl;\n" " std::cout << logl(-0.1) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -0.1 to log() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing value -0.1 to logf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing value -0.1 to logl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -0.1 to log() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing value -0.1 to logf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing value -0.1 to logl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" @@ -1397,9 +1406,9 @@ private: " std::cout << logf(0.) << std::endl;\n" " std::cout << logl(0.0) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing value 0 to log() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing value 0. to logf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing value 0.0 to logl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value 0 to log() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing value 0. to logf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing value 0.0 to logl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" @@ -1476,9 +1485,9 @@ private: " std::cout << acosf(1.1) << std::endl;\n" " std::cout << acosl(1.1) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing value 1.1 to acos() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing value 1.1 to acosf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing value 1.1 to acosl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value 1.1 to acos() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing value 1.1 to acosf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing value 1.1 to acosl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" @@ -1486,9 +1495,9 @@ private: " std::cout << acosf(-1.1) << std::endl;\n" " std::cout << acosl(-1.1) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -1.1 to acos() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing value -1.1 to acosf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing value -1.1 to acosl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -1.1 to acos() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing value -1.1 to acosf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing value -1.1 to acosl() leads to implementation-defined result.\n", errout.str()); } void mathfunctionCall_asin() { @@ -1537,9 +1546,9 @@ private: " std::cout << asinf(1.1) << std::endl;\n" " std::cout << asinl(1.1) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing value 1.1 to asin() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing value 1.1 to asinf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing value 1.1 to asinl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value 1.1 to asin() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing value 1.1 to asinf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing value 1.1 to asinl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" @@ -1547,9 +1556,9 @@ private: " std::cout << asinf(-1.1) << std::endl;\n" " std::cout << asinl(-1.1) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -1.1 to asin() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing value -1.1 to asinf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing value -1.1 to asinl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing value -1.1 to asin() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing value -1.1 to asinf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing value -1.1 to asinl() leads to implementation-defined result.\n", errout.str()); } void mathfunctionCall_pow() { @@ -1560,9 +1569,9 @@ private: " std::cout << powf(0,-10) << std::endl;\n" " std::cout << powl(0,-10) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing values 0 and -10 to pow() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing values 0 and -10 to powf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing values 0 and -10 to powl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing values 0 and -10 to pow() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing values 0 and -10 to powf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing values 0 and -10 to powl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" @@ -1619,9 +1628,9 @@ private: " std::cout << atan2f(0,0) << std::endl;\n" " std::cout << atan2l(0,0) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing values 0 and 0 to atan2() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing values 0 and 0 to atan2f() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing values 0 and 0 to atan2l() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing values 0 and 0 to atan2() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing values 0 and 0 to atan2f() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing values 0 and 0 to atan2l() leads to implementation-defined result.\n", errout.str()); } void mathfunctionCall_fmod() { @@ -1632,9 +1641,9 @@ private: " std::cout << fmodf(1.0,0) << std::endl;\n" " std::cout << fmodl(1.0,0) << std::endl;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Passing values 1.0 and 0 to fmod() leads to undefined result.\n" - "[test.cpp:4]: (error) Passing values 1.0 and 0 to fmodf() leads to undefined result.\n" - "[test.cpp:5]: (error) Passing values 1.0 and 0 to fmodl() leads to undefined result.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (warning) Passing values 1.0 and 0 to fmod() leads to implementation-defined result.\n" + "[test.cpp:4]: (warning) Passing values 1.0 and 0 to fmodf() leads to implementation-defined result.\n" + "[test.cpp:5]: (warning) Passing values 1.0 and 0 to fmodl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n"