diff options
Diffstat (limited to 'llvm/lib/Demangle')
-rw-r--r-- | llvm/lib/Demangle/DLangDemangle.cpp | 379 | ||||
-rw-r--r-- | llvm/lib/Demangle/Demangle.cpp | 44 | ||||
-rw-r--r-- | llvm/lib/Demangle/ItaniumDemangle.cpp | 39 | ||||
-rw-r--r-- | llvm/lib/Demangle/MicrosoftDemangle.cpp | 570 | ||||
-rw-r--r-- | llvm/lib/Demangle/MicrosoftDemangleNodes.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Demangle/RustDemangle.cpp | 59 |
6 files changed, 585 insertions, 510 deletions
diff --git a/llvm/lib/Demangle/DLangDemangle.cpp b/llvm/lib/Demangle/DLangDemangle.cpp index b747b0f9cc67..8856302be6dd 100644 --- a/llvm/lib/Demangle/DLangDemangle.cpp +++ b/llvm/lib/Demangle/DLangDemangle.cpp @@ -14,16 +14,17 @@ //===----------------------------------------------------------------------===// #include "llvm/Demangle/Demangle.h" -#include "llvm/Demangle/StringView.h" +#include "llvm/Demangle/StringViewExtras.h" #include "llvm/Demangle/Utility.h" #include <cctype> #include <cstring> #include <limits> +#include <string_view> using namespace llvm; using llvm::itanium_demangle::OutputBuffer; -using llvm::itanium_demangle::StringView; +using llvm::itanium_demangle::starts_with; namespace { @@ -32,7 +33,7 @@ struct Demangler { /// Initialize the information structure we use to pass around information. /// /// \param Mangled String to demangle. - Demangler(const char *Mangled); + Demangler(std::string_view Mangled); /// Extract and demangle the mangled symbol and append it to the output /// string. @@ -52,46 +53,42 @@ private: /// \param Demangled output buffer to write the demangled name. /// \param Mangled mangled symbol to be demangled. /// - /// \return The remaining string on success or nullptr on failure. - /// /// \see https://dlang.org/spec/abi.html#name_mangling . /// \see https://dlang.org/spec/abi.html#MangledName . - const char *parseMangle(OutputBuffer *Demangled, const char *Mangled); + void parseMangle(OutputBuffer *Demangled, std::string_view &Mangled); /// Extract the number from a given string. /// /// \param Mangled string to extract the number. /// \param Ret assigned result value. /// - /// \return The remaining string on success or nullptr on failure. - /// - /// \note A result larger than UINT_MAX is considered a failure. + /// \note Ret larger than UINT_MAX is considered a failure. /// /// \see https://dlang.org/spec/abi.html#Number . - const char *decodeNumber(const char *Mangled, unsigned long &Ret); + void decodeNumber(std::string_view &Mangled, unsigned long &Ret); /// Extract the back reference position from a given string. /// /// \param Mangled string to extract the back reference position. /// \param Ret assigned result value. /// - /// \return the remaining string on success or nullptr on failure. + /// \return true on success, false on error. /// /// \note Ret is always >= 0 on success, and unspecified on failure /// /// \see https://dlang.org/spec/abi.html#back_ref . /// \see https://dlang.org/spec/abi.html#NumberBackRef . - const char *decodeBackrefPos(const char *Mangled, long &Ret); + bool decodeBackrefPos(std::string_view &Mangled, long &Ret); /// Extract the symbol pointed by the back reference form a given string. /// /// \param Mangled string to extract the back reference position. /// \param Ret assigned result value. /// - /// \return the remaining string on success or nullptr on failure. + /// \return true on success, false on error. /// /// \see https://dlang.org/spec/abi.html#back_ref . - const char *decodeBackref(const char *Mangled, const char *&Ret); + bool decodeBackref(std::string_view &Mangled, std::string_view &Ret); /// Extract and demangle backreferenced symbol from a given mangled symbol /// and append it to the output string. @@ -99,22 +96,18 @@ private: /// \param Demangled output buffer to write the demangled name. /// \param Mangled mangled symbol to be demangled. /// - /// \return the remaining string on success or nullptr on failure. - /// /// \see https://dlang.org/spec/abi.html#back_ref . /// \see https://dlang.org/spec/abi.html#IdentifierBackRef . - const char *parseSymbolBackref(OutputBuffer *Demangled, const char *Mangled); + void parseSymbolBackref(OutputBuffer *Demangled, std::string_view &Mangled); /// Extract and demangle backreferenced type from a given mangled symbol /// and append it to the output string. /// /// \param Mangled mangled symbol to be demangled. /// - /// \return the remaining string on success or nullptr on failure. - /// /// \see https://dlang.org/spec/abi.html#back_ref . /// \see https://dlang.org/spec/abi.html#TypeBackRef . - const char *parseTypeBackref(const char *Mangled); + void parseTypeBackref(std::string_view &Mangled); /// Check whether it is the beginning of a symbol name. /// @@ -123,7 +116,7 @@ private: /// \return true on success, false otherwise. /// /// \see https://dlang.org/spec/abi.html#SymbolName . - bool isSymbolName(const char *Mangled); + bool isSymbolName(std::string_view Mangled); /// Extract and demangle an identifier from a given mangled symbol append it /// to the output string. @@ -131,10 +124,8 @@ private: /// \param Demangled Output buffer to write the demangled name. /// \param Mangled Mangled symbol to be demangled. /// - /// \return The remaining string on success or nullptr on failure. - /// /// \see https://dlang.org/spec/abi.html#SymbolName . - const char *parseIdentifier(OutputBuffer *Demangled, const char *Mangled); + void parseIdentifier(OutputBuffer *Demangled, std::string_view &Mangled); /// Extract and demangle the plain identifier from a given mangled symbol and /// prepend/append it to the output string, with a special treatment for some @@ -144,11 +135,9 @@ private: /// \param Mangled Mangled symbol to be demangled. /// \param Len Length of the mangled symbol name. /// - /// \return The remaining string on success or nullptr on failure. - /// /// \see https://dlang.org/spec/abi.html#LName . - const char *parseLName(OutputBuffer *Demangled, const char *Mangled, - unsigned long Len); + void parseLName(OutputBuffer *Demangled, std::string_view &Mangled, + unsigned long Len); /// Extract and demangle the qualified symbol from a given mangled symbol /// append it to the output string. @@ -156,33 +145,38 @@ private: /// \param Demangled Output buffer to write the demangled name. /// \param Mangled Mangled symbol to be demangled. /// - /// \return The remaining string on success or nullptr on failure. - /// /// \see https://dlang.org/spec/abi.html#QualifiedName . - const char *parseQualified(OutputBuffer *Demangled, const char *Mangled); + void parseQualified(OutputBuffer *Demangled, std::string_view &Mangled); /// Extract and demangle a type from a given mangled symbol append it to /// the output string. /// /// \param Mangled mangled symbol to be demangled. /// - /// \return the remaining string on success or nullptr on failure. + /// \return true on success, false on error. /// /// \see https://dlang.org/spec/abi.html#Type . - const char *parseType(const char *Mangled); + bool parseType(std::string_view &Mangled); - /// The string we are demangling. - const char *Str; + /// An immutable view of the string we are demangling. + const std::string_view Str; /// The index of the last back reference. int LastBackref; }; } // namespace -const char *Demangler::decodeNumber(const char *Mangled, unsigned long &Ret) { - // Return nullptr if trying to extract something that isn't a digit. - if (Mangled == nullptr || !std::isdigit(*Mangled)) - return nullptr; +void Demangler::decodeNumber(std::string_view &Mangled, unsigned long &Ret) { + // Clear Mangled if trying to extract something that isn't a digit. + if (Mangled.empty()) { + Mangled = {}; + return; + } + + if (!std::isdigit(Mangled.front())) { + Mangled = {}; + return; + } unsigned long Val = 0; @@ -190,25 +184,29 @@ const char *Demangler::decodeNumber(const char *Mangled, unsigned long &Ret) { unsigned long Digit = Mangled[0] - '0'; // Check for overflow. - if (Val > (std::numeric_limits<unsigned int>::max() - Digit) / 10) - return nullptr; + if (Val > (std::numeric_limits<unsigned int>::max() - Digit) / 10) { + Mangled = {}; + return; + } Val = Val * 10 + Digit; - ++Mangled; - } while (std::isdigit(*Mangled)); + Mangled.remove_prefix(1); + } while (!Mangled.empty() && std::isdigit(Mangled.front())); - if (*Mangled == '\0') - return nullptr; + if (Mangled.empty()) { + Mangled = {}; + return; + } Ret = Val; - return Mangled; } -const char *Demangler::decodeBackrefPos(const char *Mangled, long &Ret) { +bool Demangler::decodeBackrefPos(std::string_view &Mangled, long &Ret) { // Return nullptr if trying to extract something that isn't a digit - if (Mangled == nullptr || !std::isalpha(*Mangled)) - return nullptr; - + if (Mangled.empty()) { + Mangled = {}; + return false; + } // Any identifier or non-basic type that has been emitted to the mangled // symbol before will not be emitted again, but is referenced by a special // sequence encoding the relative position of the original occurrence in the @@ -221,7 +219,7 @@ const char *Demangler::decodeBackrefPos(const char *Mangled, long &Ret) { // ^ unsigned long Val = 0; - while (std::isalpha(*Mangled)) { + while (!Mangled.empty() && std::isalpha(Mangled.front())) { // Check for overflow if (Val > (std::numeric_limits<unsigned long>::max() - 25) / 26) break; @@ -233,116 +231,133 @@ const char *Demangler::decodeBackrefPos(const char *Mangled, long &Ret) { if ((long)Val <= 0) break; Ret = Val; - return Mangled + 1; + Mangled.remove_prefix(1); + return true; } Val += Mangled[0] - 'A'; - ++Mangled; + Mangled.remove_prefix(1); } - return nullptr; + Mangled = {}; + return false; } -const char *Demangler::decodeBackref(const char *Mangled, const char *&Ret) { - assert(Mangled != nullptr && *Mangled == 'Q' && "Invalid back reference!"); - Ret = nullptr; +bool Demangler::decodeBackref(std::string_view &Mangled, + std::string_view &Ret) { + assert(!Mangled.empty() && Mangled.front() == 'Q' && + "Invalid back reference!"); + Ret = {}; // Position of 'Q' - const char *Qpos = Mangled; + const char *Qpos = Mangled.data(); long RefPos; - ++Mangled; + Mangled.remove_prefix(1); - Mangled = decodeBackrefPos(Mangled, RefPos); - if (Mangled == nullptr) - return nullptr; + if (!decodeBackrefPos(Mangled, RefPos)) { + Mangled = {}; + return false; + } - if (RefPos > Qpos - Str) - return nullptr; + if (RefPos > Qpos - Str.data()) { + Mangled = {}; + return false; + } // Set the position of the back reference. Ret = Qpos - RefPos; - return Mangled; + return true; } -const char *Demangler::parseSymbolBackref(OutputBuffer *Demangled, - const char *Mangled) { +void Demangler::parseSymbolBackref(OutputBuffer *Demangled, + std::string_view &Mangled) { // An identifier back reference always points to a digit 0 to 9. // IdentifierBackRef: // Q NumberBackRef // ^ - const char *Backref; unsigned long Len; // Get position of the back reference - Mangled = decodeBackref(Mangled, Backref); + std::string_view Backref; + if (!decodeBackref(Mangled, Backref)) { + Mangled = {}; + return; + } // Must point to a simple identifier - Backref = decodeNumber(Backref, Len); - if (Backref == nullptr || strlen(Backref) < Len) - return nullptr; - - Backref = parseLName(Demangled, Backref, Len); - if (Backref == nullptr) - return nullptr; + decodeNumber(Backref, Len); + if (Backref.empty() || Backref.length() < Len) { + Mangled = {}; + return; + } - return Mangled; + parseLName(Demangled, Backref, Len); + if (Backref.empty()) + Mangled = {}; } -const char *Demangler::parseTypeBackref(const char *Mangled) { +void Demangler::parseTypeBackref(std::string_view &Mangled) { // A type back reference always points to a letter. // TypeBackRef: // Q NumberBackRef // ^ - const char *Backref; // If we appear to be moving backwards through the mangle string, then // bail as this may be a recursive back reference. - if (Mangled - Str >= LastBackref) - return nullptr; + if (Mangled.data() - Str.data() >= LastBackref) { + Mangled = {}; + return; + } int SaveRefPos = LastBackref; - LastBackref = Mangled - Str; + LastBackref = Mangled.data() - Str.data(); // Get position of the back reference. - Mangled = decodeBackref(Mangled, Backref); + std::string_view Backref; + if (!decodeBackref(Mangled, Backref)) { + Mangled = {}; + return; + } // Can't decode back reference. - if (Backref == nullptr) - return nullptr; + if (Backref.empty()) { + Mangled = {}; + return; + } // TODO: Add support for function type back references. - Backref = parseType(Backref); + if (!parseType(Backref)) + Mangled = {}; LastBackref = SaveRefPos; - if (Backref == nullptr) - return nullptr; - - return Mangled; + if (Backref.empty()) + Mangled = {}; } -bool Demangler::isSymbolName(const char *Mangled) { +bool Demangler::isSymbolName(std::string_view Mangled) { long Ret; - const char *Qref = Mangled; + const char *Qref = Mangled.data(); - if (std::isdigit(*Mangled)) + if (std::isdigit(Mangled.front())) return true; // TODO: Handle template instances. - if (*Mangled != 'Q') + if (Mangled.front() != 'Q') return false; - Mangled = decodeBackrefPos(Mangled + 1, Ret); - if (Mangled == nullptr || Ret > Qref - Str) + Mangled.remove_prefix(1); + bool Valid = decodeBackrefPos(Mangled, Ret); + if (!Valid || Ret > Qref - Str.data()) return false; return std::isdigit(Qref[-Ret]); } -const char *Demangler::parseMangle(OutputBuffer *Demangled, - const char *Mangled) { +void Demangler::parseMangle(OutputBuffer *Demangled, + std::string_view &Mangled) { // A D mangled symbol is comprised of both scope and type information. // MangleName: // _D QualifiedName Type @@ -352,24 +367,24 @@ const char *Demangler::parseMangle(OutputBuffer *Demangled, // above location. // Note that type is never a function type, but only the return type of // a function or the type of a variable. - Mangled += 2; + Mangled.remove_prefix(2); - Mangled = parseQualified(Demangled, Mangled); + parseQualified(Demangled, Mangled); - if (Mangled != nullptr) { - // Artificial symbols end with 'Z' and have no type. - if (*Mangled == 'Z') - ++Mangled; - else { - Mangled = parseType(Mangled); - } + if (Mangled.empty()) { + Mangled = {}; + return; } - return Mangled; + // Artificial symbols end with 'Z' and have no type. + if (Mangled.front() == 'Z') { + Mangled.remove_prefix(1); + } else if (!parseType(Mangled)) + Mangled = {}; } -const char *Demangler::parseQualified(OutputBuffer *Demangled, - const char *Mangled) { +void Demangler::parseQualified(OutputBuffer *Demangled, + std::string_view &Mangled) { // Qualified names are identifiers separated by their encoded length. // Nested functions also encode their argument types without specifying // what they return. @@ -388,10 +403,10 @@ const char *Demangler::parseQualified(OutputBuffer *Demangled, size_t NotFirst = false; do { // Skip over anonymous symbols. - if (*Mangled == '0') { + if (!Mangled.empty() && Mangled.front() == '0') { do - ++Mangled; - while (*Mangled == '0'); + Mangled.remove_prefix(1); + while (!Mangled.empty() && Mangled.front() == '0'); continue; } @@ -400,62 +415,63 @@ const char *Demangler::parseQualified(OutputBuffer *Demangled, *Demangled << '.'; NotFirst = true; - Mangled = parseIdentifier(Demangled, Mangled); - - } while (Mangled && isSymbolName(Mangled)); - - return Mangled; + parseIdentifier(Demangled, Mangled); + } while (!Mangled.empty() && isSymbolName(Mangled)); } -const char *Demangler::parseIdentifier(OutputBuffer *Demangled, - const char *Mangled) { - unsigned long Len; - - if (Mangled == nullptr || *Mangled == '\0') - return nullptr; +void Demangler::parseIdentifier(OutputBuffer *Demangled, + std::string_view &Mangled) { + if (Mangled.empty()) { + Mangled = {}; + return; + } - if (*Mangled == 'Q') + if (Mangled.front() == 'Q') return parseSymbolBackref(Demangled, Mangled); // TODO: Parse lengthless template instances. - const char *Endptr = decodeNumber(Mangled, Len); - - if (Endptr == nullptr || Len == 0) - return nullptr; - - if (strlen(Endptr) < Len) - return nullptr; + unsigned long Len; + decodeNumber(Mangled, Len); - Mangled = Endptr; + if (Mangled.empty()) { + Mangled = {}; + return; + } + if (!Len || Mangled.length() < Len) { + Mangled = {}; + return; + } // TODO: Parse template instances with a length prefix. // There can be multiple different declarations in the same function that // have the same mangled name. To make the mangled names unique, a fake // parent in the form `__Sddd' is added to the symbol. - if (Len >= 4 && Mangled[0] == '_' && Mangled[1] == '_' && Mangled[2] == 'S') { - const char *NumPtr = Mangled + 3; - while (NumPtr < (Mangled + Len) && std::isdigit(*NumPtr)) - ++NumPtr; - - if (Mangled + Len == NumPtr) { + if (Len >= 4 && starts_with(Mangled, "__S")) { + const size_t SuffixLen = Mangled.length() - Len; + std::string_view P = Mangled.substr(3); + while (P.length() > SuffixLen && std::isdigit(P.front())) + P.remove_prefix(1); + if (P.length() == SuffixLen) { // Skip over the fake parent. - Mangled += Len; + Mangled.remove_prefix(Len); return parseIdentifier(Demangled, Mangled); } // Else demangle it as a plain identifier. } - return parseLName(Demangled, Mangled, Len); + parseLName(Demangled, Mangled, Len); } -const char *Demangler::parseType(const char *Mangled) { - if (*Mangled == '\0') - return nullptr; +bool Demangler::parseType(std::string_view &Mangled) { + if (Mangled.empty()) { + Mangled = {}; + return false; + } - switch (*Mangled) { + switch (Mangled.front()) { // TODO: Parse type qualifiers. // TODO: Parse function types. // TODO: Parse compound types. @@ -464,99 +480,102 @@ const char *Demangler::parseType(const char *Mangled) { // Basic types. case 'i': - ++Mangled; + Mangled.remove_prefix(1); // TODO: Add type name dumping - return Mangled; + return true; // TODO: Add support for the rest of the basic types. // Back referenced type. - case 'Q': - return parseTypeBackref(Mangled); + case 'Q': { + parseTypeBackref(Mangled); + return true; + } default: // unhandled. - return nullptr; + Mangled = {}; + return false; } } -const char *Demangler::parseLName(OutputBuffer *Demangled, const char *Mangled, - unsigned long Len) { +void Demangler::parseLName(OutputBuffer *Demangled, std::string_view &Mangled, + unsigned long Len) { switch (Len) { case 6: - if (strncmp(Mangled, "__initZ", Len + 1) == 0) { + if (starts_with(Mangled, "__initZ")) { // The static initializer for a given symbol. Demangled->prepend("initializer for "); Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1); - Mangled += Len; - return Mangled; + Mangled.remove_prefix(Len); + return; } - if (strncmp(Mangled, "__vtblZ", Len + 1) == 0) { + if (starts_with(Mangled, "__vtblZ")) { // The vtable symbol for a given class. Demangled->prepend("vtable for "); Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1); - Mangled += Len; - return Mangled; + Mangled.remove_prefix(Len); + return; } break; case 7: - if (strncmp(Mangled, "__ClassZ", Len + 1) == 0) { + if (starts_with(Mangled, "__ClassZ")) { // The classinfo symbol for a given class. Demangled->prepend("ClassInfo for "); Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1); - Mangled += Len; - return Mangled; + Mangled.remove_prefix(Len); + return; } break; case 11: - if (strncmp(Mangled, "__InterfaceZ", Len + 1) == 0) { + if (starts_with(Mangled, "__InterfaceZ")) { // The interface symbol for a given class. Demangled->prepend("Interface for "); Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1); - Mangled += Len; - return Mangled; + Mangled.remove_prefix(Len); + return; } break; case 12: - if (strncmp(Mangled, "__ModuleInfoZ", Len + 1) == 0) { + if (starts_with(Mangled, "__ModuleInfoZ")) { // The ModuleInfo symbol for a given module. Demangled->prepend("ModuleInfo for "); Demangled->setCurrentPosition(Demangled->getCurrentPosition() - 1); - Mangled += Len; - return Mangled; + Mangled.remove_prefix(Len); + return; } break; } - *Demangled << StringView(Mangled, Len); - Mangled += Len; - - return Mangled; + *Demangled << Mangled.substr(0, Len); + Mangled.remove_prefix(Len); } -Demangler::Demangler(const char *Mangled) - : Str(Mangled), LastBackref(strlen(Mangled)) {} +Demangler::Demangler(std::string_view Mangled) + : Str(Mangled), LastBackref(Mangled.length()) {} const char *Demangler::parseMangle(OutputBuffer *Demangled) { - return parseMangle(Demangled, this->Str); + std::string_view M(this->Str); + parseMangle(Demangled, M); + return M.data(); } -char *llvm::dlangDemangle(const char *MangledName) { - if (MangledName == nullptr || strncmp(MangledName, "_D", 2) != 0) +char *llvm::dlangDemangle(std::string_view MangledName) { + if (MangledName.empty() || !starts_with(MangledName, "_D")) return nullptr; OutputBuffer Demangled; - if (strcmp(MangledName, "_Dmain") == 0) { + if (MangledName == "_Dmain") { Demangled << "D main"; } else { - Demangler D = Demangler(MangledName); - MangledName = D.parseMangle(&Demangled); + Demangler D(MangledName); + const char *M = D.parseMangle(&Demangled); // Check that the entire symbol was successfully demangled. - if (MangledName == nullptr || *MangledName != '\0') { + if (M == nullptr || *M != '\0') { std::free(Demangled.getBuffer()); return nullptr; } diff --git a/llvm/lib/Demangle/Demangle.cpp b/llvm/lib/Demangle/Demangle.cpp index 9d128424cabf..f2aa571d685f 100644 --- a/llvm/lib/Demangle/Demangle.cpp +++ b/llvm/lib/Demangle/Demangle.cpp @@ -11,45 +11,45 @@ //===----------------------------------------------------------------------===// #include "llvm/Demangle/Demangle.h" +#include "llvm/Demangle/StringViewExtras.h" #include <cstdlib> -#include <cstring> +#include <string_view> -static bool isItaniumEncoding(const char *S) { - // Itanium encoding requires 1 or 3 leading underscores, followed by 'Z'. - return std::strncmp(S, "_Z", 2) == 0 || std::strncmp(S, "___Z", 4) == 0; -} - -static bool isRustEncoding(const char *S) { return S[0] == '_' && S[1] == 'R'; } - -static bool isDLangEncoding(const std::string &MangledName) { - return MangledName.size() >= 2 && MangledName[0] == '_' && - MangledName[1] == 'D'; -} +using llvm::itanium_demangle::starts_with; -std::string llvm::demangle(const std::string &MangledName) { +std::string llvm::demangle(std::string_view MangledName) { std::string Result; - const char *S = MangledName.c_str(); - if (nonMicrosoftDemangle(S, Result)) + if (nonMicrosoftDemangle(MangledName, Result)) return Result; - if (S[0] == '_' && nonMicrosoftDemangle(S + 1, Result)) + if (starts_with(MangledName, '_') && + nonMicrosoftDemangle(MangledName.substr(1), Result)) return Result; - if (char *Demangled = - microsoftDemangle(S, nullptr, nullptr, nullptr, nullptr)) { + if (char *Demangled = microsoftDemangle(MangledName, nullptr, nullptr)) { Result = Demangled; std::free(Demangled); - return Result; + } else { + Result = MangledName; } + return Result; +} - return MangledName; +static bool isItaniumEncoding(std::string_view S) { + // Itanium encoding requires 1 or 3 leading underscores, followed by 'Z'. + return starts_with(S, "_Z") || starts_with(S, "___Z"); } -bool llvm::nonMicrosoftDemangle(const char *MangledName, std::string &Result) { +static bool isRustEncoding(std::string_view S) { return starts_with(S, "_R"); } + +static bool isDLangEncoding(std::string_view S) { return starts_with(S, "_D"); } + +bool llvm::nonMicrosoftDemangle(std::string_view MangledName, + std::string &Result) { char *Demangled = nullptr; if (isItaniumEncoding(MangledName)) - Demangled = itaniumDemangle(MangledName, nullptr, nullptr, nullptr); + Demangled = itaniumDemangle(MangledName); else if (isRustEncoding(MangledName)) Demangled = rustDemangle(MangledName); else if (isDLangEncoding(MangledName)) diff --git a/llvm/lib/Demangle/ItaniumDemangle.cpp b/llvm/lib/Demangle/ItaniumDemangle.cpp index 9b646ea800aa..e3f208f0adf8 100644 --- a/llvm/lib/Demangle/ItaniumDemangle.cpp +++ b/llvm/lib/Demangle/ItaniumDemangle.cpp @@ -18,6 +18,7 @@ #include <cstdio> #include <cstdlib> #include <cstring> +#include <exception> #include <functional> #include <utility> @@ -78,8 +79,8 @@ struct DumpVisitor { } void printStr(const char *S) { fprintf(stderr, "%s", S); } - void print(StringView SV) { - fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin()); + void print(std::string_view SV) { + fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.data()); } void print(const Node *N) { if (N) @@ -365,33 +366,21 @@ public: using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>; -char *llvm::itaniumDemangle(const char *MangledName, char *Buf, - size_t *N, int *Status) { - if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) { - if (Status) - *Status = demangle_invalid_args; +char *llvm::itaniumDemangle(std::string_view MangledName) { + if (MangledName.empty()) return nullptr; - } - int InternalStatus = demangle_success; - Demangler Parser(MangledName, MangledName + std::strlen(MangledName)); + Demangler Parser(MangledName.data(), + MangledName.data() + MangledName.length()); Node *AST = Parser.parse(); + if (!AST) + return nullptr; - if (AST == nullptr) - InternalStatus = demangle_invalid_mangled_name; - else { - OutputBuffer OB(Buf, N); - assert(Parser.ForwardTemplateRefs.empty()); - AST->print(OB); - OB += '\0'; - if (N != nullptr) - *N = OB.getCurrentPosition(); - Buf = OB.getBuffer(); - } - - if (Status) - *Status = InternalStatus; - return InternalStatus == demangle_success ? Buf : nullptr; + OutputBuffer OB; + assert(Parser.ForwardTemplateRefs.empty()); + AST->print(OB); + OB += '\0'; + return OB.getBuffer(); } ItaniumPartialDemangler::ItaniumPartialDemangler() diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index c21b0a30105e..cd7ff40d63a4 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -14,34 +14,50 @@ //===----------------------------------------------------------------------===// #include "llvm/Demangle/MicrosoftDemangle.h" -#include "llvm/Demangle/Demangle.h" -#include "llvm/Demangle/MicrosoftDemangleNodes.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/Demangle/DemangleConfig.h" -#include "llvm/Demangle/StringView.h" +#include "llvm/Demangle/MicrosoftDemangleNodes.h" +#include "llvm/Demangle/StringViewExtras.h" #include "llvm/Demangle/Utility.h" #include <array> #include <cctype> #include <cstdio> +#include <string_view> #include <tuple> using namespace llvm; using namespace ms_demangle; -static bool startsWithDigit(StringView S) { +static bool startsWithDigit(std::string_view S) { return !S.empty() && std::isdigit(S.front()); } - struct NodeList { Node *N = nullptr; NodeList *Next = nullptr; }; -static bool isMemberPointer(StringView MangledName, bool &Error) { +static bool consumeFront(std::string_view &S, char C) { + if (!llvm::itanium_demangle::starts_with(S, C)) + return false; + S.remove_prefix(1); + return true; +} + +static bool consumeFront(std::string_view &S, std::string_view C) { + if (!llvm::itanium_demangle::starts_with(S, C)) + return false; + S.remove_prefix(C.size()); + return true; +} + +static bool isMemberPointer(std::string_view MangledName, bool &Error) { Error = false; - switch (MangledName.popFront()) { + const char F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { case '$': // This is probably an rvalue reference (e.g. $$Q), and you cannot have an // rvalue reference to a member. @@ -75,9 +91,9 @@ static bool isMemberPointer(StringView MangledName, bool &Error) { // Remove ext qualifiers since those can appear on either type and are // therefore not indicative. - MangledName.consumeFront('E'); // 64-bit - MangledName.consumeFront('I'); // restrict - MangledName.consumeFront('F'); // unaligned + consumeFront(MangledName, 'E'); // 64-bit + consumeFront(MangledName, 'I'); // restrict + consumeFront(MangledName, 'F'); // unaligned if (MangledName.empty()) { Error = true; @@ -103,50 +119,50 @@ static bool isMemberPointer(StringView MangledName, bool &Error) { } static SpecialIntrinsicKind -consumeSpecialIntrinsicKind(StringView &MangledName) { - if (MangledName.consumeFront("?_7")) +consumeSpecialIntrinsicKind(std::string_view &MangledName) { + if (consumeFront(MangledName, "?_7")) return SpecialIntrinsicKind::Vftable; - if (MangledName.consumeFront("?_8")) + if (consumeFront(MangledName, "?_8")) return SpecialIntrinsicKind::Vbtable; - if (MangledName.consumeFront("?_9")) + if (consumeFront(MangledName, "?_9")) return SpecialIntrinsicKind::VcallThunk; - if (MangledName.consumeFront("?_A")) + if (consumeFront(MangledName, "?_A")) return SpecialIntrinsicKind::Typeof; - if (MangledName.consumeFront("?_B")) + if (consumeFront(MangledName, "?_B")) return SpecialIntrinsicKind::LocalStaticGuard; - if (MangledName.consumeFront("?_C")) + if (consumeFront(MangledName, "?_C")) return SpecialIntrinsicKind::StringLiteralSymbol; - if (MangledName.consumeFront("?_P")) + if (consumeFront(MangledName, "?_P")) return SpecialIntrinsicKind::UdtReturning; - if (MangledName.consumeFront("?_R0")) + if (consumeFront(MangledName, "?_R0")) return SpecialIntrinsicKind::RttiTypeDescriptor; - if (MangledName.consumeFront("?_R1")) + if (consumeFront(MangledName, "?_R1")) return SpecialIntrinsicKind::RttiBaseClassDescriptor; - if (MangledName.consumeFront("?_R2")) + if (consumeFront(MangledName, "?_R2")) return SpecialIntrinsicKind::RttiBaseClassArray; - if (MangledName.consumeFront("?_R3")) + if (consumeFront(MangledName, "?_R3")) return SpecialIntrinsicKind::RttiClassHierarchyDescriptor; - if (MangledName.consumeFront("?_R4")) + if (consumeFront(MangledName, "?_R4")) return SpecialIntrinsicKind::RttiCompleteObjLocator; - if (MangledName.consumeFront("?_S")) + if (consumeFront(MangledName, "?_S")) return SpecialIntrinsicKind::LocalVftable; - if (MangledName.consumeFront("?__E")) + if (consumeFront(MangledName, "?__E")) return SpecialIntrinsicKind::DynamicInitializer; - if (MangledName.consumeFront("?__F")) + if (consumeFront(MangledName, "?__F")) return SpecialIntrinsicKind::DynamicAtexitDestructor; - if (MangledName.consumeFront("?__J")) + if (consumeFront(MangledName, "?__J")) return SpecialIntrinsicKind::LocalStaticThreadGuard; return SpecialIntrinsicKind::None; } -static bool startsWithLocalScopePattern(StringView S) { - if (!S.consumeFront('?')) +static bool startsWithLocalScopePattern(std::string_view S) { + if (!consumeFront(S, '?')) return false; size_t End = S.find('?'); - if (End == StringView::npos) + if (End == std::string_view::npos) return false; - StringView Candidate = S.substr(0, End); + std::string_view Candidate = S.substr(0, End); if (Candidate.empty()) return false; @@ -158,7 +174,7 @@ static bool startsWithLocalScopePattern(StringView S) { // If it's not 0-9, then it's an encoded number terminated with an @ if (Candidate.back() != '@') return false; - Candidate = Candidate.dropBack(); + Candidate.remove_suffix(1); // An encoded number starts with B-P and all subsequent digits are in A-P. // Note that the reason the first digit cannot be A is two fold. First, it @@ -168,17 +184,17 @@ static bool startsWithLocalScopePattern(StringView S) { // ambiguity is also why single digit encoded numbers use 0-9 rather than A-J. if (Candidate[0] < 'B' || Candidate[0] > 'P') return false; - Candidate = Candidate.dropFront(); + Candidate.remove_prefix(1); while (!Candidate.empty()) { if (Candidate[0] < 'A' || Candidate[0] > 'P') return false; - Candidate = Candidate.dropFront(); + Candidate.remove_prefix(1); } return true; } -static bool isTagType(StringView S) { +static bool isTagType(std::string_view S) { switch (S.front()) { case 'T': // union case 'U': // struct @@ -189,10 +205,10 @@ static bool isTagType(StringView S) { return false; } -static bool isCustomType(StringView S) { return S[0] == '?'; } +static bool isCustomType(std::string_view S) { return S[0] == '?'; } -static bool isPointerType(StringView S) { - if (S.startsWith("$$Q")) // foo && +static bool isPointerType(std::string_view S) { + if (llvm::itanium_demangle::starts_with(S, "$$Q")) // foo && return true; switch (S.front()) { @@ -206,27 +222,30 @@ static bool isPointerType(StringView S) { return false; } -static bool isArrayType(StringView S) { return S[0] == 'Y'; } +static bool isArrayType(std::string_view S) { return S[0] == 'Y'; } -static bool isFunctionType(StringView S) { - return S.startsWith("$$A8@@") || S.startsWith("$$A6"); +static bool isFunctionType(std::string_view S) { + return llvm::itanium_demangle::starts_with(S, "$$A8@@") || + llvm::itanium_demangle::starts_with(S, "$$A6"); } static FunctionRefQualifier -demangleFunctionRefQualifier(StringView &MangledName) { - if (MangledName.consumeFront('G')) +demangleFunctionRefQualifier(std::string_view &MangledName) { + if (consumeFront(MangledName, 'G')) return FunctionRefQualifier::Reference; - else if (MangledName.consumeFront('H')) + else if (consumeFront(MangledName, 'H')) return FunctionRefQualifier::RValueReference; return FunctionRefQualifier::None; } static std::pair<Qualifiers, PointerAffinity> -demanglePointerCVQualifiers(StringView &MangledName) { - if (MangledName.consumeFront("$$Q")) +demanglePointerCVQualifiers(std::string_view &MangledName) { + if (consumeFront(MangledName, "$$Q")) return std::make_pair(Q_None, PointerAffinity::RValueReference); - switch (MangledName.popFront()) { + const char F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { case 'A': return std::make_pair(Q_None, PointerAffinity::Reference); case 'P': @@ -244,18 +263,18 @@ demanglePointerCVQualifiers(StringView &MangledName) { DEMANGLE_UNREACHABLE; } -StringView Demangler::copyString(StringView Borrowed) { +std::string_view Demangler::copyString(std::string_view Borrowed) { char *Stable = Arena.allocUnalignedBuffer(Borrowed.size()); // This is not a micro-optimization, it avoids UB, should Borrowed be an null // buffer. if (Borrowed.size()) - std::memcpy(Stable, Borrowed.begin(), Borrowed.size()); + std::memcpy(Stable, Borrowed.data(), Borrowed.size()); return {Stable, Borrowed.size()}; } SpecialTableSymbolNode * -Demangler::demangleSpecialTableSymbolNode(StringView &MangledName, +Demangler::demangleSpecialTableSymbolNode(std::string_view &MangledName, SpecialIntrinsicKind K) { NamedIdentifierNode *NI = Arena.alloc<NamedIdentifierNode>(); switch (K) { @@ -282,20 +301,22 @@ Demangler::demangleSpecialTableSymbolNode(StringView &MangledName, Error = true; return nullptr; } - char Front = MangledName.popFront(); + char Front = MangledName.front(); + MangledName.remove_prefix(1); if (Front != '6' && Front != '7') { Error = true; return nullptr; } std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName); - if (!MangledName.consumeFront('@')) + if (!consumeFront(MangledName, '@')) STSN->TargetName = demangleFullyQualifiedTypeName(MangledName); return STSN; } LocalStaticGuardVariableNode * -Demangler::demangleLocalStaticGuard(StringView &MangledName, bool IsThread) { +Demangler::demangleLocalStaticGuard(std::string_view &MangledName, + bool IsThread) { LocalStaticGuardIdentifierNode *LSGI = Arena.alloc<LocalStaticGuardIdentifierNode>(); LSGI->IsThread = IsThread; @@ -304,9 +325,9 @@ Demangler::demangleLocalStaticGuard(StringView &MangledName, bool IsThread) { Arena.alloc<LocalStaticGuardVariableNode>(); LSGVN->Name = QN; - if (MangledName.consumeFront("4IA")) + if (consumeFront(MangledName, "4IA")) LSGVN->IsVisible = false; - else if (MangledName.consumeFront("5")) + else if (consumeFront(MangledName, "5")) LSGVN->IsVisible = true; else { Error = true; @@ -319,7 +340,7 @@ Demangler::demangleLocalStaticGuard(StringView &MangledName, bool IsThread) { } static NamedIdentifierNode *synthesizeNamedIdentifier(ArenaAllocator &Arena, - StringView Name) { + std::string_view Name) { NamedIdentifierNode *Id = Arena.alloc<NamedIdentifierNode>(); Id->Name = Name; return Id; @@ -336,27 +357,29 @@ static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena, } static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena, - StringView Name) { + std::string_view Name) { NamedIdentifierNode *Id = synthesizeNamedIdentifier(Arena, Name); return synthesizeQualifiedName(Arena, Id); } static VariableSymbolNode *synthesizeVariable(ArenaAllocator &Arena, TypeNode *Type, - StringView VariableName) { + std::string_view VariableName) { VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); VSN->Type = Type; VSN->Name = synthesizeQualifiedName(Arena, VariableName); return VSN; } -VariableSymbolNode *Demangler::demangleUntypedVariable( - ArenaAllocator &Arena, StringView &MangledName, StringView VariableName) { +VariableSymbolNode * +Demangler::demangleUntypedVariable(ArenaAllocator &Arena, + std::string_view &MangledName, + std::string_view VariableName) { NamedIdentifierNode *NI = synthesizeNamedIdentifier(Arena, VariableName); QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI); VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); VSN->Name = QN; - if (MangledName.consumeFront("8")) + if (consumeFront(MangledName, "8")) return VSN; Error = true; @@ -365,7 +388,7 @@ VariableSymbolNode *Demangler::demangleUntypedVariable( VariableSymbolNode * Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena, - StringView &MangledName) { + std::string_view &MangledName) { RttiBaseClassDescriptorNode *RBCDN = Arena.alloc<RttiBaseClassDescriptorNode>(); RBCDN->NVOffset = demangleUnsigned(MangledName); @@ -377,18 +400,19 @@ Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena, VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); VSN->Name = demangleNameScopeChain(MangledName, RBCDN); - MangledName.consumeFront('8'); + consumeFront(MangledName, '8'); return VSN; } -FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName, - bool IsDestructor) { +FunctionSymbolNode * +Demangler::demangleInitFiniStub(std::string_view &MangledName, + bool IsDestructor) { DynamicStructorIdentifierNode *DSIN = Arena.alloc<DynamicStructorIdentifierNode>(); DSIN->IsDestructor = IsDestructor; bool IsKnownStaticDataMember = false; - if (MangledName.consumeFront('?')) + if (consumeFront(MangledName, '?')) IsKnownStaticDataMember = true; SymbolNode *Symbol = demangleDeclarator(MangledName); @@ -406,7 +430,7 @@ FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName, // both cases. int AtCount = IsKnownStaticDataMember ? 2 : 1; for (int I = 0; I < AtCount; ++I) { - if (MangledName.consumeFront('@')) + if (consumeFront(MangledName, '@')) continue; Error = true; return nullptr; @@ -430,7 +454,7 @@ FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName, return FSN; } -SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) { +SymbolNode *Demangler::demangleSpecialIntrinsic(std::string_view &MangledName) { SpecialIntrinsicKind SIK = consumeSpecialIntrinsicKind(MangledName); switch (SIK) { @@ -453,7 +477,7 @@ SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) { TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result); if (Error) break; - if (!MangledName.consumeFront("@8")) + if (!consumeFront(MangledName, "@8")) break; if (!MangledName.empty()) break; @@ -484,18 +508,18 @@ SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) { } IdentifierNode * -Demangler::demangleFunctionIdentifierCode(StringView &MangledName) { - assert(MangledName.startsWith('?')); - MangledName = MangledName.dropFront(); +Demangler::demangleFunctionIdentifierCode(std::string_view &MangledName) { + assert(llvm::itanium_demangle::starts_with(MangledName, '?')); + MangledName.remove_prefix(1); if (MangledName.empty()) { Error = true; return nullptr; } - if (MangledName.consumeFront("__")) + if (consumeFront(MangledName, "__")) return demangleFunctionIdentifierCode( MangledName, FunctionIdentifierCodeGroup::DoubleUnder); - if (MangledName.consumeFront("_")) + if (consumeFront(MangledName, "_")) return demangleFunctionIdentifierCode(MangledName, FunctionIdentifierCodeGroup::Under); return demangleFunctionIdentifierCode(MangledName, @@ -503,7 +527,7 @@ Demangler::demangleFunctionIdentifierCode(StringView &MangledName) { } StructorIdentifierNode * -Demangler::demangleStructorIdentifier(StringView &MangledName, +Demangler::demangleStructorIdentifier(std::string_view &MangledName, bool IsDestructor) { StructorIdentifierNode *N = Arena.alloc<StructorIdentifierNode>(); N->IsDestructor = IsDestructor; @@ -511,14 +535,14 @@ Demangler::demangleStructorIdentifier(StringView &MangledName, } ConversionOperatorIdentifierNode * -Demangler::demangleConversionOperatorIdentifier(StringView &MangledName) { +Demangler::demangleConversionOperatorIdentifier(std::string_view &MangledName) { ConversionOperatorIdentifierNode *N = Arena.alloc<ConversionOperatorIdentifierNode>(); return N; } LiteralOperatorIdentifierNode * -Demangler::demangleLiteralOperatorIdentifier(StringView &MangledName) { +Demangler::demangleLiteralOperatorIdentifier(std::string_view &MangledName) { LiteralOperatorIdentifierNode *N = Arena.alloc<LiteralOperatorIdentifierNode>(); N->Name = demangleSimpleString(MangledName, /*Memorize=*/false); @@ -666,15 +690,17 @@ Demangler::translateIntrinsicFunctionCode(char CH, } IdentifierNode * -Demangler::demangleFunctionIdentifierCode(StringView &MangledName, +Demangler::demangleFunctionIdentifierCode(std::string_view &MangledName, FunctionIdentifierCodeGroup Group) { if (MangledName.empty()) { Error = true; return nullptr; } + const char CH = MangledName.front(); switch (Group) { case FunctionIdentifierCodeGroup::Basic: - switch (char CH = MangledName.popFront()) { + MangledName.remove_prefix(1); + switch (CH) { case '0': case '1': return demangleStructorIdentifier(MangledName, CH == '1'); @@ -685,10 +711,12 @@ Demangler::demangleFunctionIdentifierCode(StringView &MangledName, translateIntrinsicFunctionCode(CH, Group)); } case FunctionIdentifierCodeGroup::Under: + MangledName.remove_prefix(1); return Arena.alloc<IntrinsicFunctionIdentifierNode>( - translateIntrinsicFunctionCode(MangledName.popFront(), Group)); + translateIntrinsicFunctionCode(CH, Group)); case FunctionIdentifierCodeGroup::DoubleUnder: - switch (char CH = MangledName.popFront()) { + MangledName.remove_prefix(1); + switch (CH) { case 'K': return demangleLiteralOperatorIdentifier(MangledName); default: @@ -700,7 +728,7 @@ Demangler::demangleFunctionIdentifierCode(StringView &MangledName, DEMANGLE_UNREACHABLE; } -SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName, +SymbolNode *Demangler::demangleEncodedSymbol(std::string_view &MangledName, QualifiedNameNode *Name) { if (MangledName.empty()) { Error = true; @@ -730,7 +758,7 @@ SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName, return FSN; } -SymbolNode *Demangler::demangleDeclarator(StringView &MangledName) { +SymbolNode *Demangler::demangleDeclarator(std::string_view &MangledName) { // What follows is a main symbol name. This may include namespaces or class // back references. QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName); @@ -754,18 +782,19 @@ SymbolNode *Demangler::demangleDeclarator(StringView &MangledName) { return Symbol; } -SymbolNode *Demangler::demangleMD5Name(StringView &MangledName) { - assert(MangledName.startsWith("??@")); +SymbolNode *Demangler::demangleMD5Name(std::string_view &MangledName) { + assert(llvm::itanium_demangle::starts_with(MangledName, "??@")); // This is an MD5 mangled name. We can't demangle it, just return the // mangled name. // An MD5 mangled name is ??@ followed by 32 characters and a terminating @. size_t MD5Last = MangledName.find('@', strlen("??@")); - if (MD5Last == StringView::npos) { + if (MD5Last == std::string_view::npos) { Error = true; return nullptr; } - const char *Start = MangledName.begin(); - MangledName = MangledName.dropFront(MD5Last + 1); + const char *Start = MangledName.data(); + const size_t StartSize = MangledName.size(); + MangledName.remove_prefix(MD5Last + 1); // There are two additional special cases for MD5 names: // 1. For complete object locators where the object name is long enough @@ -777,18 +806,20 @@ SymbolNode *Demangler::demangleMD5Name(StringView &MangledName) { // instead of_CT??@...@8 with just one MD5 name. Since we don't yet // demangle catchable types anywhere, this isn't handled for MD5 names // either. - MangledName.consumeFront("??_R4@"); + consumeFront(MangledName, "??_R4@"); - StringView MD5(Start, MangledName.begin()); + assert(MangledName.size() < StartSize); + const size_t Count = StartSize - MangledName.size(); + std::string_view MD5(Start, Count); SymbolNode *S = Arena.alloc<SymbolNode>(NodeKind::Md5Symbol); S->Name = synthesizeQualifiedName(Arena, MD5); return S; } -SymbolNode *Demangler::demangleTypeinfoName(StringView &MangledName) { - assert(MangledName.startsWith('.')); - MangledName.consumeFront('.'); +SymbolNode *Demangler::demangleTypeinfoName(std::string_view &MangledName) { + assert(llvm::itanium_demangle::starts_with(MangledName, '.')); + consumeFront(MangledName, '.'); TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result); if (Error || !MangledName.empty()) { @@ -799,23 +830,23 @@ SymbolNode *Demangler::demangleTypeinfoName(StringView &MangledName) { } // Parser entry point. -SymbolNode *Demangler::parse(StringView &MangledName) { +SymbolNode *Demangler::parse(std::string_view &MangledName) { // Typeinfo names are strings stored in RTTI data. They're not symbol names. // It's still useful to demangle them. They're the only demangled entity // that doesn't start with a "?" but a ".". - if (MangledName.startsWith('.')) + if (llvm::itanium_demangle::starts_with(MangledName, '.')) return demangleTypeinfoName(MangledName); - if (MangledName.startsWith("??@")) + if (llvm::itanium_demangle::starts_with(MangledName, "??@")) return demangleMD5Name(MangledName); // MSVC-style mangled symbols must start with '?'. - if (!MangledName.startsWith('?')) { + if (!llvm::itanium_demangle::starts_with(MangledName, '?')) { Error = true; return nullptr; } - MangledName.consumeFront('?'); + consumeFront(MangledName, '?'); // ?$ is a template instantiation, but all other names that start with ? are // operators / special names. @@ -825,12 +856,12 @@ SymbolNode *Demangler::parse(StringView &MangledName) { return demangleDeclarator(MangledName); } -TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) { - if (!MangledName.consumeFront(".?A")) { +TagTypeNode *Demangler::parseTagUniqueName(std::string_view &MangledName) { + if (!consumeFront(MangledName, ".?A")) { Error = true; return nullptr; } - MangledName.consumeFront(".?A"); + consumeFront(MangledName, ".?A"); if (MangledName.empty()) { Error = true; return nullptr; @@ -846,8 +877,9 @@ TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) { // ::= 3 # global // ::= 4 # static local -VariableSymbolNode *Demangler::demangleVariableEncoding(StringView &MangledName, - StorageClass SC) { +VariableSymbolNode * +Demangler::demangleVariableEncoding(std::string_view &MangledName, + StorageClass SC) { VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>(); VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop); @@ -897,12 +929,13 @@ VariableSymbolNode *Demangler::demangleVariableEncoding(StringView &MangledName, // ::= <hex digit>+ @ # when Number == 0 or >= 10 // // <hex-digit> ::= [A-P] # A = 0, B = 1, ... -std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) { - bool IsNegative = MangledName.consumeFront('?'); +std::pair<uint64_t, bool> +Demangler::demangleNumber(std::string_view &MangledName) { + bool IsNegative = consumeFront(MangledName, '?'); if (startsWithDigit(MangledName)) { uint64_t Ret = MangledName[0] - '0' + 1; - MangledName = MangledName.dropFront(1); + MangledName.remove_prefix(1); return {Ret, IsNegative}; } @@ -910,7 +943,7 @@ std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) { for (size_t i = 0; i < MangledName.size(); ++i) { char C = MangledName[i]; if (C == '@') { - MangledName = MangledName.dropFront(i + 1); + MangledName.remove_prefix(i + 1); return {Ret, IsNegative}; } if ('A' <= C && C <= 'P') { @@ -924,7 +957,7 @@ std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) { return {0ULL, false}; } -uint64_t Demangler::demangleUnsigned(StringView &MangledName) { +uint64_t Demangler::demangleUnsigned(std::string_view &MangledName) { bool IsNegative = false; uint64_t Number = 0; std::tie(Number, IsNegative) = demangleNumber(MangledName); @@ -933,7 +966,7 @@ uint64_t Demangler::demangleUnsigned(StringView &MangledName) { return Number; } -int64_t Demangler::demangleSigned(StringView &MangledName) { +int64_t Demangler::demangleSigned(std::string_view &MangledName) { bool IsNegative = false; uint64_t Number = 0; std::tie(Number, IsNegative) = demangleNumber(MangledName); @@ -945,7 +978,7 @@ int64_t Demangler::demangleSigned(StringView &MangledName) { // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9. // Memorize it. -void Demangler::memorizeString(StringView S) { +void Demangler::memorizeString(std::string_view S) { if (Backrefs.NamesCount >= BackrefContext::Max) return; for (size_t i = 0; i < Backrefs.NamesCount; ++i) @@ -956,7 +989,8 @@ void Demangler::memorizeString(StringView S) { Backrefs.Names[Backrefs.NamesCount++] = N; } -NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) { +NamedIdentifierNode * +Demangler::demangleBackRefName(std::string_view &MangledName) { assert(startsWithDigit(MangledName)); size_t I = MangledName[0] - '0'; @@ -965,7 +999,7 @@ NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) { return nullptr; } - MangledName = MangledName.dropFront(); + MangledName.remove_prefix(1); return Backrefs.Names[I]; } @@ -974,16 +1008,16 @@ void Demangler::memorizeIdentifier(IdentifierNode *Identifier) { // memorize it for the purpose of back-referencing. OutputBuffer OB; Identifier->output(OB, OF_Default); - StringView Owned = copyString(OB); + std::string_view Owned = copyString(OB); memorizeString(Owned); std::free(OB.getBuffer()); } IdentifierNode * -Demangler::demangleTemplateInstantiationName(StringView &MangledName, +Demangler::demangleTemplateInstantiationName(std::string_view &MangledName, NameBackrefBehavior NBB) { - assert(MangledName.startsWith("?$")); - MangledName.consumeFront("?$"); + assert(llvm::itanium_demangle::starts_with(MangledName, "?$")); + consumeFront(MangledName, "?$"); BackrefContext OuterContext; std::swap(OuterContext, Backrefs); @@ -1013,9 +1047,9 @@ Demangler::demangleTemplateInstantiationName(StringView &MangledName, return Identifier; } -NamedIdentifierNode *Demangler::demangleSimpleName(StringView &MangledName, - bool Memorize) { - StringView S = demangleSimpleString(MangledName, Memorize); +NamedIdentifierNode * +Demangler::demangleSimpleName(std::string_view &MangledName, bool Memorize) { + std::string_view S = demangleSimpleString(MangledName, Memorize); if (Error) return nullptr; @@ -1031,33 +1065,36 @@ static uint8_t rebasedHexDigitToNumber(char C) { return (C <= 'J') ? (C - 'A') : (10 + C - 'K'); } -uint8_t Demangler::demangleCharLiteral(StringView &MangledName) { +uint8_t Demangler::demangleCharLiteral(std::string_view &MangledName) { assert(!MangledName.empty()); - if (!MangledName.startsWith('?')) - return MangledName.popFront(); + if (!llvm::itanium_demangle::starts_with(MangledName, '?')) { + const uint8_t F = MangledName.front(); + MangledName.remove_prefix(1); + return F; + } - MangledName = MangledName.dropFront(); + MangledName.remove_prefix(1); if (MangledName.empty()) goto CharLiteralError; - if (MangledName.consumeFront('$')) { + if (consumeFront(MangledName, '$')) { // Two hex digits if (MangledName.size() < 2) goto CharLiteralError; - StringView Nibbles = MangledName.substr(0, 2); + std::string_view Nibbles = MangledName.substr(0, 2); if (!isRebasedHexDigit(Nibbles[0]) || !isRebasedHexDigit(Nibbles[1])) goto CharLiteralError; // Don't append the null terminator. uint8_t C1 = rebasedHexDigitToNumber(Nibbles[0]); uint8_t C2 = rebasedHexDigitToNumber(Nibbles[1]); - MangledName = MangledName.dropFront(2); + MangledName.remove_prefix(2); return (C1 << 4) | C2; } if (startsWithDigit(MangledName)) { const char *Lookup = ",/\\:. \n\t'-"; char C = Lookup[MangledName[0] - '0']; - MangledName = MangledName.dropFront(); + MangledName.remove_prefix(1); return C; } @@ -1067,7 +1104,7 @@ uint8_t Demangler::demangleCharLiteral(StringView &MangledName) { '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5', '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'}; char C = Lookup[MangledName[0] - 'a']; - MangledName = MangledName.dropFront(); + MangledName.remove_prefix(1); return C; } @@ -1077,7 +1114,7 @@ uint8_t Demangler::demangleCharLiteral(StringView &MangledName) { '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5', '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'}; char C = Lookup[MangledName[0] - 'A']; - MangledName = MangledName.dropFront(); + MangledName.remove_prefix(1); return C; } @@ -1086,7 +1123,7 @@ CharLiteralError: return '\0'; } -wchar_t Demangler::demangleWcharLiteral(StringView &MangledName) { +wchar_t Demangler::demangleWcharLiteral(std::string_view &MangledName) { uint8_t C1, C2; C1 = demangleCharLiteral(MangledName); @@ -1131,7 +1168,7 @@ static void outputHex(OutputBuffer &OB, unsigned C) { TempBuffer[Pos--] = 'x'; assert(Pos >= 0); TempBuffer[Pos--] = '\\'; - OB << StringView(&TempBuffer[Pos + 1]); + OB << std::string_view(&TempBuffer[Pos + 1]); } static void outputEscapedChar(OutputBuffer &OB, unsigned C) { @@ -1253,7 +1290,8 @@ static unsigned decodeMultiByteChar(const uint8_t *StringBytes, return Result; } -FunctionSymbolNode *Demangler::demangleVcallThunkNode(StringView &MangledName) { +FunctionSymbolNode * +Demangler::demangleVcallThunkNode(std::string_view &MangledName) { FunctionSymbolNode *FSN = Arena.alloc<FunctionSymbolNode>(); VcallThunkIdentifierNode *VTIN = Arena.alloc<VcallThunkIdentifierNode>(); FSN->Signature = Arena.alloc<ThunkSignatureNode>(); @@ -1261,36 +1299,39 @@ FunctionSymbolNode *Demangler::demangleVcallThunkNode(StringView &MangledName) { FSN->Name = demangleNameScopeChain(MangledName, VTIN); if (!Error) - Error = !MangledName.consumeFront("$B"); + Error = !consumeFront(MangledName, "$B"); if (!Error) VTIN->OffsetInVTable = demangleUnsigned(MangledName); if (!Error) - Error = !MangledName.consumeFront('A'); + Error = !consumeFront(MangledName, 'A'); if (!Error) FSN->Signature->CallConvention = demangleCallingConvention(MangledName); return (Error) ? nullptr : FSN; } EncodedStringLiteralNode * -Demangler::demangleStringLiteral(StringView &MangledName) { +Demangler::demangleStringLiteral(std::string_view &MangledName) { // This function uses goto, so declare all variables up front. OutputBuffer OB; - StringView CRC; + std::string_view CRC; uint64_t StringByteSize; bool IsWcharT = false; bool IsNegative = false; size_t CrcEndPos = 0; + char F; EncodedStringLiteralNode *Result = Arena.alloc<EncodedStringLiteralNode>(); // Prefix indicating the beginning of a string literal - if (!MangledName.consumeFront("@_")) + if (!consumeFront(MangledName, "@_")) goto StringLiteralError; if (MangledName.empty()) goto StringLiteralError; // Char Type (regular or wchar_t) - switch (MangledName.popFront()) { + F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { case '1': IsWcharT = true; DEMANGLE_FALLTHROUGH; @@ -1307,10 +1348,10 @@ Demangler::demangleStringLiteral(StringView &MangledName) { // CRC 32 (always 8 characters plus a terminator) CrcEndPos = MangledName.find('@'); - if (CrcEndPos == StringView::npos) + if (CrcEndPos == std::string_view::npos) goto StringLiteralError; CRC = MangledName.substr(0, CrcEndPos); - MangledName = MangledName.dropFront(CrcEndPos + 1); + MangledName.remove_prefix(CrcEndPos + 1); if (MangledName.empty()) goto StringLiteralError; @@ -1319,7 +1360,7 @@ Demangler::demangleStringLiteral(StringView &MangledName) { if (StringByteSize > 64) Result->IsTruncated = true; - while (!MangledName.consumeFront('@')) { + while (!consumeFront(MangledName, '@')) { if (MangledName.size() < 2) goto StringLiteralError; wchar_t W = demangleWcharLiteral(MangledName); @@ -1336,7 +1377,7 @@ Demangler::demangleStringLiteral(StringView &MangledName) { uint8_t StringBytes[MaxStringByteLength]; unsigned BytesDecoded = 0; - while (!MangledName.consumeFront('@')) { + while (!consumeFront(MangledName, '@')) { if (MangledName.size() < 1 || BytesDecoded >= MaxStringByteLength) goto StringLiteralError; StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName); @@ -1382,16 +1423,16 @@ StringLiteralError: // Returns MangledName's prefix before the first '@', or an error if // MangledName contains no '@' or the prefix has length 0. -StringView Demangler::demangleSimpleString(StringView &MangledName, - bool Memorize) { - StringView S; +std::string_view Demangler::demangleSimpleString(std::string_view &MangledName, + bool Memorize) { + std::string_view S; for (size_t i = 0; i < MangledName.size(); ++i) { if (MangledName[i] != '@') continue; if (i == 0) break; S = MangledName.substr(0, i); - MangledName = MangledName.dropFront(i + 1); + MangledName.remove_prefix(i + 1); if (Memorize) memorizeString(S); @@ -1403,36 +1444,36 @@ StringView Demangler::demangleSimpleString(StringView &MangledName, } NamedIdentifierNode * -Demangler::demangleAnonymousNamespaceName(StringView &MangledName) { - assert(MangledName.startsWith("?A")); - MangledName.consumeFront("?A"); +Demangler::demangleAnonymousNamespaceName(std::string_view &MangledName) { + assert(llvm::itanium_demangle::starts_with(MangledName, "?A")); + consumeFront(MangledName, "?A"); NamedIdentifierNode *Node = Arena.alloc<NamedIdentifierNode>(); Node->Name = "`anonymous namespace'"; size_t EndPos = MangledName.find('@'); - if (EndPos == StringView::npos) { + if (EndPos == std::string_view::npos) { Error = true; return nullptr; } - StringView NamespaceKey = MangledName.substr(0, EndPos); + std::string_view NamespaceKey = MangledName.substr(0, EndPos); memorizeString(NamespaceKey); MangledName = MangledName.substr(EndPos + 1); return Node; } NamedIdentifierNode * -Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) { +Demangler::demangleLocallyScopedNamePiece(std::string_view &MangledName) { assert(startsWithLocalScopePattern(MangledName)); NamedIdentifierNode *Identifier = Arena.alloc<NamedIdentifierNode>(); - MangledName.consumeFront('?'); + consumeFront(MangledName, '?'); uint64_t Number = 0; bool IsNegative = false; std::tie(Number, IsNegative) = demangleNumber(MangledName); assert(!IsNegative); // One ? to terminate the number - MangledName.consumeFront('?'); + consumeFront(MangledName, '?'); assert(!Error); Node *Scope = parse(MangledName); @@ -1453,7 +1494,7 @@ Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) { // Parses a type name in the form of A@B@C@@ which represents C::B::A. QualifiedNameNode * -Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) { +Demangler::demangleFullyQualifiedTypeName(std::string_view &MangledName) { IdentifierNode *Identifier = demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true); if (Error) @@ -1471,7 +1512,7 @@ Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) { // Symbol names have slightly different rules regarding what can appear // so we separate out the implementations for flexibility. QualifiedNameNode * -Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) { +Demangler::demangleFullyQualifiedSymbolName(std::string_view &MangledName) { // This is the final component of a symbol name (i.e. the leftmost component // of a mangled name. Since the only possible template instantiation that // can appear in this context is a function template, and since those are @@ -1500,8 +1541,9 @@ Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) { return QN; } -IdentifierNode *Demangler::demangleUnqualifiedTypeName(StringView &MangledName, - bool Memorize) { +IdentifierNode * +Demangler::demangleUnqualifiedTypeName(std::string_view &MangledName, + bool Memorize) { // An inner-most name can be a back-reference, because a fully-qualified name // (e.g. Scope + Inner) can contain other fully qualified names inside of // them (for example template parameters), and these nested parameters can @@ -1509,32 +1551,33 @@ IdentifierNode *Demangler::demangleUnqualifiedTypeName(StringView &MangledName, if (startsWithDigit(MangledName)) return demangleBackRefName(MangledName); - if (MangledName.startsWith("?$")) + if (llvm::itanium_demangle::starts_with(MangledName, "?$")) return demangleTemplateInstantiationName(MangledName, NBB_Template); return demangleSimpleName(MangledName, Memorize); } IdentifierNode * -Demangler::demangleUnqualifiedSymbolName(StringView &MangledName, +Demangler::demangleUnqualifiedSymbolName(std::string_view &MangledName, NameBackrefBehavior NBB) { if (startsWithDigit(MangledName)) return demangleBackRefName(MangledName); - if (MangledName.startsWith("?$")) + if (llvm::itanium_demangle::starts_with(MangledName, "?$")) return demangleTemplateInstantiationName(MangledName, NBB); - if (MangledName.startsWith('?')) + if (llvm::itanium_demangle::starts_with(MangledName, '?')) return demangleFunctionIdentifierCode(MangledName); return demangleSimpleName(MangledName, /*Memorize=*/(NBB & NBB_Simple) != 0); } -IdentifierNode *Demangler::demangleNameScopePiece(StringView &MangledName) { +IdentifierNode * +Demangler::demangleNameScopePiece(std::string_view &MangledName) { if (startsWithDigit(MangledName)) return demangleBackRefName(MangledName); - if (MangledName.startsWith("?$")) + if (llvm::itanium_demangle::starts_with(MangledName, "?$")) return demangleTemplateInstantiationName(MangledName, NBB_Template); - if (MangledName.startsWith("?A")) + if (llvm::itanium_demangle::starts_with(MangledName, "?A")) return demangleAnonymousNamespaceName(MangledName); if (startsWithLocalScopePattern(MangledName)) @@ -1556,14 +1599,14 @@ static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head, } QualifiedNameNode * -Demangler::demangleNameScopeChain(StringView &MangledName, +Demangler::demangleNameScopeChain(std::string_view &MangledName, IdentifierNode *UnqualifiedName) { NodeList *Head = Arena.alloc<NodeList>(); Head->N = UnqualifiedName; size_t Count = 1; - while (!MangledName.consumeFront("@")) { + while (!consumeFront(MangledName, "@")) { ++Count; NodeList *NewHead = Arena.alloc<NodeList>(); NewHead->Next = Head; @@ -1587,8 +1630,10 @@ Demangler::demangleNameScopeChain(StringView &MangledName, return QN; } -FuncClass Demangler::demangleFunctionClass(StringView &MangledName) { - switch (MangledName.popFront()) { +FuncClass Demangler::demangleFunctionClass(std::string_view &MangledName) { + const char F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { case '9': return FuncClass(FC_ExternC | FC_NoParameterList); case 'A': @@ -1645,11 +1690,13 @@ FuncClass Demangler::demangleFunctionClass(StringView &MangledName) { return FuncClass(FC_Global | FC_Far); case '$': { FuncClass VFlag = FC_VirtualThisAdjust; - if (MangledName.consumeFront('R')) + if (consumeFront(MangledName, 'R')) VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx); if (MangledName.empty()) break; - switch (MangledName.popFront()) { + const char F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { case '0': return FuncClass(FC_Private | FC_Virtual | VFlag); case '1': @@ -1670,13 +1717,16 @@ FuncClass Demangler::demangleFunctionClass(StringView &MangledName) { return FC_Public; } -CallingConv Demangler::demangleCallingConvention(StringView &MangledName) { +CallingConv +Demangler::demangleCallingConvention(std::string_view &MangledName) { if (MangledName.empty()) { Error = true; return CallingConv::None; } - switch (MangledName.popFront()) { + const char F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { case 'A': case 'B': return CallingConv::Cdecl; @@ -1709,10 +1759,13 @@ CallingConv Demangler::demangleCallingConvention(StringView &MangledName) { return CallingConv::None; } -StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) { +StorageClass +Demangler::demangleVariableStorageClass(std::string_view &MangledName) { assert(MangledName.front() >= '0' && MangledName.front() <= '4'); - switch (MangledName.popFront()) { + const char F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { case '0': return StorageClass::PrivateStatic; case '1': @@ -1728,13 +1781,15 @@ StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) { } std::pair<Qualifiers, bool> -Demangler::demangleQualifiers(StringView &MangledName) { +Demangler::demangleQualifiers(std::string_view &MangledName) { if (MangledName.empty()) { Error = true; return std::make_pair(Q_None, false); } - switch (MangledName.popFront()) { + const char F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { // Member qualifiers case 'Q': return std::make_pair(Q_None, true); @@ -1760,14 +1815,14 @@ Demangler::demangleQualifiers(StringView &MangledName) { // <variable-type> ::= <type> <cvr-qualifiers> // ::= <type> <pointee-cvr-qualifiers> # pointers, references -TypeNode *Demangler::demangleType(StringView &MangledName, +TypeNode *Demangler::demangleType(std::string_view &MangledName, QualifierMangleMode QMM) { Qualifiers Quals = Q_None; bool IsMember = false; if (QMM == QualifierMangleMode::Mangle) { std::tie(Quals, IsMember) = demangleQualifiers(MangledName); } else if (QMM == QualifierMangleMode::Result) { - if (MangledName.consumeFront('?')) + if (consumeFront(MangledName, '?')) std::tie(Quals, IsMember) = demangleQualifiers(MangledName); } @@ -1789,11 +1844,11 @@ TypeNode *Demangler::demangleType(StringView &MangledName, } else if (isArrayType(MangledName)) Ty = demangleArrayType(MangledName); else if (isFunctionType(MangledName)) { - if (MangledName.consumeFront("$$A8@@")) + if (consumeFront(MangledName, "$$A8@@")) Ty = demangleFunctionType(MangledName, true); else { - assert(MangledName.startsWith("$$A6")); - MangledName.consumeFront("$$A6"); + assert(llvm::itanium_demangle::starts_with(MangledName, "$$A6")); + consumeFront(MangledName, "$$A6"); Ty = demangleFunctionType(MangledName, false); } } else if (isCustomType(MangledName)) { @@ -1808,18 +1863,19 @@ TypeNode *Demangler::demangleType(StringView &MangledName, return Ty; } -bool Demangler::demangleThrowSpecification(StringView &MangledName) { - if (MangledName.consumeFront("_E")) +bool Demangler::demangleThrowSpecification(std::string_view &MangledName) { + if (consumeFront(MangledName, "_E")) return true; - if (MangledName.consumeFront('Z')) + if (consumeFront(MangledName, 'Z')) return false; Error = true; return false; } -FunctionSignatureNode *Demangler::demangleFunctionType(StringView &MangledName, - bool HasThisQuals) { +FunctionSignatureNode * +Demangler::demangleFunctionType(std::string_view &MangledName, + bool HasThisQuals) { FunctionSignatureNode *FTy = Arena.alloc<FunctionSignatureNode>(); if (HasThisQuals) { @@ -1833,7 +1889,7 @@ FunctionSignatureNode *Demangler::demangleFunctionType(StringView &MangledName, // <return-type> ::= <type> // ::= @ # structors (they have no declared return type) - bool IsStructor = MangledName.consumeFront('@'); + bool IsStructor = consumeFront(MangledName, '@'); if (!IsStructor) FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result); @@ -1845,9 +1901,9 @@ FunctionSignatureNode *Demangler::demangleFunctionType(StringView &MangledName, } FunctionSymbolNode * -Demangler::demangleFunctionEncoding(StringView &MangledName) { +Demangler::demangleFunctionEncoding(std::string_view &MangledName) { FuncClass ExtraFlags = FC_None; - if (MangledName.consumeFront("$$J0")) + if (consumeFront(MangledName, "$$J0")) ExtraFlags = FC_ExternC; if (MangledName.empty()) { @@ -1897,13 +1953,13 @@ Demangler::demangleFunctionEncoding(StringView &MangledName) { return Symbol; } -CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) { - assert(MangledName.startsWith('?')); - MangledName.popFront(); +CustomTypeNode *Demangler::demangleCustomType(std::string_view &MangledName) { + assert(llvm::itanium_demangle::starts_with(MangledName, '?')); + MangledName.remove_prefix(1); CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>(); CTN->Identifier = demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true); - if (!MangledName.consumeFront('@')) + if (!consumeFront(MangledName, '@')) Error = true; if (Error) return nullptr; @@ -1911,11 +1967,14 @@ CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) { } // Reads a primitive type. -PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) { - if (MangledName.consumeFront("$$T")) +PrimitiveTypeNode * +Demangler::demanglePrimitiveType(std::string_view &MangledName) { + if (consumeFront(MangledName, "$$T")) return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Nullptr); - switch (MangledName.popFront()) { + const char F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { case 'X': return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Void); case 'D': @@ -1947,7 +2006,9 @@ PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) { Error = true; return nullptr; } - switch (MangledName.popFront()) { + const char F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { case 'N': return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Bool); case 'J': @@ -1970,10 +2031,12 @@ PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) { return nullptr; } -TagTypeNode *Demangler::demangleClassType(StringView &MangledName) { +TagTypeNode *Demangler::demangleClassType(std::string_view &MangledName) { TagTypeNode *TT = nullptr; - switch (MangledName.popFront()) { + const char F = MangledName.front(); + MangledName.remove_prefix(1); + switch (F) { case 'T': TT = Arena.alloc<TagTypeNode>(TagKind::Union); break; @@ -1984,7 +2047,7 @@ TagTypeNode *Demangler::demangleClassType(StringView &MangledName) { TT = Arena.alloc<TagTypeNode>(TagKind::Class); break; case 'W': - if (!MangledName.consumeFront('4')) { + if (!consumeFront(MangledName, '4')) { Error = true; return nullptr; } @@ -2000,13 +2063,13 @@ TagTypeNode *Demangler::demangleClassType(StringView &MangledName) { // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type> // # the E is required for 64-bit non-static pointers -PointerTypeNode *Demangler::demanglePointerType(StringView &MangledName) { +PointerTypeNode *Demangler::demanglePointerType(std::string_view &MangledName) { PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>(); std::tie(Pointer->Quals, Pointer->Affinity) = demanglePointerCVQualifiers(MangledName); - if (MangledName.consumeFront("6")) { + if (consumeFront(MangledName, "6")) { Pointer->Pointee = demangleFunctionType(MangledName, false); return Pointer; } @@ -2018,7 +2081,8 @@ PointerTypeNode *Demangler::demanglePointerType(StringView &MangledName) { return Pointer; } -PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) { +PointerTypeNode * +Demangler::demangleMemberPointerType(std::string_view &MangledName) { PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>(); std::tie(Pointer->Quals, Pointer->Affinity) = @@ -2030,7 +2094,7 @@ PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) { // isMemberPointer() only returns true if there is at least one character // after the qualifiers. - if (MangledName.consumeFront("8")) { + if (consumeFront(MangledName, "8")) { Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName); Pointer->Pointee = demangleFunctionType(MangledName, true); } else { @@ -2048,21 +2112,22 @@ PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) { return Pointer; } -Qualifiers Demangler::demanglePointerExtQualifiers(StringView &MangledName) { +Qualifiers +Demangler::demanglePointerExtQualifiers(std::string_view &MangledName) { Qualifiers Quals = Q_None; - if (MangledName.consumeFront('E')) + if (consumeFront(MangledName, 'E')) Quals = Qualifiers(Quals | Q_Pointer64); - if (MangledName.consumeFront('I')) + if (consumeFront(MangledName, 'I')) Quals = Qualifiers(Quals | Q_Restrict); - if (MangledName.consumeFront('F')) + if (consumeFront(MangledName, 'F')) Quals = Qualifiers(Quals | Q_Unaligned); return Quals; } -ArrayTypeNode *Demangler::demangleArrayType(StringView &MangledName) { +ArrayTypeNode *Demangler::demangleArrayType(std::string_view &MangledName) { assert(MangledName.front() == 'Y'); - MangledName.popFront(); + MangledName.remove_prefix(1); uint64_t Rank = 0; bool IsNegative = false; @@ -2091,7 +2156,7 @@ ArrayTypeNode *Demangler::demangleArrayType(StringView &MangledName) { } ATy->Dimensions = nodeListToNodeArray(Arena, Head, Rank); - if (MangledName.consumeFront("$$C")) { + if (consumeFront(MangledName, "$$C")) { bool IsMember = false; std::tie(ATy->Quals, IsMember) = demangleQualifiers(MangledName); if (IsMember) { @@ -2105,17 +2170,18 @@ ArrayTypeNode *Demangler::demangleArrayType(StringView &MangledName) { } // Reads a function's parameters. -NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName, - bool &IsVariadic) { +NodeArrayNode * +Demangler::demangleFunctionParameterList(std::string_view &MangledName, + bool &IsVariadic) { // Empty parameter list. - if (MangledName.consumeFront('X')) + if (consumeFront(MangledName, 'X')) return nullptr; NodeList *Head = Arena.alloc<NodeList>(); NodeList **Current = &Head; size_t Count = 0; - while (!Error && !MangledName.startsWith('@') && - !MangledName.startsWith('Z')) { + while (!Error && !llvm::itanium_demangle::starts_with(MangledName, '@') && + !llvm::itanium_demangle::starts_with(MangledName, 'Z')) { ++Count; if (startsWithDigit(MangledName)) { @@ -2124,7 +2190,7 @@ NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName, Error = true; return nullptr; } - MangledName = MangledName.dropFront(); + MangledName.remove_prefix(1); *Current = Arena.alloc<NodeList>(); (*Current)->N = Backrefs.FunctionParams[N]; @@ -2159,10 +2225,10 @@ NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName, // A non-empty parameter list is terminated by either 'Z' (variadic) parameter // list or '@' (non variadic). Careful not to consume "@Z", as in that case // the following Z could be a throw specifier. - if (MangledName.consumeFront('@')) + if (consumeFront(MangledName, '@')) return NA; - if (MangledName.consumeFront('Z')) { + if (consumeFront(MangledName, 'Z')) { IsVariadic = true; return NA; } @@ -2171,14 +2237,14 @@ NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName, } NodeArrayNode * -Demangler::demangleTemplateParameterList(StringView &MangledName) { +Demangler::demangleTemplateParameterList(std::string_view &MangledName) { NodeList *Head = nullptr; NodeList **Current = &Head; size_t Count = 0; - while (!MangledName.startsWith('@')) { - if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") || - MangledName.consumeFront("$$$V") || MangledName.consumeFront("$$Z")) { + while (!llvm::itanium_demangle::starts_with(MangledName, '@')) { + if (consumeFront(MangledName, "$S") || consumeFront(MangledName, "$$V") || + consumeFront(MangledName, "$$$V") || consumeFront(MangledName, "$$Z")) { // parameter pack separator continue; } @@ -2191,29 +2257,32 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) { NodeList &TP = **Current; TemplateParameterReferenceNode *TPRN = nullptr; - if (MangledName.consumeFront("$$Y")) { + if (consumeFront(MangledName, "$$Y")) { // Template alias TP.N = demangleFullyQualifiedTypeName(MangledName); - } else if (MangledName.consumeFront("$$B")) { + } else if (consumeFront(MangledName, "$$B")) { // Array TP.N = demangleType(MangledName, QualifierMangleMode::Drop); - } else if (MangledName.consumeFront("$$C")) { + } else if (consumeFront(MangledName, "$$C")) { // Type has qualifiers. TP.N = demangleType(MangledName, QualifierMangleMode::Mangle); - } else if (MangledName.startsWith("$1") || MangledName.startsWith("$H") || - MangledName.startsWith("$I") || MangledName.startsWith("$J")) { + } else if (llvm::itanium_demangle::starts_with(MangledName, "$1") || + llvm::itanium_demangle::starts_with(MangledName, "$H") || + llvm::itanium_demangle::starts_with(MangledName, "$I") || + llvm::itanium_demangle::starts_with(MangledName, "$J")) { // Pointer to member TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); TPRN->IsMemberPointer = true; - MangledName = MangledName.dropFront(); + MangledName.remove_prefix(1); // 1 - single inheritance <name> // H - multiple inheritance <name> <number> // I - virtual inheritance <name> <number> <number> // J - unspecified inheritance <name> <number> <number> <number> - char InheritanceSpecifier = MangledName.popFront(); + char InheritanceSpecifier = MangledName.front(); + MangledName.remove_prefix(1); SymbolNode *S = nullptr; - if (MangledName.startsWith('?')) { + if (llvm::itanium_demangle::starts_with(MangledName, '?')) { S = parse(MangledName); if (Error || !S->Name) { Error = true; @@ -2242,18 +2311,20 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) { } TPRN->Affinity = PointerAffinity::Pointer; TPRN->Symbol = S; - } else if (MangledName.startsWith("$E?")) { - MangledName.consumeFront("$E"); + } else if (llvm::itanium_demangle::starts_with(MangledName, "$E?")) { + consumeFront(MangledName, "$E"); // Reference to symbol TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); TPRN->Symbol = parse(MangledName); TPRN->Affinity = PointerAffinity::Reference; - } else if (MangledName.startsWith("$F") || MangledName.startsWith("$G")) { + } else if (llvm::itanium_demangle::starts_with(MangledName, "$F") || + llvm::itanium_demangle::starts_with(MangledName, "$G")) { TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>(); // Data member pointer. - MangledName = MangledName.dropFront(); - char InheritanceSpecifier = MangledName.popFront(); + MangledName.remove_prefix(1); + char InheritanceSpecifier = MangledName.front(); + MangledName.remove_prefix(1); switch (InheritanceSpecifier) { case 'G': @@ -2271,7 +2342,7 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) { } TPRN->IsMemberPointer = true; - } else if (MangledName.consumeFront("$0")) { + } else if (consumeFront(MangledName, "$0")) { // Integral non-type template parameter bool IsNegative = false; uint64_t Value = 0; @@ -2292,8 +2363,9 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) { // Template parameter lists cannot be variadic, so it can only be terminated // by @ (as opposed to 'Z' in the function parameter case). - assert(MangledName.startsWith('@')); // The above loop exits only on '@'. - MangledName.consumeFront('@'); + assert(llvm::itanium_demangle::starts_with( + MangledName, '@')); // The above loop exits only on '@'. + consumeFront(MangledName, '@'); return nodeListToNodeArray(Arena, Head, Count); } @@ -2309,8 +2381,8 @@ void Demangler::dumpBackReferences() { TypeNode *T = Backrefs.FunctionParams[I]; T->output(OB, OF_Default); - StringView B = OB; - std::printf(" [%d] - %.*s\n", (int)I, (int)B.size(), B.begin()); + std::string_view B = OB; + std::printf(" [%d] - %.*s\n", (int)I, (int)B.size(), B.data()); } std::free(OB.getBuffer()); @@ -2319,21 +2391,20 @@ void Demangler::dumpBackReferences() { std::printf("%d name backreferences\n", (int)Backrefs.NamesCount); for (size_t I = 0; I < Backrefs.NamesCount; ++I) { std::printf(" [%d] - %.*s\n", (int)I, (int)Backrefs.Names[I]->Name.size(), - Backrefs.Names[I]->Name.begin()); + Backrefs.Names[I]->Name.data()); } if (Backrefs.NamesCount > 0) std::printf("\n"); } -char *llvm::microsoftDemangle(const char *MangledName, size_t *NMangled, - char *Buf, size_t *N, +char *llvm::microsoftDemangle(std::string_view MangledName, size_t *NMangled, int *Status, MSDemangleFlags Flags) { Demangler D; - StringView Name{MangledName}; + std::string_view Name{MangledName}; SymbolNode *AST = D.parse(Name); if (!D.Error && NMangled) - *NMangled = Name.begin() - MangledName; + *NMangled = MangledName.size() - Name.size(); if (Flags & MSDF_DumpBackrefs) D.dumpBackReferences(); @@ -2351,14 +2422,13 @@ char *llvm::microsoftDemangle(const char *MangledName, size_t *NMangled, OF = OutputFlags(OF | OF_NoVariableType); int InternalStatus = demangle_success; + char *Buf; if (D.Error) InternalStatus = demangle_invalid_mangled_name; else { - OutputBuffer OB(Buf, N); + OutputBuffer OB; AST->output(OB, OF); OB += '\0'; - if (N != nullptr) - *N = OB.getCurrentPosition(); Buf = OB.getBuffer(); } diff --git a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp index 975649f28ad2..9a9c34ec6d34 100644 --- a/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangleNodes.cpp @@ -120,7 +120,7 @@ static void outputCallingConvention(OutputBuffer &OB, CallingConv CC) { std::string Node::toString(OutputFlags Flags) const { OutputBuffer OB; this->output(OB, Flags); - StringView SV = OB; + std::string_view SV = OB; std::string Owned(SV.begin(), SV.end()); std::free(OB.getBuffer()); return Owned; @@ -158,7 +158,7 @@ void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags) const { } void NodeArrayNode::output(OutputBuffer &OB, OutputFlags Flags, - StringView Separator) const { + std::string_view Separator) const { if (Count == 0) return; if (Nodes[0]) diff --git a/llvm/lib/Demangle/RustDemangle.cpp b/llvm/lib/Demangle/RustDemangle.cpp index 8c01155127d8..f0d70de3abb5 100644 --- a/llvm/lib/Demangle/RustDemangle.cpp +++ b/llvm/lib/Demangle/RustDemangle.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Demangle/Demangle.h" -#include "llvm/Demangle/StringView.h" +#include "llvm/Demangle/StringViewExtras.h" #include "llvm/Demangle/Utility.h" #include <algorithm> @@ -20,17 +20,18 @@ #include <cstdint> #include <cstring> #include <limits> +#include <string_view> using namespace llvm; using llvm::itanium_demangle::OutputBuffer; using llvm::itanium_demangle::ScopedOverride; -using llvm::itanium_demangle::StringView; +using llvm::itanium_demangle::starts_with; namespace { struct Identifier { - StringView Name; + std::string_view Name; bool Punycode; bool empty() const { return Name.empty(); } @@ -77,7 +78,7 @@ class Demangler { size_t RecursionLevel; size_t BoundLifetimes; // Input string that is being demangled with "_R" prefix removed. - StringView Input; + std::string_view Input; // Position in the input string. size_t Position; // When true, print methods append the output to the stream. @@ -92,7 +93,7 @@ public: Demangler(size_t MaxRecursionLevel = 500); - bool demangle(StringView MangledName); + bool demangle(std::string_view MangledName); private: bool demanglePath(IsInType Type, @@ -128,10 +129,10 @@ private: uint64_t parseOptionalBase62Number(char Tag); uint64_t parseBase62Number(); uint64_t parseDecimalNumber(); - uint64_t parseHexNumber(StringView &HexDigits); + uint64_t parseHexNumber(std::string_view &HexDigits); void print(char C); - void print(StringView S); + void print(std::string_view S); void printDecimalNumber(uint64_t N); void printBasicType(BasicType); void printLifetime(uint64_t Index); @@ -147,17 +148,13 @@ private: } // namespace -char *llvm::rustDemangle(const char *MangledName) { - if (MangledName == nullptr) - return nullptr; - +char *llvm::rustDemangle(std::string_view MangledName) { // Return early if mangled name doesn't look like a Rust symbol. - StringView Mangled(MangledName); - if (!Mangled.startsWith("_R")) + if (MangledName.empty() || !starts_with(MangledName, "_R")) return nullptr; Demangler D; - if (!D.demangle(Mangled)) { + if (!D.demangle(MangledName)) { std::free(D.Output.getBuffer()); return nullptr; } @@ -190,20 +187,20 @@ static inline bool isValid(const char C) { // responsibility of the caller to free the memory behind the output stream. // // <symbol-name> = "_R" <path> [<instantiating-crate>] -bool Demangler::demangle(StringView Mangled) { +bool Demangler::demangle(std::string_view Mangled) { Position = 0; Error = false; Print = true; RecursionLevel = 0; BoundLifetimes = 0; - if (!Mangled.consumeFront("_R")) { + if (!starts_with(Mangled, "_R")) { Error = true; return false; } + Mangled.remove_prefix(2); size_t Dot = Mangled.find('.'); - Input = Mangled.substr(0, Dot); - StringView Suffix = Mangled.dropFront(Dot); + Input = Dot == std::string_view::npos ? Mangled : Mangled.substr(0, Dot); demanglePath(IsInType::No); @@ -215,9 +212,9 @@ bool Demangler::demangle(StringView Mangled) { if (Position != Input.size()) Error = true; - if (!Suffix.empty()) { + if (Dot != std::string_view::npos) { print(" ("); - print(Suffix); + print(Mangled.substr(Dot)); print(")"); } @@ -775,7 +772,7 @@ void Demangler::demangleConstInt() { if (consumeIf('n')) print('-'); - StringView HexDigits; + std::string_view HexDigits; uint64_t Value = parseHexNumber(HexDigits); if (HexDigits.size() <= 16) { printDecimalNumber(Value); @@ -788,7 +785,7 @@ void Demangler::demangleConstInt() { // <const-data> = "0_" // false // | "1_" // true void Demangler::demangleConstBool() { - StringView HexDigits; + std::string_view HexDigits; parseHexNumber(HexDigits); if (HexDigits == "0") print("false"); @@ -805,7 +802,7 @@ static bool isAsciiPrintable(uint64_t CodePoint) { // <const-data> = <hex-number> void Demangler::demangleConstChar() { - StringView HexDigits; + std::string_view HexDigits; uint64_t CodePoint = parseHexNumber(HexDigits); if (Error || HexDigits.size() > 6) { Error = true; @@ -859,7 +856,7 @@ Identifier Demangler::parseIdentifier() { Error = true; return {}; } - StringView S = Input.substr(Position, Bytes); + std::string_view S = Input.substr(Position, Bytes); Position += Bytes; if (!std::all_of(S.begin(), S.end(), isValid)) { @@ -967,7 +964,7 @@ uint64_t Demangler::parseDecimalNumber() { // // <hex-number> = "0_" // | <1-9a-f> {<0-9a-f>} "_" -uint64_t Demangler::parseHexNumber(StringView &HexDigits) { +uint64_t Demangler::parseHexNumber(std::string_view &HexDigits) { size_t Start = Position; uint64_t Value = 0; @@ -991,7 +988,7 @@ uint64_t Demangler::parseHexNumber(StringView &HexDigits) { } if (Error) { - HexDigits = StringView(); + HexDigits = std::string_view(); return 0; } @@ -1008,7 +1005,7 @@ void Demangler::print(char C) { Output += C; } -void Demangler::print(StringView S) { +void Demangler::print(std::string_view S) { if (Error || !Print) return; @@ -1105,17 +1102,17 @@ static inline bool encodeUTF8(size_t CodePoint, char *Output) { // Decodes string encoded using punycode and appends results to Output. // Returns true if decoding was successful. -static bool decodePunycode(StringView Input, OutputBuffer &Output) { +static bool decodePunycode(std::string_view Input, OutputBuffer &Output) { size_t OutputSize = Output.getCurrentPosition(); size_t InputIdx = 0; // Rust uses an underscore as a delimiter. - size_t DelimiterPos = StringView::npos; + size_t DelimiterPos = std::string_view::npos; for (size_t I = 0; I != Input.size(); ++I) if (Input[I] == '_') DelimiterPos = I; - if (DelimiterPos != StringView::npos) { + if (DelimiterPos != std::string_view::npos) { // Copy basic code points before the last delimiter to the output. for (; InputIdx != DelimiterPos; ++InputIdx) { char C = Input[InputIdx]; @@ -1123,7 +1120,7 @@ static bool decodePunycode(StringView Input, OutputBuffer &Output) { return false; // Code points are padded with zeros while decoding is in progress. char UTF8[4] = {C}; - Output += StringView(UTF8, UTF8 + 4); + Output += std::string_view(UTF8, 4); } // Skip over the delimiter. ++InputIdx; |