From 710d7ce0157f4485e4fa461d3885bff434261c6f Mon Sep 17 00:00:00 2001 From: rikardfalkeborn Date: Fri, 3 Aug 2018 12:14:39 +0200 Subject: [PATCH] Add checks of log2 and log1p range (#1324) * Add tests for log10{,f,l} valid arguments * Add log2{,f,l} to checkfunctions * Add log1p{,f,l} to checkfunctions * checkfunctions: Simplify check for log function limit out of range The conditions for negative and non-negative int and float were identical so the call to isNegative can be removed and the if-statements be simplified. --- lib/checkfunctions.cpp | 23 +++--- test/testfunctions.cpp | 162 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 154 insertions(+), 31 deletions(-) diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 479262618..9b4b08a2c 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -226,20 +226,17 @@ void CheckFunctions::checkMathFunctions() continue; if (printWarnings && Token::Match(tok, "%name% ( !!)")) { if (tok->strAt(-1) != "." - && Token::Match(tok, "log|logf|logl|log10|log10f|log10l ( %num% )")) { + && Token::Match(tok, "log|logf|logl|log10|log10f|log10l|log2|log2f|log2l ( %num% )")) { const std::string& number = tok->strAt(2); - const bool isNegative = MathLib::isNegative(number); - const bool isInt = MathLib::isInt(number); - const bool isFloat = MathLib::isFloat(number); - if (isNegative && isInt && MathLib::toLongNumber(number) <= 0) { - mathfunctionCallWarning(tok); // case log(-2) - } else if (isNegative && isFloat && MathLib::toDoubleNumber(number) <= 0.) { - mathfunctionCallWarning(tok); // case log(-2.0) - } else if (!isNegative && isFloat && MathLib::toDoubleNumber(number) <= 0.) { - mathfunctionCallWarning(tok); // case log(0.0) - } else if (!isNegative && isInt && MathLib::toLongNumber(number) <= 0) { - mathfunctionCallWarning(tok); // case log(0) - } + if ((MathLib::isInt(number) && MathLib::toLongNumber(number) <= 0) || + (MathLib::isFloat(number) && MathLib::toDoubleNumber(number) <= 0.)) + mathfunctionCallWarning(tok); + } + else if (Token::Match(tok, "log1p|log1pf|log1pl ( %num% )")) { + const std::string& number = tok->strAt(2); + if ((MathLib::isInt(number) && MathLib::toLongNumber(number) <= -1) || + (MathLib::isFloat(number) && MathLib::toDoubleNumber(number) <= -1.)) + 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% )")) { diff --git a/test/testfunctions.cpp b/test/testfunctions.cpp index 80edccc02..cbcb448bd 100644 --- a/test/testfunctions.cpp +++ b/test/testfunctions.cpp @@ -478,71 +478,197 @@ private: } void mathfunctionCall_log() { - // log,log10,logf,logl,log10f,log10l + // log,log10,logf,logl,log10f,log10l,log2,log2f,log2l,log1p,log1pf,log1pl check("void foo()\n" "{\n" " std::cout << log(-2) << std::endl;\n" " std::cout << logf(-2) << std::endl;\n" " std::cout << logl(-2) << std::endl;\n" + " std::cout << log10(-2) << std::endl;\n" + " std::cout << log10f(-2) << std::endl;\n" + " std::cout << log10l(-2) << std::endl;\n" + " std::cout << log2(-2) << std::endl;\n" + " std::cout << log2f(-2) << std::endl;\n" + " std::cout << log2l(-2) << std::endl;\n" + " std::cout << log1p(-3) << std::endl;\n" + " std::cout << log1pf(-3) << std::endl;\n" + " std::cout << log1pl(-3) << std::endl;\n" "}"); 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()); + "[test.cpp:5]: (warning) Passing value -2 to logl() leads to implementation-defined result.\n" + "[test.cpp:6]: (warning) Passing value -2 to log10() leads to implementation-defined result.\n" + "[test.cpp:7]: (warning) Passing value -2 to log10f() leads to implementation-defined result.\n" + "[test.cpp:8]: (warning) Passing value -2 to log10l() leads to implementation-defined result.\n" + "[test.cpp:9]: (warning) Passing value -2 to log2() leads to implementation-defined result.\n" + "[test.cpp:10]: (warning) Passing value -2 to log2f() leads to implementation-defined result.\n" + "[test.cpp:11]: (warning) Passing value -2 to log2l() leads to implementation-defined result.\n" + "[test.cpp:12]: (warning) Passing value -3 to log1p() leads to implementation-defined result.\n" + "[test.cpp:13]: (warning) Passing value -3 to log1pf() leads to implementation-defined result.\n" + "[test.cpp:14]: (warning) Passing value -3 to log1pl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" " std::cout << log(-1) << std::endl;\n" " std::cout << logf(-1) << std::endl;\n" " std::cout << logl(-1) << std::endl;\n" + " std::cout << log10(-1) << std::endl;\n" + " std::cout << log10f(-1) << std::endl;\n" + " std::cout << log10l(-1) << std::endl;\n" + " std::cout << log2(-1) << std::endl;\n" + " std::cout << log2f(-1) << std::endl;\n" + " std::cout << log2l(-1) << std::endl;\n" + " std::cout << log1p(-2) << std::endl;\n" + " std::cout << log1pf(-2) << std::endl;\n" + " std::cout << log1pl(-2) << std::endl;\n" "}"); 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()); + "[test.cpp:5]: (warning) Passing value -1 to logl() leads to implementation-defined result.\n" + "[test.cpp:6]: (warning) Passing value -1 to log10() leads to implementation-defined result.\n" + "[test.cpp:7]: (warning) Passing value -1 to log10f() leads to implementation-defined result.\n" + "[test.cpp:8]: (warning) Passing value -1 to log10l() leads to implementation-defined result.\n" + "[test.cpp:9]: (warning) Passing value -1 to log2() leads to implementation-defined result.\n" + "[test.cpp:10]: (warning) Passing value -1 to log2f() leads to implementation-defined result.\n" + "[test.cpp:11]: (warning) Passing value -1 to log2l() leads to implementation-defined result.\n" + "[test.cpp:12]: (warning) Passing value -2 to log1p() leads to implementation-defined result.\n" + "[test.cpp:13]: (warning) Passing value -2 to log1pf() leads to implementation-defined result.\n" + "[test.cpp:14]: (warning) Passing value -2 to log1pl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" " std::cout << log(-1.0) << std::endl;\n" " std::cout << logf(-1.0) << std::endl;\n" " std::cout << logl(-1.0) << std::endl;\n" + " std::cout << log10(-1.0) << std::endl;\n" + " std::cout << log10f(-1.0) << std::endl;\n" + " std::cout << log10l(-1.0) << std::endl;\n" + " std::cout << log2(-1.0) << std::endl;\n" + " std::cout << log2f(-1.0) << std::endl;\n" + " std::cout << log2l(-1.0) << std::endl;\n" + " std::cout << log1p(-2.0) << std::endl;\n" + " std::cout << log1pf(-2.0) << std::endl;\n" + " std::cout << log1pl(-2.0) << std::endl;\n" "}"); 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()); + "[test.cpp:5]: (warning) Passing value -1.0 to logl() leads to implementation-defined result.\n" + "[test.cpp:6]: (warning) Passing value -1.0 to log10() leads to implementation-defined result.\n" + "[test.cpp:7]: (warning) Passing value -1.0 to log10f() leads to implementation-defined result.\n" + "[test.cpp:8]: (warning) Passing value -1.0 to log10l() leads to implementation-defined result.\n" + "[test.cpp:9]: (warning) Passing value -1.0 to log2() leads to implementation-defined result.\n" + "[test.cpp:10]: (warning) Passing value -1.0 to log2f() leads to implementation-defined result.\n" + "[test.cpp:11]: (warning) Passing value -1.0 to log2l() leads to implementation-defined result.\n" + "[test.cpp:12]: (warning) Passing value -2.0 to log1p() leads to implementation-defined result.\n" + "[test.cpp:13]: (warning) Passing value -2.0 to log1pf() leads to implementation-defined result.\n" + "[test.cpp:14]: (warning) Passing value -2.0 to log1pl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" " std::cout << log(-0.1) << std::endl;\n" " std::cout << logf(-0.1) << std::endl;\n" " std::cout << logl(-0.1) << std::endl;\n" + " std::cout << log10(-0.1) << std::endl;\n" + " std::cout << log10f(-0.1) << std::endl;\n" + " std::cout << log10l(-0.1) << std::endl;\n" + " std::cout << log2(-0.1) << std::endl;\n" + " std::cout << log2f(-0.1) << std::endl;\n" + " std::cout << log2l(-0.1) << std::endl;\n" + " std::cout << log1p(-1.1) << std::endl;\n" + " std::cout << log1pf(-1.1) << std::endl;\n" + " std::cout << log1pl(-1.1) << std::endl;\n" "}"); 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()); + "[test.cpp:5]: (warning) Passing value -0.1 to logl() leads to implementation-defined result.\n" + "[test.cpp:6]: (warning) Passing value -0.1 to log10() leads to implementation-defined result.\n" + "[test.cpp:7]: (warning) Passing value -0.1 to log10f() leads to implementation-defined result.\n" + "[test.cpp:8]: (warning) Passing value -0.1 to log10l() leads to implementation-defined result.\n" + "[test.cpp:9]: (warning) Passing value -0.1 to log2() leads to implementation-defined result.\n" + "[test.cpp:10]: (warning) Passing value -0.1 to log2f() leads to implementation-defined result.\n" + "[test.cpp:11]: (warning) Passing value -0.1 to log2l() leads to implementation-defined result.\n" + "[test.cpp:12]: (warning) Passing value -1.1 to log1p() leads to implementation-defined result.\n" + "[test.cpp:13]: (warning) Passing value -1.1 to log1pf() leads to implementation-defined result.\n" + "[test.cpp:14]: (warning) Passing value -1.1 to log1pl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" " std::cout << log(0) << std::endl;\n" " std::cout << logf(0.) << std::endl;\n" " std::cout << logl(0.0) << std::endl;\n" + " std::cout << log10(0.0) << std::endl;\n" + " std::cout << log10f(0) << std::endl;\n" + " std::cout << log10l(0.) << std::endl;\n" + " std::cout << log2(0.) << std::endl;\n" + " std::cout << log2f(0.0) << std::endl;\n" + " std::cout << log2l(0) << std::endl;\n" + " std::cout << log1p(-1.) << std::endl;\n" + " std::cout << log1pf(-1.0) << std::endl;\n" + " std::cout << log1pl(-1) << std::endl;\n" "}"); 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()); + "[test.cpp:5]: (warning) Passing value 0.0 to logl() leads to implementation-defined result.\n" + "[test.cpp:6]: (warning) Passing value 0.0 to log10() leads to implementation-defined result.\n" + "[test.cpp:7]: (warning) Passing value 0 to log10f() leads to implementation-defined result.\n" + "[test.cpp:8]: (warning) Passing value 0. to log10l() leads to implementation-defined result.\n" + "[test.cpp:9]: (warning) Passing value 0. to log2() leads to implementation-defined result.\n" + "[test.cpp:10]: (warning) Passing value 0.0 to log2f() leads to implementation-defined result.\n" + "[test.cpp:11]: (warning) Passing value 0 to log2l() leads to implementation-defined result.\n" + "[test.cpp:12]: (warning) Passing value -1. to log1p() leads to implementation-defined result.\n" + "[test.cpp:13]: (warning) Passing value -1.0 to log1pf() leads to implementation-defined result.\n" + "[test.cpp:14]: (warning) Passing value -1 to log1pl() leads to implementation-defined result.\n", errout.str()); check("void foo()\n" "{\n" - " std::cout << log(1E-3) << std::endl;\n" - " std::cout << logf(1E-3) << std::endl;\n" - " std::cout << logl(1E-3) << std::endl;\n" - " std::cout << log(1.0E-3) << std::endl;\n" - " std::cout << logf(1.0E-3) << std::endl;\n" - " std::cout << logl(1.0E-3) << std::endl;\n" - " std::cout << log(1.0E+3) << std::endl;\n" - " std::cout << logf(1.0E+3) << std::endl;\n" - " std::cout << logl(1.0E+3) << std::endl;\n" - " std::cout << log(2.0) << std::endl;\n" - " std::cout << logf(2.0) << std::endl;\n" - " std::cout << logf(2.0f) << std::endl;\n" + " std::cout << log(1E-3) << std::endl;\n" + " std::cout << logf(1E-3) << std::endl;\n" + " std::cout << logl(1E-3) << std::endl;\n" + " std::cout << log10(1E-3) << std::endl;\n" + " std::cout << log10f(1E-3) << std::endl;\n" + " std::cout << log10l(1E-3) << std::endl;\n" + " std::cout << log2(1E-3) << std::endl;\n" + " std::cout << log2f(1E-3) << std::endl;\n" + " std::cout << log2l(1E-3) << std::endl;\n" + " std::cout << log1p(-1+1E-3) << std::endl;\n" + " std::cout << log1pf(-1+1E-3) << std::endl;\n" + " std::cout << log1pl(-1+1E-3) << std::endl;\n" + " std::cout << log(1.0E-3) << std::endl;\n" + " std::cout << logf(1.0E-3) << std::endl;\n" + " std::cout << logl(1.0E-3) << std::endl;\n" + " std::cout << log10(1.0E-3) << std::endl;\n" + " std::cout << log10f(1.0E-3) << std::endl;\n" + " std::cout << log10l(1.0E-3) << std::endl;\n" + " std::cout << log2(1.0E-3) << std::endl;\n" + " std::cout << log2f(1.0E-3) << std::endl;\n" + " std::cout << log2l(1.0E-3) << std::endl;\n" + " std::cout << log1p(-1+1.0E-3) << std::endl;\n" + " std::cout << log1pf(-1+1.0E-3) << std::endl;\n" + " std::cout << log1pl(-1+1.0E-3) << std::endl;\n" + " std::cout << log(1.0E+3) << std::endl;\n" + " std::cout << logf(1.0E+3) << std::endl;\n" + " std::cout << logl(1.0E+3) << std::endl;\n" + " std::cout << log10(1.0E+3) << std::endl;\n" + " std::cout << log10f(1.0E+3) << std::endl;\n" + " std::cout << log10l(1.0E+3) << std::endl;\n" + " std::cout << log2(1.0E+3) << std::endl;\n" + " std::cout << log2f(1.0E+3) << std::endl;\n" + " std::cout << log2l(1.0E+3) << std::endl;\n" + " std::cout << log1p(1.0E+3) << std::endl;\n" + " std::cout << log1pf(1.0E+3) << std::endl;\n" + " std::cout << log1pl(1.0E+3) << std::endl;\n" + " std::cout << log(2.0) << std::endl;\n" + " std::cout << logf(2.0) << std::endl;\n" + " std::cout << logf(2.0f) << std::endl;\n" + " std::cout << log10(2.0) << std::endl;\n" + " std::cout << log10f(2.0) << std::endl;\n" + " std::cout << log10f(2.0f) << std::endl;\n" + " std::cout << log2(2.0) << std::endl;\n" + " std::cout << log2f(2.0) << std::endl;\n" + " std::cout << log2f(2.0f) << std::endl;\n" + " std::cout << log1p(2.0) << std::endl;\n" + " std::cout << log1pf(2.0) << std::endl;\n" + " std::cout << log1pf(2.0f) << std::endl;\n" "}"); ASSERT_EQUALS("", errout.str());