ticket #1513 new check: Detecting obviously wrong math call arguments passed to math functions)
This commit is contained in:
parent
c7d36b73ed
commit
b5fb01c202
|
@ -2435,6 +2435,48 @@ void CheckOther::checkZeroDivision()
|
|||
}
|
||||
|
||||
|
||||
void CheckOther::checkMathFunctions()
|
||||
{
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
// case log(-2)
|
||||
if (Token::Match(tok, "log ( %num% )") &&
|
||||
MathLib::isNegative(tok->tokAt(2)->str()) &&
|
||||
MathLib::isInt(tok->tokAt(2)->str()) &&
|
||||
MathLib::toLongNumber(tok->tokAt(2)->str()) <= 0)
|
||||
{
|
||||
mathfunctionCallError(tok);
|
||||
}
|
||||
// case log(-2.0)
|
||||
else if (Token::Match(tok, "log ( %num% )") &&
|
||||
MathLib::isNegative(tok->tokAt(2)->str()) &&
|
||||
MathLib::isFloat(tok->tokAt(2)->str()) &&
|
||||
MathLib::toDoubleNumber(tok->tokAt(2)->str()) <= 0.)
|
||||
{
|
||||
mathfunctionCallError(tok);
|
||||
}
|
||||
|
||||
// case log(0.0)
|
||||
else if (Token::Match(tok, "log ( %num% )") &&
|
||||
!MathLib::isNegative(tok->tokAt(2)->str()) &&
|
||||
MathLib::isFloat(tok->tokAt(2)->str()) &&
|
||||
MathLib::toDoubleNumber(tok->tokAt(2)->str()) <= 0.)
|
||||
{
|
||||
mathfunctionCallError(tok);
|
||||
}
|
||||
|
||||
// case log(0)
|
||||
else if (Token::Match(tok, "log ( %num% )") &&
|
||||
!MathLib::isNegative(tok->tokAt(2)->str()) &&
|
||||
MathLib::isInt(tok->tokAt(2)->str()) &&
|
||||
MathLib::toLongNumber(tok->tokAt(2)->str()) <= 0)
|
||||
{
|
||||
mathfunctionCallError(tok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CheckOther::postIncrement()
|
||||
{
|
||||
|
@ -2578,6 +2620,11 @@ void CheckOther::zerodivError(const Token *tok)
|
|||
reportError(tok, Severity::error, "zerodiv", "Division by zero");
|
||||
}
|
||||
|
||||
void CheckOther::mathfunctionCallError(const Token *tok)
|
||||
{
|
||||
reportError(tok, Severity::error, "wrongmathcall","Passing value " + tok->tokAt(2)->str() + " to " + tok->str() + "() leads to undefined result");
|
||||
}
|
||||
|
||||
void CheckOther::postIncrementError(const Token *tok, const std::string &var_name, const bool isIncrement)
|
||||
{
|
||||
std::string type = (isIncrement ? "Incrementing" : "Decrementing");
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
checkOther.strPlusChar();
|
||||
checkOther.invalidFunctionUsage();
|
||||
checkOther.checkZeroDivision();
|
||||
checkOther.checkMathFunctions();
|
||||
|
||||
// New type of check: Check execution paths
|
||||
checkOther.executionPaths();
|
||||
|
@ -150,6 +151,9 @@ public:
|
|||
/** @brief %Check zero division*/
|
||||
void checkZeroDivision();
|
||||
|
||||
/** @brief %Check for parameters given to math function that do not make sense*/
|
||||
void checkMathFunctions();
|
||||
|
||||
/** @brief %Check for post increment/decrement in for loop*/
|
||||
void postIncrement();
|
||||
|
||||
|
@ -184,6 +188,7 @@ public:
|
|||
void uninitdataError(const Token *tok, const std::string &varname);
|
||||
void uninitvarError(const Token *tok, const std::string &varname);
|
||||
void zerodivError(const Token *tok);
|
||||
void mathfunctionCallError(const Token *tok);
|
||||
void postIncrementError(const Token *tok, const std::string &var_name, const bool isIncrement);
|
||||
|
||||
void getErrorMessages()
|
||||
|
@ -196,6 +201,7 @@ public:
|
|||
uninitdataError(0, "varname");
|
||||
uninitvarError(0, "varname");
|
||||
zerodivError(0);
|
||||
mathfunctionCallError(0);
|
||||
|
||||
// style
|
||||
cstyleCastError(0);
|
||||
|
|
|
@ -75,6 +75,32 @@ std::string MathLib::toString(T d)
|
|||
return result.str();
|
||||
}
|
||||
|
||||
bool MathLib::isFloat(const std::string &s)
|
||||
{
|
||||
// every number that contains a . is a float
|
||||
if (s.find("." , 0) != std::string::npos)
|
||||
return true;
|
||||
// scientific notation
|
||||
else if (s.find("E-", 0) != std::string::npos
|
||||
|| s.find("e-", 0) != std::string::npos)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MathLib::isNegative(const std::string &s)
|
||||
{
|
||||
// remember position
|
||||
unsigned long n = 0;
|
||||
// eat up whitespace
|
||||
while (std::isspace(s[n])) ++n;
|
||||
// every negative number has a negative sign
|
||||
if (s[n] == '-')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MathLib::isInt(const std::string & s)
|
||||
{
|
||||
// perform prechecks:
|
||||
|
|
|
@ -37,6 +37,8 @@ public:
|
|||
static std::string toString(T d);
|
||||
|
||||
static bool isInt(const std::string & str);
|
||||
static bool isFloat(const std::string &str);
|
||||
static bool isNegative(const std::string &str);
|
||||
|
||||
static std::string add(const std::string & first, const std::string & second);
|
||||
static std::string subtract(const std::string & first, const std::string & second);
|
||||
|
|
|
@ -34,6 +34,8 @@ private:
|
|||
TEST_CASE(calculate);
|
||||
TEST_CASE(convert);
|
||||
TEST_CASE(isint);
|
||||
TEST_CASE(isnegative);
|
||||
TEST_CASE(isfloat);
|
||||
}
|
||||
|
||||
void calculate()
|
||||
|
@ -164,6 +166,55 @@ private:
|
|||
ASSERT_EQUALS(false, MathLib::isInt("-1.E+1"));
|
||||
ASSERT_EQUALS(false, MathLib::isInt("+1.E-1"));
|
||||
}
|
||||
|
||||
void isnegative()
|
||||
{
|
||||
ASSERT_EQUALS(true, MathLib::isNegative("-1"));
|
||||
ASSERT_EQUALS(true, MathLib::isNegative("-1."));
|
||||
ASSERT_EQUALS(true, MathLib::isNegative("-1.0"));
|
||||
ASSERT_EQUALS(true, MathLib::isNegative("-1.0E+2"));
|
||||
ASSERT_EQUALS(true, MathLib::isNegative("-1.0E-2"));
|
||||
|
||||
ASSERT_EQUALS(false, MathLib::isNegative("+1"));
|
||||
ASSERT_EQUALS(false, MathLib::isNegative("+1."));
|
||||
ASSERT_EQUALS(false, MathLib::isNegative("+1.0"));
|
||||
ASSERT_EQUALS(false, MathLib::isNegative("+1.0E+2"));
|
||||
ASSERT_EQUALS(false, MathLib::isNegative("+1.0E-2"));
|
||||
}
|
||||
|
||||
void isfloat()
|
||||
{
|
||||
ASSERT_EQUALS(false, MathLib::isFloat("0"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("0."));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("0.0"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("-0."));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("+0."));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("-0.0"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("+0.0"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("+0.0E+1"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("+0.0E-1"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("-0.0E+1"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("-0.0E-1"));
|
||||
|
||||
ASSERT_EQUALS(false , MathLib::isFloat("1"));
|
||||
ASSERT_EQUALS(false , MathLib::isFloat("-1"));
|
||||
ASSERT_EQUALS(false , MathLib::isFloat("+1"));
|
||||
ASSERT_EQUALS(false , MathLib::isFloat("+1E+1"));
|
||||
ASSERT_EQUALS(false , MathLib::isFloat("+1E+10000"));
|
||||
ASSERT_EQUALS(false , MathLib::isFloat("-1E+1"));
|
||||
ASSERT_EQUALS(false , MathLib::isFloat("-1E+10000"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("-1E-1"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("-1E-10000"));
|
||||
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("0.4"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("2352.3f"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("0.00004"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("2352.00001f"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat(".4"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("1.0E+1"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("1.0E-1"));
|
||||
ASSERT_EQUALS(true , MathLib::isFloat("-1.0E+1"));
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestMathLib)
|
||||
|
|
|
@ -89,6 +89,8 @@ private:
|
|||
TEST_CASE(dangerousStrolUsage);
|
||||
|
||||
TEST_CASE(passedByValue);
|
||||
|
||||
TEST_CASE(mathfunctionCall1);
|
||||
}
|
||||
|
||||
void check(const char code[])
|
||||
|
@ -110,11 +112,10 @@ private:
|
|||
checkOther.warningRedundantCode();
|
||||
checkOther.checkZeroDivision();
|
||||
checkOther.unreachableCode();
|
||||
checkOther.checkMathFunctions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void zeroDiv1()
|
||||
{
|
||||
check("void foo()\n"
|
||||
|
@ -2157,6 +2158,70 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:1]: (style) Function parameter 'v' is passed by value. It could be passed by reference instead.\n", errout.str());
|
||||
}
|
||||
|
||||
void mathfunctionCall1()
|
||||
{
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" std::cout << log(-2) << std::endl;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -2 to log() leads to undefined result\n", errout.str());
|
||||
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" std::cout << log(-1.) << std::endl;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -1. to log() leads to undefined result\n", errout.str());
|
||||
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" std::cout << log(-1.0) << std::endl;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -1.0 to log() leads to undefined result\n", errout.str());
|
||||
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" std::cout << log(-0.1) << std::endl;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Passing value -0.1 to log() leads to undefined result\n", errout.str());
|
||||
|
||||
check("void foo()\n"
|
||||
"{\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.) << 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"
|
||||
"}");
|
||||
TODO_ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" std::cout << log(1E-3) << std::endl;\n"
|
||||
"}");
|
||||
TODO_ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestOther)
|
||||
|
|
Loading…
Reference in New Issue