Fixed #5023 (Add support for asinf,acosf,asinl,acosl (...) functions)

This commit is contained in:
Ettl Martin 2013-09-13 19:49:25 +02:00 committed by Daniel Marjamäki
parent bcbcee87d5
commit 5a671f8914
2 changed files with 194 additions and 69 deletions

View File

@ -2262,7 +2262,7 @@ void CheckOther::checkMathFunctions()
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (tok->varId()) if (tok->varId())
continue; continue;
if (Token::Match(tok, "log|log10 ( %num% )")) { if (Token::Match(tok, "log|logf|logl|log10|log10f|log10l ( %num% )")) {
bool isNegative = MathLib::isNegative(tok->strAt(2)); bool isNegative = MathLib::isNegative(tok->strAt(2));
bool isInt = MathLib::isInt(tok->strAt(2)); bool isInt = MathLib::isInt(tok->strAt(2));
bool isFloat = MathLib::isFloat(tok->strAt(2)); bool isFloat = MathLib::isFloat(tok->strAt(2));
@ -2278,7 +2278,7 @@ void CheckOther::checkMathFunctions()
} }
// acos( x ), asin( x ) where x is defined for interval [-1,+1], but not beyond // acos( x ), asin( x ) where x is defined for interval [-1,+1], but not beyond
else if (Token::Match(tok, "acos|asin ( %num% )") && else if (Token::Match(tok, "acos|acosl|acosf|asin|asinf|asinl ( %num% )") &&
std::fabs(MathLib::toDoubleNumber(tok->strAt(2))) > 1.0) { std::fabs(MathLib::toDoubleNumber(tok->strAt(2))) > 1.0) {
mathfunctionCallError(tok); mathfunctionCallError(tok);
} }
@ -2288,19 +2288,19 @@ void CheckOther::checkMathFunctions()
mathfunctionCallError(tok); mathfunctionCallError(tok);
} }
// atan2 ( x , y): x and y can not be zero, because this is mathematically not defined // atan2 ( x , y): x and y can not be zero, because this is mathematically not defined
else if (Token::Match(tok, "atan2 ( %num% , %num% )") && else if (Token::Match(tok, "atan2|atan2f|atan2l ( %num% , %num% )") &&
MathLib::isNullValue(tok->strAt(2)) && MathLib::isNullValue(tok->strAt(2)) &&
MathLib::isNullValue(tok->strAt(4))) { MathLib::isNullValue(tok->strAt(4))) {
mathfunctionCallError(tok, 2); mathfunctionCallError(tok, 2);
} }
// fmod ( x , y) If y is zero, then either a range error will occur or the function will return zero (implementation-defined). // 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 ( %any%")) { else if (Token::Match(tok, "fmod|fmodf|fmodl ( %any%")) {
const Token* nextArg = tok->tokAt(2)->nextArgument(); const Token* nextArg = tok->tokAt(2)->nextArgument();
if (nextArg && nextArg->isNumber() && MathLib::isNullValue(nextArg->str())) if (nextArg && nextArg->isNumber() && MathLib::isNullValue(nextArg->str()))
mathfunctionCallError(tok, 2); mathfunctionCallError(tok, 2);
} }
// pow ( x , y) If x is zero, and y is negative --> division by zero // pow ( x , y) If x is zero, and y is negative --> division by zero
else if (Token::Match(tok, "pow ( %num% , %num% )") && else if (Token::Match(tok, "pow|powf|powl ( %num% , %num% )") &&
MathLib::isNullValue(tok->strAt(2)) && MathLib::isNullValue(tok->strAt(2)) &&
MathLib::isNegative(tok->strAt(4))) { MathLib::isNegative(tok->strAt(4))) {
mathfunctionCallError(tok, 2); mathfunctionCallError(tok, 2);

View File

@ -1335,64 +1335,71 @@ private:
} }
void mathfunctionCall1() { void mathfunctionCall1() {
// log|log10 // log,log10,logf,logl,log10f,log10l
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << log(-2) << std::endl;\n" " std::cout << log(-2) << std::endl;\n"
" 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", errout.str()); 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());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << log(-1.) << std::endl;\n" " std::cout << log(-1) << std::endl;\n"
" 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", errout.str()); 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());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << log(-1.0) << std::endl;\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"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -1.0 to log() leads to undefined result.\n", errout.str()); 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());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << log(-0.1) << std::endl;\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"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -0.1 to log() leads to undefined result.\n", errout.str()); 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());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << log(0) << std::endl;\n" " std::cout << log(0) << std::endl;\n"
" 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", errout.str()); 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"
check("void foo()\n" "[test.cpp:5]: (error) Passing value 0.0 to logl() leads to undefined result.\n", errout.str());
"{\n"
" std::cout << log(0.) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value 0. to log() leads to undefined result.\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << log(0.0) << std::endl;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value 0.0 to log() leads to undefined result.\n", errout.str());
check("void foo()\n"
"{\n"
" std::cout << log(1.0E+3) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << log(1.0E-3) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << log(1E-3) << 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 << 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.0) << std::endl;\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
@ -1402,52 +1409,128 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
" std::cout << log(2.0) << std::endl;\n"
"}");
ASSERT_EQUALS("", errout.str());
// #3473 - no warning if "log" is a variable // #3473 - no warning if "log" is a variable
check("Fred::Fred() : log(0) { }"); check("Fred::Fred() : log(0) { }");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// acos // acos, acosf, acosl
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << acos(1) << std::endl;\n" " return acos(1) \n"
" std::cout << acos(-1) << std::endl;\n" " + acos(-1) \n"
" std::cout << acos(0.1) << std::endl;\n" " + acos(0.1) \n"
" std::cout << acos(0.0001) << std::endl;\n" " + acos(0.0001) \n"
" std::cout << acos(0.01) << std::endl;\n" " + acos(0.01) \n"
" std::cout << acos(1.0E-1) << std::endl;\n" " + acos(1.0E-1) \n"
" std::cout << acos(-1.0E-1) << std::endl;\n" " + acos(-1.0E-1) \n"
" std::cout << acos(+1.0E-1) << std::endl;\n" " + acos(+1.0E-1) \n"
" std::cout << acos(0.1E-1) << std::endl;\n" " + acos(0.1E-1) \n"
" std::cout << acos(+0.1E-1) << std::endl;\n" " + acos(+0.1E-1) \n"
" std::cout << acos(-0.1E-1) << std::endl;\n" " + acos(-0.1E-1) \n"
" + acosf(1) \n"
" + acosf(-1) \n"
" + acosf(0.1) \n"
" + acosf(0.0001) \n"
" + acosf(0.01) \n"
" + acosf(1.0E-1) \n"
" + acosf(-1.0E-1) \n"
" + acosf(+1.0E-1) \n"
" + acosf(0.1E-1) \n"
" + acosf(+0.1E-1) \n"
" + acosf(-0.1E-1) \n"
" + acosl(1) \n"
" + acosl(-1) \n"
" + acosl(0.1) \n"
" + acosl(0.0001) \n"
" + acosl(0.01) \n"
" + acosl(1.0E-1) \n"
" + acosl(-1.0E-1) \n"
" + acosl(+1.0E-1) \n"
" + acosl(0.1E-1) \n"
" + acosl(+0.1E-1) \n"
" + acosl(-0.1E-1); \n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << acos(1.1) << std::endl;\n" " std::cout << acos(1.1) << std::endl;\n"
" 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", errout.str()); 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());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << acos(-1.1) << std::endl;\n" " std::cout << acos(-1.1) << std::endl;\n"
" 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", errout.str()); 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());
// asin, asinf, asinl
check("void foo()\n"
"{\n"
" return asin(1) \n"
" + asin(-1) \n"
" + asin(0.1) \n"
" + asin(0.0001) \n"
" + asin(0.01) \n"
" + asin(1.0E-1) \n"
" + asin(-1.0E-1) \n"
" + asin(+1.0E-1) \n"
" + asin(0.1E-1) \n"
" + asin(+0.1E-1) \n"
" + asin(-0.1E-1) \n"
" + asinf(1) \n"
" + asinf(-1) \n"
" + asinf(0.1) \n"
" + asinf(0.0001) \n"
" + asinf(0.01) \n"
" + asinf(1.0E-1) \n"
" + asinf(-1.0E-1) \n"
" + asinf(+1.0E-1) \n"
" + asinf(0.1E-1) \n"
" + asinf(+0.1E-1) \n"
" + asinf(-0.1E-1) \n"
" + asinl(1) \n"
" + asinl(-1) \n"
" + asinl(0.1) \n"
" + asinl(0.0001) \n"
" + asinl(0.01) \n"
" + asinl(1.0E-1) \n"
" + asinl(-1.0E-1) \n"
" + asinl(+1.0E-1) \n"
" + asinl(0.1E-1) \n"
" + asinl(+0.1E-1) \n"
" + asinl(-0.1E-1); \n"
"}");
ASSERT_EQUALS("", errout.str());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << acos(-110) << std::endl;\n" " std::cout << asin(1.1) << std::endl;\n"
" std::cout << asinf(1.1) << std::endl;\n"
" std::cout << asinl(1.1) << std::endl;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -110 to acos() leads to undefined result.\n", errout.str()); 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());
check("void foo()\n"
"{\n"
" std::cout << asin(-1.1) << std::endl;\n"
" 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());
// atan2 // atan2
check("void foo()\n" check("void foo()\n"
@ -1463,57 +1546,99 @@ private:
" std::cout << atan2(0.1E-1,3) << std::endl;\n" " std::cout << atan2(0.1E-1,3) << std::endl;\n"
" std::cout << atan2(+0.1E-1,1) << std::endl;\n" " std::cout << atan2(+0.1E-1,1) << std::endl;\n"
" std::cout << atan2(-0.1E-1,8) << std::endl;\n" " std::cout << atan2(-0.1E-1,8) << std::endl;\n"
" std::cout << atan2f(1,1) << std::endl;\n"
" std::cout << atan2f(-1,-1) << std::endl;\n"
" std::cout << atan2f(0.1,1) << std::endl;\n"
" std::cout << atan2f(0.0001,100) << std::endl;\n"
" std::cout << atan2f(0.01m-1) << std::endl;\n"
" std::cout << atan2f(1.0E-1,-3) << std::endl;\n"
" std::cout << atan2f(-1.0E-1,+2) << std::endl;\n"
" std::cout << atan2f(+1.0E-1,0) << std::endl;\n"
" std::cout << atan2f(0.1E-1,3) << std::endl;\n"
" std::cout << atan2f(+0.1E-1,1) << std::endl;\n"
" std::cout << atan2f(-0.1E-1,8) << std::endl;\n"
" std::cout << atan2l(1,1) << std::endl;\n"
" std::cout << atan2l(-1,-1) << std::endl;\n"
" std::cout << atan2l(0.1,1) << std::endl;\n"
" std::cout << atan2l(0.0001,100) << std::endl;\n"
" std::cout << atan2l(0.01m-1) << std::endl;\n"
" std::cout << atan2l(1.0E-1,-3) << std::endl;\n"
" std::cout << atan2l(-1.0E-1,+2) << std::endl;\n"
" std::cout << atan2l(+1.0E-1,0) << std::endl;\n"
" std::cout << atan2l(0.1E-1,3) << std::endl;\n"
" std::cout << atan2l(+0.1E-1,1) << std::endl;\n"
" std::cout << atan2l(-0.1E-1,8) << std::endl;\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << atan2(0,0) << std::endl;\n" " std::cout << atan2(0,0) << std::endl;\n"
" 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", errout.str()); 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());
// fmod // fmod, fmodl, fmodf
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << fmod(1.0,0) << std::endl;\n" " std::cout << fmod(1.0,0) << std::endl;\n"
" 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", errout.str()); 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());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << fmod(1.0,1) << std::endl;\n" " std::cout << fmod(1.0,1) << std::endl;\n"
" std::cout << fmodf(1.0,1) << std::endl;\n"
" std::cout << fmodl(1.0,1) << std::endl;\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// pow // pow, powf, powl
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << pow(0,-10) << std::endl;\n" " std::cout << pow(0,-10) << std::endl;\n"
" 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", errout.str()); 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());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << pow(0,10) << std::endl;\n" " std::cout << pow(0,10) << std::endl;\n"
" std::cout << powf(0,10) << std::endl;\n"
" std::cout << powl(0,10) << std::endl;\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// sqrt // sqrt, sqrtf, sqrtl
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << sqrt(-1) << std::endl;\n" " std::cout << sqrt(-1) << std::endl;\n"
" 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", errout.str()); 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());
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" std::cout << sqrt(1) << std::endl;\n" " std::cout << sqrt(1) << std::endl;\n"
" std::cout << sqrtf(1) << std::endl;\n"
" std::cout << sqrtl(1) << std::endl;\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void cctypefunctionCall() { void cctypefunctionCall() {