From 86a8d88729f5aa1d011333d6c7ace93ae6c1cd0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 8 Jun 2022 09:58:11 +0200 Subject: [PATCH] Tokenizer: Remove simplification of math functions from simplifyTokenList2 --- lib/cppcheck.cpp | 16 +-- lib/tokenize.cpp | 196 ------------------------------------ lib/tokenize.h | 12 --- test/testsimplifytokens.cpp | 39 ------- test/testtokenize.cpp | 19 ---- 5 files changed, 4 insertions(+), 278 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 47fd4ec7f..74e417bb5 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -887,19 +887,11 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string if (!mSettings.buildDir.empty()) checkUnusedFunctions.parseTokens(tokenizer, filename.c_str(), &mSettings); - // simplify more if required, skip rest of iteration if failed + // handling of "simple" rules has been removed. if (mSimplify && hasRule("simple")) { - std::cout << "Handling of \"simple\" rules is deprecated and will be removed in Cppcheck 2.5." << std::endl; - - // if further simplification fails then skip rest of iteration - Timer timer3("Tokenizer::simplifyTokenList2", mSettings.showtime, &s_timerResults); - result = tokenizer.simplifyTokenList2(); - timer3.stop(); - if (!result) - continue; - - if (!Settings::terminated()) - executeRules("simple", tokenizer); + // FIXME Remove this function + tokenizer.simplifyTokenList2(); + throw InternalError(nullptr, "Handling of \"simple\" rules has been removed in Cppcheck. Use --addon instead."); } } catch (const simplecpp::Output &o) { diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index bd6789742..84971a5e0 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5275,9 +5275,6 @@ bool Tokenizer::simplifyTokenList2() tok->clearValueFlow(); } - // Convert e.g. atol("0") into 0 - simplifyMathFunctions(); - // f(x=g()) => x=g(); f(x) simplifyAssignmentInFunctionCall(); @@ -5388,8 +5385,6 @@ bool Tokenizer::simplifyTokenList2() simplifyEmptyNamespaces(); - simplifyMathFunctions(); - validate(); Token::assignProgressValues(list.front()); @@ -9681,16 +9676,6 @@ static bool isNumberOneOf(const std::string &s, const MathLib::bigint& intConsta return false; } -// ------------------------------------------------------------------------ -// Helper function to check whether number is zero (0 or 0.0 or 0E+0) or not? -// @param s the string to check -// @return true in case s is zero and false otherwise. -// ------------------------------------------------------------------------ -bool Tokenizer::isZeroNumber(const std::string &s) -{ - return isNumberOneOf(s, 0L, "0.0"); -} - // ------------------------------------------------------------------------ // Helper function to check whether number is one (1 or 0.1E+1 or 1E+0) or not? // @param s the string to check @@ -9715,187 +9700,6 @@ bool Tokenizer::isTwoNumber(const std::string &s) return isNumberOneOf(s, 2L, "2.0"); } -// ------------------------------------------------------ -// Simplify math functions. -// It simplifies the following functions: atol(), fmin(), -// fminl(), fminf(), fmax(), fmaxl(), fmaxf(), pow(), -// powf(), powl(), cbrt(), cbrtl(), cbtrf(), sqrt(), -// sqrtf(), sqrtl(), exp(), expf(), expl(), exp2(), -// exp2f(), exp2l(), log2(), log2f(), log2l(), log1p(), -// log1pf(), log1pl(), log10(), log10l(), log10f(), -// log(), logf(), logl(), logb(), logbf(), logbl(), acosh() -// acoshf(), acoshl(), acos(), acosf(), acosl(), cosh() -// coshf(), coshf(), cos(), cosf(), cosl(), erfc(), -// erfcf(), erfcl(), ilogb(), ilogbf(), ilogbf(), erf(), -// erfl(), erff(), asin(), asinf(), asinf(), asinh(), -// asinhf(), asinhl(), tan(), tanf(), tanl(), tanh(), -// tanhf(), tanhl(), atan(), atanf(), atanl(), atanh(), -// atanhf(), atanhl(), expm1(), expm1l(), expm1f(), sin(), -// sinf(), sinl(), sinh(), sinhf(), sinhl() -// in the tokenlist. -// -// Reference: -// - http://www.cplusplus.com/reference/cmath/ -// ------------------------------------------------------ -void Tokenizer::simplifyMathFunctions() -{ - for (Token *tok = list.front(); tok; tok = tok->next()) { - if (tok->isName() && !tok->varId() && tok->strAt(1) == "(") { // precondition for function - bool simplifcationMade = false; - if (Token::Match(tok, "atol ( %str% )")) { //@todo Add support for atoll() - if (Token::simpleMatch(tok->tokAt(-2), "std ::")) { - tok = tok->tokAt(-2);// set token index two steps back - tok->deleteNext(2); // delete "std ::" - } - const std::string& strNumber = tok->tokAt(2)->strValue(); // get number - const bool isNotAnInteger = (!MathLib::isInt(strNumber));// check: is not an integer - if (strNumber.empty() || isNotAnInteger) { - // Ignore strings which we can't convert - continue; - } - // Convert string into a number and insert into token list - tok->str(MathLib::toString(MathLib::toLongNumber(strNumber))); - // remove ( %num% ) - tok->deleteNext(3); - simplifcationMade = true; - } else if (Token::Match(tok, "sqrt|sqrtf|sqrtl|cbrt|cbrtf|cbrtl ( %num% )")) { - // Simplify: sqrt(0) = 0 and cbrt(0) == 0 - // sqrt(1) = 1 and cbrt(1) == 1 - // get number string - const std::string& parameter(tok->strAt(2)); - // is parameter 0 ? - if (isZeroNumber(parameter)) { - tok->deleteNext(3); // delete tokens - tok->str("0"); // insert result into token list - simplifcationMade = true; - } else if (isOneNumber(parameter)) { - tok->deleteNext(3); // delete tokens - tok->str("1"); // insert result into token list - simplifcationMade = true; - } - } else if (Token::Match(tok, "exp|expf|expl|exp2|exp2f|exp2l|cos|cosf|cosl|cosh|coshf|coshl|erfc|erfcf|erfcl ( %num% )")) { - // Simplify: exp[f|l](0) = 1 and exp2[f|l](0) = 1 - // cosh[f|l](0) = 1 and cos[f|l](0) = 1 - // erfc[f|l](0) = 1 - // get number string - const std::string& parameter(tok->strAt(2)); - // is parameter 0 ? - if (isZeroNumber(parameter)) { - tok->deleteNext(3); // delete tokens - tok->str("1"); // insert result into token list - simplifcationMade = true; - } - } else if (Token::Match(tok, "log1p|log1pf|log1pl|sin|sinf|sinl|sinh|sinhf|sinhl|erf|erff|erfl|asin|asinf|asinl|asinh|asinhf|asinhl|tan|tanf|tanl|tanh|tanhf|tanhl|atan|atanf|atanl|atanh|atanhf|atanhl|expm1|expm1f|expm1l ( %num% )")) { - // Simplify: log1p[f|l](0) = 0 and sin[f|l](0) = 0 - // sinh[f|l](0) = 0 and erf[f|l](0) = 0 - // asin[f|l](0) = 0 and sinh[f|l](0) = 0 - // tan[f|l](0) = 0 and tanh[f|l](0) = 0 - // atan[f|l](0) = 0 and atanh[f|l](0)= 0 - // expm1[f|l](0) = 0 - // get number string - const std::string& parameter(tok->strAt(2)); - // is parameter 0 ? - if (isZeroNumber(parameter)) { - tok->deleteNext(3); // delete tokens - tok->str("0"); // insert result into token list - simplifcationMade = true; - } - } else if (Token::Match(tok, "log2|log2f|log2l|log|logf|logl|log10|log10f|log10l|logb|logbf|logbl|acosh|acoshf|acoshl|acos|acosf|acosl|ilogb|ilogbf|ilogbl ( %num% )")) { - // Simplify: log2[f|l](1) = 0 , log10[f|l](1) = 0 - // log[f|l](1) = 0 , logb10[f|l](1) = 0 - // acosh[f|l](1) = 0 , acos[f|l](1) = 0 - // ilogb[f|l](1) = 0 - // get number string - const std::string& parameter(tok->strAt(2)); - // is parameter 1 ? - if (isOneNumber(parameter)) { - tok->deleteNext(3); // delete tokens - tok->str("0"); // insert result into token list - simplifcationMade = true; - } - } else if (Token::Match(tok, "fmin|fminl|fminf ( %num% , %num% )")) { - // @todo if one of the parameters is NaN the other is returned - // e.g. printf ("fmin (NaN, -1.0) = %f\n", fmin(NaN,-1.0)); - // e.g. printf ("fmin (-1.0, NaN) = %f\n", fmin(-1.0,NaN)); - const std::string& strLeftNumber(tok->strAt(2)); - const std::string& strRightNumber(tok->strAt(4)); - const bool isLessEqual = MathLib::isLessEqual(strLeftNumber, strRightNumber); - // case: left <= right ==> insert left - if (isLessEqual) { - tok->str(strLeftNumber); // insert e.g. -1.0 - tok->deleteNext(5); // delete e.g. fmin ( -1.0, 1.0 ) - simplifcationMade = true; - } else { // case left > right ==> insert right - tok->str(strRightNumber); // insert e.g. 0.0 - tok->deleteNext(5); // delete e.g. fmin ( 1.0, 0.0 ) - simplifcationMade = true; - } - } else if (Token::Match(tok, "fmax|fmaxl|fmaxf ( %num% , %num% )")) { - // @todo if one of the parameters is NaN the other is returned - // e.g. printf ("fmax (NaN, -1.0) = %f\n", fmax(NaN,-1.0)); - // e.g. printf ("fmax (-1.0, NaN) = %f\n", fmax(-1.0,NaN)); - const std::string& strLeftNumber(tok->strAt(2)); - const std::string& strRightNumber(tok->strAt(4)); - const bool isLessEqual = MathLib::isLessEqual(strLeftNumber, strRightNumber); - // case: left <= right ==> insert right - if (isLessEqual) { - tok->str(strRightNumber);// insert e.g. 1.0 - tok->deleteNext(5); // delete e.g. fmax ( -1.0, 1.0 ) - simplifcationMade = true; - } else { // case left > right ==> insert left - tok->str(strLeftNumber); // insert e.g. 1.0 - tok->deleteNext(5); // delete e.g. fmax ( 1.0, 0.0 ) - simplifcationMade = true; - } - } else if (Token::Match(tok, "pow|powf|powl (")) { - if (Token::Match(tok->tokAt(2), "%num% , %num% )")) { - // In case of pow ( 0 , anyNumber > 0): It can be simplified to 0 - // In case of pow ( 0 , 0 ): It simplified to 1 - // In case of pow ( 1 , anyNumber ): It simplified to 1 - const std::string& leftNumber(tok->strAt(2)); // get the left parameter - const std::string& rightNumber(tok->strAt(4)); // get the right parameter - const bool isLeftNumberZero = isZeroNumber(leftNumber); - const bool isLeftNumberOne = isOneNumber(leftNumber); - const bool isRightNumberZero = isZeroNumber(rightNumber); - if (isLeftNumberZero && !isRightNumberZero && MathLib::isPositive(rightNumber)) { // case: 0^(y) = 0 and y > 0 - tok->deleteNext(5); // delete tokens - tok->str("0"); // insert simplified result - simplifcationMade = true; - } else if (isLeftNumberZero && isRightNumberZero) { // case: 0^0 = 1 - tok->deleteNext(5); // delete tokens - tok->str("1"); // insert simplified result - simplifcationMade = true; - } else if (isLeftNumberOne) { // case 1^(y) = 1 - tok->deleteNext(5); // delete tokens - tok->str("1"); // insert simplified result - simplifcationMade = true; - } - } - if (Token::Match(tok->tokAt(2), "%any% , %num% )")) { - // In case of pow( x , 1 ): It can be simplified to x. - const std::string& leftParameter(tok->strAt(2)); // get the left parameter - const std::string& rightNumber(tok->strAt(4)); // get right number - if (isOneNumber(rightNumber)) { // case: x^(1) = x - tok->str(leftParameter); // insert simplified result - tok->deleteNext(5); // delete tokens - simplifcationMade = true; - } else if (isZeroNumber(rightNumber)) { // case: x^(0) = 1 - tok->deleteNext(5); // delete tokens - tok->str("1"); // insert simplified result - simplifcationMade = true; - } - } - } - // Jump back to begin of statement if a simplification was performed - if (simplifcationMade) { - while (tok->previous() && tok->str() != ";") { - tok = tok->previous(); - } - } - } - } -} - void Tokenizer::simplifyComma() { bool inReturn = false; diff --git a/lib/tokenize.h b/lib/tokenize.h index 7125a3081..22b1a0dd7 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -547,11 +547,6 @@ public: void findComplicatedSyntaxErrorsInTemplates(); - /** - * Simplify e.g. 'atol("0")' into '0' - */ - void simplifyMathFunctions(); - /** * Simplify e.g. 'sin(0)' into '0' */ @@ -897,13 +892,6 @@ public: return list.front(); } - /** - * Helper function to check whether number is zero (0 or 0.0 or 0E+0) or not? - * @param s the string to check - * @return true in case is is zero and false otherwise. - */ - static bool isZeroNumber(const std::string &s); - /** * Helper function to check whether number is one (1 or 0.1E+1 or 1E+0) or not? * @param s the string to check diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index e0e553df8..7cca6fc34 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -60,36 +60,6 @@ private: TEST_CASE(test1); // array access. replace "*(p+1)" => "p[1]" - TEST_CASE(simplifyMathFunctions_sqrt); - TEST_CASE(simplifyMathFunctions_cbrt); - TEST_CASE(simplifyMathFunctions_exp); - TEST_CASE(simplifyMathFunctions_exp2); - TEST_CASE(simplifyMathFunctions_logb); - TEST_CASE(simplifyMathFunctions_log1p); - TEST_CASE(simplifyMathFunctions_ilogb); - TEST_CASE(simplifyMathFunctions_log10); - TEST_CASE(simplifyMathFunctions_log); - TEST_CASE(simplifyMathFunctions_log2); - TEST_CASE(simplifyMathFunctions_pow); - TEST_CASE(simplifyMathFunctions_fmin); - TEST_CASE(simplifyMathFunctions_fmax); - TEST_CASE(simplifyMathFunctions_acosh); - TEST_CASE(simplifyMathFunctions_acos); - TEST_CASE(simplifyMathFunctions_cosh); - TEST_CASE(simplifyMathFunctions_cos); - TEST_CASE(simplifyMathFunctions_erfc); - TEST_CASE(simplifyMathFunctions_erf); - TEST_CASE(simplifyMathFunctions_sin); - TEST_CASE(simplifyMathFunctions_sinh); - TEST_CASE(simplifyMathFunctions_asin); - TEST_CASE(simplifyMathFunctions_asinh); - TEST_CASE(simplifyMathFunctions_tan); - TEST_CASE(simplifyMathFunctions_tanh); - TEST_CASE(simplifyMathFunctions_atan); - TEST_CASE(simplifyMathFunctions_atanh); - TEST_CASE(simplifyMathFunctions_expm1); - TEST_CASE(simplifyMathExpressions); //ticket #1620 - // foo(p = new char[10]); => p = new char[10]; foo(p); TEST_CASE(simplifyAssignmentInFunctionCall); @@ -188,8 +158,6 @@ private: TEST_CASE(strcat1); TEST_CASE(strcat2); - TEST_CASE(simplifyAtol); - TEST_CASE(simplifyOperator1); TEST_CASE(simplifyOperator2); @@ -4117,13 +4085,6 @@ private: ASSERT_EQUALS(expect, tok(code)); } - void simplifyAtol() { - ASSERT_EQUALS("a = std :: atol ( x ) ;", tok("a = std::atol(x);")); - ASSERT_EQUALS("a = atol ( \"text\" ) ;", tok("a = atol(\"text\");")); - ASSERT_EQUALS("a = 0 ;", tok("a = std::atol(\"0\");")); - ASSERT_EQUALS("a = 10 ;", tok("a = atol(\"0xa\");")); - } - void simplifyOperator1() { // #3237 - error merging namespaces with operators const char code[] = "class c {\n" diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 56ed5fe63..4c2f667f0 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -145,7 +145,6 @@ private: TEST_CASE(simplifyExternC); TEST_CASE(simplifyKeyword); // #5842 - remove C99 static keyword between [] - TEST_CASE(isZeroNumber); TEST_CASE(isOneNumber); TEST_CASE(isTwoNumber); @@ -5628,24 +5627,6 @@ private: ASSERT_EQUALS(expected2, tokenizeAndStringifyWindows(code2, true, Settings::Win32A)); } - void isZeroNumber() const { - ASSERT_EQUALS(true, Tokenizer::isZeroNumber("0.0")); - ASSERT_EQUALS(true, Tokenizer::isZeroNumber("+0.0")); - ASSERT_EQUALS(true, Tokenizer::isZeroNumber("-0.0")); - ASSERT_EQUALS(true, Tokenizer::isZeroNumber("+0L")); - ASSERT_EQUALS(true, Tokenizer::isZeroNumber("+0")); - ASSERT_EQUALS(true, Tokenizer::isZeroNumber("-0")); - ASSERT_EQUALS(true, Tokenizer::isZeroNumber("-0E+0")); - - ASSERT_EQUALS(false, Tokenizer::isZeroNumber("1.0")); - ASSERT_EQUALS(false, Tokenizer::isZeroNumber("+1.0")); - ASSERT_EQUALS(false, Tokenizer::isZeroNumber("-1")); - ASSERT_EQUALS(false, Tokenizer::isZeroNumber("")); - ASSERT_EQUALS(false, Tokenizer::isZeroNumber("garbage")); - ASSERT_EQUALS(false, Tokenizer::isZeroNumber("E2")); - ASSERT_EQUALS(false, Tokenizer::isZeroNumber("2e")); - } - void isOneNumber() const { ASSERT_EQUALS(true, Tokenizer::isOneNumber("1.0")); ASSERT_EQUALS(true, Tokenizer::isOneNumber("+1.0"));