From c3136dbc2a5e6733bffb813f4d1239151744f5d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 31 Aug 2023 23:14:28 +0200 Subject: [PATCH] Refactor: The code to generate id string from pointer can be simplified (#5382) --- lib/symboldatabase.cpp | 46 ++++++++++++++++----------------- lib/token.cpp | 8 +++--- lib/tokenize.cpp | 22 ++++++++-------- lib/utils.h | 53 +++++++++++--------------------------- test/testutils.cpp | 58 +++++++----------------------------------- 5 files changed, 62 insertions(+), 125 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 6ad1915c2..9628dc0c6 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -4043,7 +4043,7 @@ void SymbolDatabase::printXml(std::ostream &out) const for (std::list::const_iterator scope = scopeList.cbegin(); scope != scopeList.cend(); ++scope) { outs += " type); @@ -4055,27 +4055,27 @@ void SymbolDatabase::printXml(std::ostream &out) const } if (scope->bodyStart) { outs += " bodyStart=\""; - outs += ptr_to_string(scope->bodyStart); + outs += id_string(scope->bodyStart); outs += '\"'; } if (scope->bodyEnd) { outs += " bodyEnd=\""; - outs += ptr_to_string(scope->bodyEnd); + outs += id_string(scope->bodyEnd); outs += '\"'; } if (scope->nestedIn) { outs += " nestedIn=\""; - outs += ptr_to_string(scope->nestedIn); + outs += id_string(scope->nestedIn); outs += "\""; } if (scope->function) { outs += " function=\""; - outs += ptr_to_string(scope->function); + outs += id_string(scope->function); outs += "\""; } if (scope->definedType) { outs += " definedType=\""; - outs += ptr_to_string(scope->definedType); + outs += id_string(scope->definedType); outs += "\""; } if (scope->functionList.empty() && scope->varlist.empty()) @@ -4086,11 +4086,11 @@ void SymbolDatabase::printXml(std::ostream &out) const outs += " \n"; for (std::list::const_iterator function = scope->functionList.cbegin(); function != scope->functionList.cend(); ++function) { outs += " token); + outs += id_string(function->token); outs += "\" tokenDef=\""; - outs += ptr_to_string(function->tokenDef); + outs += id_string(function->tokenDef); outs += "\" name=\""; outs += ErrorLogger::toxml(function->name()); outs += '\"'; @@ -4123,7 +4123,7 @@ void SymbolDatabase::printXml(std::ostream &out) const outs += " isAttributeNoreturn=\"true\""; if (const Function* overriddenFunction = function->getOverriddenFunction()) { outs += " overriddenFunction=\""; - outs += ptr_to_string(overriddenFunction); + outs += id_string(overriddenFunction); outs += "\""; } if (function->argCount() == 0U) @@ -4135,7 +4135,7 @@ void SymbolDatabase::printXml(std::ostream &out) const outs += " \n"; variables.insert(arg); } @@ -4148,7 +4148,7 @@ void SymbolDatabase::printXml(std::ostream &out) const outs += " \n"; for (std::list::const_iterator var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var) { outs += " \n"; } outs += " \n"; @@ -4162,9 +4162,9 @@ void SymbolDatabase::printXml(std::ostream &out) const outs += " \n"; for (const Type& type:typeList) { outs += " nameToken()); + outs += id_string(var->nameToken()); outs += '\"'; outs += " typeStartToken=\""; - outs += ptr_to_string(var->typeStartToken()); + outs += id_string(var->typeStartToken()); outs += '\"'; outs += " typeEndToken=\""; - outs += ptr_to_string(var->typeEndToken()); + outs += id_string(var->typeEndToken()); outs += '\"'; outs += " access=\""; outs += accessControlToString(var->mAccess); outs += '\"'; outs += " scope=\""; - outs += ptr_to_string(var->scope()); + outs += id_string(var->scope()); outs += '\"'; if (var->valueType()) { outs += " constness=\""; @@ -7591,7 +7591,7 @@ std::string ValueType::dump() const case CONTAINER: { ret += "valueType-type=\"container\""; ret += " valueType-containerId=\""; - ret += ptr_to_string(container); + ret += id_string(container); ret += "\""; break; } @@ -7674,7 +7674,7 @@ std::string ValueType::dump() const if (typeScope) { ret += " valueType-typeScope=\""; - ret += ptr_to_string(typeScope); + ret += id_string(typeScope); ret += '\"'; } diff --git a/lib/token.cpp b/lib/token.cpp index 0a8524f16..0ad96387d 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -1710,7 +1710,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const continue; if (xml) { outs += " "; outs += '\n'; } @@ -1763,7 +1763,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const break; case ValueFlow::Value::ValueType::TOK: outs += "tokvalue=\""; - outs += ptr_to_string(value.tokvalue); + outs += id_string(value.tokvalue); outs += '\"'; break; case ValueFlow::Value::ValueType::FLOAT: @@ -1801,7 +1801,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const break; case ValueFlow::Value::ValueType::LIFETIME: outs += "lifetime=\""; - outs += ptr_to_string(value.tokvalue); + outs += id_string(value.tokvalue); outs += '\"'; outs += " lifetime-scope=\""; outs += ValueFlow::Value::toString(value.lifetimeScope); @@ -1812,7 +1812,7 @@ void Token::printValueFlow(bool xml, std::ostream &out) const break; case ValueFlow::Value::ValueType::SYMBOLIC: outs += "symbolic=\""; - outs += ptr_to_string(value.tokvalue); + outs += id_string(value.tokvalue); outs += '\"'; outs += " symbolic-delta=\""; outs += std::to_string(value.intvalue); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 81fe6abba..cc4f3cfa0 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5806,7 +5806,7 @@ void Tokenizer::dump(std::ostream &out) const outs += '\n'; for (const Token *tok = list.front(); tok; tok = tok->next()) { outs += " scope()); + outs += id_string(tok->scope()); outs += '\"'; if (tok->isName()) { outs += " type=\"name\""; @@ -5880,7 +5880,7 @@ void Tokenizer::dump(std::ostream &out) const outs += " isAttributeExport=\"true\""; if (tok->link()) { outs += " link=\""; - outs += ptr_to_string(tok->link()); + outs += id_string(tok->link()); outs += '\"'; } if (tok->varId() > 0) { @@ -5895,37 +5895,37 @@ void Tokenizer::dump(std::ostream &out) const } if (tok->variable()) { outs += " variable=\""; - outs += ptr_to_string(tok->variable()); + outs += id_string(tok->variable()); outs += '\"'; } if (tok->function()) { outs += " function=\""; - outs += ptr_to_string(tok->function()); + outs += id_string(tok->function()); outs += '\"'; } if (!tok->values().empty()) { outs += " values=\""; - outs += ptr_to_string(&tok->values()); + outs += id_string(&tok->values()); outs += '\"'; } if (tok->type()) { outs += " type-scope=\""; - outs += ptr_to_string(tok->type()->classScope); + outs += id_string(tok->type()->classScope); outs += '\"'; } if (tok->astParent()) { outs += " astParent=\""; - outs += ptr_to_string(tok->astParent()); + outs += id_string(tok->astParent()); outs += '\"'; } if (tok->astOperand1()) { outs += " astOperand1=\""; - outs += ptr_to_string(tok->astOperand1()); + outs += id_string(tok->astOperand1()); outs += '\"'; } if (tok->astOperand2()) { outs += " astOperand2=\""; - outs += ptr_to_string(tok->astOperand2()); + outs += id_string(tok->astOperand2()); outs += '\"'; } if (!tok->originalName().empty()) { @@ -5963,7 +5963,7 @@ void Tokenizer::dump(std::ostream &out) const outs += '\n'; for (const Library::Container* c: containers) { outs += " arrayLike_indexOp ? "true" : "false"); outs += "\" "; diff --git a/lib/utils.h b/lib/utils.h index 3f53f6fbc..46ee7d698 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -270,34 +270,26 @@ std::size_t getArrayLength(const T (& /*unused*/)[size]) return size; } -/** this is meant as a replacement for when we cannot print a pointer via the stream insertion operator (operator<<) for performance reasons */ -// TODO: should give portable value / only used by Tokenizer::dump() and underlying functions - something deterministic would also help with comparing the output -static inline std::string ptr_to_string(const void* p) +/** + * @brief get id string. i.e. for dump files + * it will be a hexadecimal output. + */ +static inline std::string id_string_i(std::uintptr_t l) { -#if (defined(__APPLE__) && defined(__MACH__)) - if (p == nullptr) - return "0x0"; -#elif !defined(_WIN32) || defined(__MINGW32__) - if (p == nullptr) + if (!l) return "0"; -#endif static constexpr int ptr_size = sizeof(void*); -#if defined(_WIN32) && !defined(__MINGW32__) // two characters of each byte / contains terminating \0 static constexpr int buf_size = (ptr_size * 2) + 1; -#else - // two characters of each byte / contains 0x prefix and contains terminating \0 - static constexpr int buf_size = (ptr_size * 2) + 2 + 1; -#endif + char buf[buf_size]; // needs to be signed so we don't underflow in padding loop - int idx = sizeof(buf) - 1; - buf[idx--] = '\0'; // terminate string + int idx = buf_size - 1; + buf[idx] = '\0'; - uintptr_t l = reinterpret_cast(p); while (l != 0) { char c; @@ -307,34 +299,19 @@ static inline std::string ptr_to_string(const void* p) c = '0' + temp; } else { -#if !defined(_WIN32) || defined(__MINGW32__) // a-f c = 'a' + (temp - 10); -#else - // A-F - c = 'A' + (temp - 10); -#endif } - buf[idx--] = c; // store in reverse order + buf[--idx] = c; // store in reverse order l = l / 16; } -#if defined(_WIN32) && !defined(__MINGW32__) - // pad address with 0 - while (idx >= 0) { - buf[idx--] = '0'; - } + return &buf[idx]; +} - // 000000F0A61FF122 or 0230FB33 - return buf; -#else - // add 0x prefix - buf[idx--] = 'x'; - buf[idx--] = '0'; - - // 0x7ffc5aa334d8 - return &buf[idx+1]; -#endif +static inline std::string id_string(const void* p) +{ + return id_string_i(reinterpret_cast(p)); } static inline std::string bool_to_string(bool b) diff --git a/test/testutils.cpp b/test/testutils.cpp index b4c143441..bdc095f54 100644 --- a/test/testutils.cpp +++ b/test/testutils.cpp @@ -38,7 +38,7 @@ private: TEST_CASE(isStringLiteral); TEST_CASE(isCharLiteral); TEST_CASE(strToInt); - TEST_CASE(ptrToString); + TEST_CASE(id_string); } void isValidGlobPattern() const { @@ -334,55 +334,15 @@ private: } } - void ptrToString() const + void id_string() const { - struct Dummy {}; - // stack address - { - const Dummy d; - const Dummy* const dp = &d; - std::ostringstream oss; - oss << dp; - ASSERT_EQUALS(oss.str(), ptr_to_string(dp)); - } - // highest address - { - // NOLINTNEXTLINE(performance-no-int-to-ptr) - const void* const p = reinterpret_cast(std::numeric_limits::max()); - std::ostringstream oss; - oss << p; - ASSERT_EQUALS(oss.str(), ptr_to_string(p)); - } - // same in-between address - { - const Dummy d; - const Dummy* dp = &d; - dp = dp - ((unsigned long long)dp / 2); - std::ostringstream oss; - oss << dp; - ASSERT_EQUALS(oss.str(), ptr_to_string(dp)); - } - // lowest address - { - // NOLINTNEXTLINE(performance-no-int-to-ptr) - const void* const p = reinterpret_cast(std::numeric_limits::min() + 1); - std::ostringstream oss; - oss << p; - ASSERT_EQUALS(oss.str(), ptr_to_string(p)); - } - // heap address - { - const auto dp = std::unique_ptr(new Dummy); - std::ostringstream oss; - oss << dp.get(); - ASSERT_EQUALS(oss.str(), ptr_to_string(dp.get())); - } - // NULL pointer - { - const Dummy* const dp = nullptr; - std::ostringstream oss; - oss << dp; - ASSERT_EQUALS(oss.str(), ptr_to_string(dp)); + ASSERT_EQUALS("0", id_string_i(0)); + ASSERT_EQUALS("f1", id_string_i(0xF1)); + ASSERT_EQUALS("123", id_string_i(0x123)); + ASSERT_EQUALS("1230", id_string_i(0x1230)); + ASSERT_EQUALS(std::string(8,'f'), id_string_i(0xffffffffU)); + if (sizeof(void*) == 8) { + ASSERT_EQUALS(std::string(16,'f'), id_string_i(~0ULL)); } } };