diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index e51645297..0cea33314 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -225,6 +225,14 @@ std::string MathLib::multiply(const std::string &first, const std::string &secon return toString(toDoubleNumber(first) * toDoubleNumber(second)); } +std::string MathLib::mod(const std::string &first, const std::string &second) +{ + if (MathLib::isInt(first) && MathLib::isInt(second)) { + return toString(toLongNumber(first) % toLongNumber(second)); + } + return toString(fmod(toDoubleNumber(first),toDoubleNumber(second))); +} + std::string MathLib::calculate(const std::string &first, const std::string &second, char action) { switch (action) { @@ -240,6 +248,9 @@ std::string MathLib::calculate(const std::string &first, const std::string &seco case '/': return MathLib::divide(first, second); + case '%': + return MathLib::mod(first, second); + default: throw InternalError(0, std::string("Unexpected action '") + action + "' in MathLib::calculate(). Please report this to Cppcheck developers."); } diff --git a/lib/mathlib.h b/lib/mathlib.h index c92c50659..c584f8d0d 100644 --- a/lib/mathlib.h +++ b/lib/mathlib.h @@ -54,6 +54,7 @@ public: static std::string subtract(const std::string & first, const std::string & second); static std::string multiply(const std::string & first, const std::string & second); static std::string divide(const std::string & first, const std::string & second); + static std::string mod(const std::string & first, const std::string & second); static std::string calculate(const std::string & first, const std::string & second, char action); static std::string sin(const std::string & tok); diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 87484e6bb..0536d6d9b 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -30,6 +30,7 @@ private: void run() { TEST_CASE(calculate); + TEST_CASE(calculate1); TEST_CASE(convert); TEST_CASE(isint); TEST_CASE(isnegative); @@ -123,6 +124,16 @@ private: ASSERT_THROW(MathLib::calculate("1","2",'j'),InternalError); } + void calculate1() { // mod + ASSERT_EQUALS("0" , MathLib::calculate("2" , "1" , '%')); + ASSERT_EQUALS("0" , MathLib::calculate("2.0" , "1.0" , '%')); + ASSERT_EQUALS("2" , MathLib::calculate("12" , "5" , '%')); + ASSERT_EQUALS("1" , MathLib::calculate("100" , "3" , '%')); + ASSERT_EQUALS("12" , MathLib::calculate("12.0" , "13.0" , '%')); + ASSERT_EQUALS("1.3" , MathLib::calculate("5.3" , "2.0" , '%')); + ASSERT_EQUALS("1.7" , MathLib::calculate("18.5" , "4.2" , '%')); + } + void convert() { // ------------------ // tolong conversion: diff --git a/test/testother.cpp b/test/testother.cpp index 3615563fc..9c3fdf370 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -108,6 +108,7 @@ private: TEST_CASE(testMisusedScopeObjectDoesNotPickNestedClass); TEST_CASE(trac2071); TEST_CASE(trac2084); + TEST_CASE(trac3693); TEST_CASE(assignmentInAssert); @@ -2387,6 +2388,16 @@ private: ASSERT_EQUALS("[trac1132.cpp:16]: (error) instance of \"Lock\" object destroyed immediately\n", errout.str()); } + void trac3693() { + check("struct A{\n" + " enum {\n" + " b = 300\n" + " };\n" + "};\n" + "const int DFLT_TIMEOUT = A::b % 1000000 ;\n"); + ASSERT_EQUALS("", errout.str()); + } + void testMisusedScopeObjectDoesNotPickFunction1() { check("int main ( )\n" "{\n"