diff --git a/src/token.cpp b/src/token.cpp index 99facfcaf..238610400 100644 --- a/src/token.cpp +++ b/src/token.cpp @@ -69,6 +69,14 @@ void Token::concatStr(std::string const& b) _str.append(b.begin() + 1, b.end()); } +std::string Token::strValue() +{ + assert(_str.length() >= 2); + assert(_str[0] == '"'); + assert(_str[_str.length()-1] == '"'); + return _str.substr(1, _str.length() - 2); +} + void Token::deleteNext() { Token *n = _next; diff --git a/src/token.h b/src/token.h index 4d48d7d80..77265cf60 100644 --- a/src/token.h +++ b/src/token.h @@ -266,6 +266,14 @@ public: **/ static void createMutualLinks(Token *begin, Token *end); + /** + * This can be called only for tokens that are strings, else + * the assert() is called. If Token is e.g. '"hello"', this will return + * 'hello' (removing the double quotes). + * @return String value + */ + std::string strValue(); + private: void next(Token *next) { diff --git a/src/tokenize.cpp b/src/tokenize.cpp index 87884c16f..6e957fb8e 100644 --- a/src/tokenize.cpp +++ b/src/tokenize.cpp @@ -1479,6 +1479,9 @@ void Tokenizer::simplifyTokenList() } } + // Convert e.g. atol("0") into 0 + simplifyMathFunctions(); + // Remove unwanted keywords static const char * const unwantedWords[] = { "unsigned", "unlikely", "likely" }; for (Token *tok = _tokens; tok; tok = tok->next()) @@ -3696,6 +3699,44 @@ void Tokenizer::syntaxError(const Token *tok, char c) } +bool Tokenizer::simplifyMathFunctions() +{ + bool result = false; + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (Token::Match(tok, "atol ( %str% )")) + { + if (!MathLib::isInt(tok->tokAt(2)->strValue())) + { + // Ignore strings which we can't convert + continue; + } + + if (tok->previous() && + Token::simpleMatch(tok->previous()->previous(), "std ::")) + { + // Delete "std ::" + tok = tok->previous()->previous(); + tok->deleteNext(); + tok->deleteThis(); + } + + // Delete atol( + tok->deleteNext(); + tok->deleteThis(); + + // Convert string into a number + tok->str(MathLib::toString(MathLib::toLongNumber(tok->strValue()))); + + // Delete remaining ) + tok->deleteNext(); + result = true; + } + } + + return result; +} + void Tokenizer::simplifyComma() { for (Token *tok = _tokens; tok; tok = tok->next()) diff --git a/src/tokenize.h b/src/tokenize.h index 490792ed2..94eaf91d7 100644 --- a/src/tokenize.h +++ b/src/tokenize.h @@ -279,6 +279,13 @@ private: */ void simplifyTemplates(); + /** + * Simplify e.g. 'atol("0")' into '0' + * @return true if modifications to token-list are done. + * false if no modifications are done. + */ + bool simplifyMathFunctions(); + void insertTokens(Token *dest, const Token *src, unsigned int n); /** diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 8dc487715..b7e0e2c51 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -115,6 +115,8 @@ private: // Syntax error TEST_CASE(argumentsWithSameName) + + TEST_CASE(simplifyAtol) } std::string tok(const char code[]) @@ -1482,6 +1484,14 @@ private: ASSERT_EQUALS("void foo ( int x , y ) int x ; { }", 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\");")); + } }; REGISTER_TEST(TestSimplifyTokens) diff --git a/test/testtoken.cpp b/test/testtoken.cpp index 0ba458634..cb0e2f716 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -35,6 +35,7 @@ private: TEST_CASE(nextprevious); TEST_CASE(multiCompare); TEST_CASE(getStrLength); + TEST_CASE(strValue); } void nextprevious() @@ -96,6 +97,15 @@ private: Tokenizer::deleteTokens(tok); } + void strValue() + { + Token tok; + tok.str("\"\""); + ASSERT_EQUALS(std::string(""), tok.strValue()); + + tok.str("\"0\""); + ASSERT_EQUALS(std::string("0"), tok.strValue()); + } }; REGISTER_TEST(TestTOKEN)