Index: llvm/lib/Demangle/DLangDemangle.cpp =================================================================== --- llvm/lib/Demangle/DLangDemangle.cpp +++ llvm/lib/Demangle/DLangDemangle.cpp @@ -133,6 +133,16 @@ /// \see https://dlang.org/spec/abi.html#Number const char *decodeNumber(const char *Mangled, unsigned long *Ret); + /// Extract the hex-digit from a given string + /// + /// \param Mangled string to extract the hex-digit + /// \param Ret assigned result value + /// + /// \return the remaining string on success or nullptr on failure. + /// + /// \see https://dlang.org/spec/abi.html#HexDigits + const char *decodeHexdigit(const char *Mangled, char *Ret); + /// Extract the back reference position from a given string /// /// \param Mangled string to extract the back reference position @@ -387,6 +397,17 @@ /// \see https://dlang.org/spec/abi.html#Value const char *parseInteger(OutputString *Decl, const char *Mangled, char Type); + /// Extract and demangle a string value from a given mangled symbol append it + /// to the output string + /// + /// \param Decl 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#Value + const char *parseString(OutputString *Decl, const char *Mangled); + /// Extract and demangle a floating-point value from a given mangled symbol /// append it to the output string /// @@ -520,6 +541,31 @@ return Mangled; } +const char *Demangler::decodeHexdigit(const char *Mangled, char *Ret) { + char C; + + // Return nullptr if trying to extract something that isn't a hexdigit + if (Mangled == nullptr || !std::isxdigit(Mangled[0]) || + !std::isxdigit(Mangled[1])) + return nullptr; + + C = Mangled[0]; + if (!std::isdigit(C)) + *Ret = C - (std::isupper(C) ? 'A' : 'a') + 10; + else + *Ret = C - '0'; + + C = Mangled[1]; + if (!std::isdigit(C)) + *Ret = (*Ret << 4) | (C - (std::isupper(C) ? 'A' : 'a') + 10); + else + *Ret = (*Ret << 4) | (C - '0'); + + Mangled += 2; + + return Mangled; +} + bool Demangler::isCallConvention(const char *Mangled) { switch (*Mangled) { case 'F': @@ -1698,6 +1744,13 @@ Decl->append('i'); break; + // String values + case 'a': /* UTF8 */ + case 'w': /* UTF16 */ + case 'd': /* UTF32 */ + Mangled = parseString(Decl, Mangled); + break; + default: return nullptr; } @@ -1705,6 +1758,64 @@ return Mangled; } +const char *Demangler::parseString(OutputString *Decl, const char *Mangled) { + char Type = *Mangled; + unsigned long Len; + + Mangled++; + Mangled = decodeNumber(Mangled, &Len); + if (Mangled == nullptr || *Mangled != '_') + return nullptr; + + Mangled++; + Decl->append('\"'); + while (Len--) { + char Val; + const char *Endptr = decodeHexdigit(Mangled, &Val); + + if (Endptr == nullptr) + return nullptr; + + /* Sanitize white and non-printable characters. */ + switch (Val) { + case ' ': + Decl->append(' '); + break; + case '\t': + Decl->append("\\t"); + break; + case '\n': + Decl->append("\\n"); + break; + case '\r': + Decl->append("\\r"); + break; + case '\f': + Decl->append("\\f"); + break; + case '\v': + Decl->append("\\v"); + break; + + default: + if (std::isprint(Val)) + Decl->append(Val); + else { + Decl->append("\\x"); + Decl->append(Mangled, 2); + } + } + + Mangled = Endptr; + } + Decl->append('\"'); + + if (Type != 'a') + Decl->append(Type); + + return Mangled; +} + const char *Demangler::parseInteger(OutputString *Decl, const char *Mangled, char Type) { if (Type == 'a' || Type == 'u' || Type == 'w') { Index: llvm/unittests/Demangle/DLangDemangleTest.cpp =================================================================== --- llvm/unittests/Demangle/DLangDemangleTest.cpp +++ llvm/unittests/Demangle/DLangDemangleTest.cpp @@ -302,7 +302,13 @@ "44555666777888999Zv", "demangle.test!(0x0." "00111222333444555666777888999AAABBBCCCDDDEEEFFFp00011122233344455566677" - "7888999)"} + "7888999)"}, + {"_D8demangle22__T4testVG3ua3_616263Zv", "demangle.test!(\"abc\")"}, + {"_D8demangle22__T4testVG3ud3_616263Zv", "demangle.test!(\"abc\"d)"}, + {"_D8demangle22__T4testVG3uw3_616263Zv", "demangle.test!(\"abc\"w)"}, + {"_D8demangle16__T4testVAyaa0_Zv", "demangle.test!(\"\")"}, + {"_D8demangle32__T4testVAyaa8_20090a0d0c0b00ffZv", + "demangle.test!(\" \\t\\n\\r\\f\\v\\x00\\xff\")"} }; for (ExpectedVal Val : ExpectedArray) {