diff --git a/llvm/lib/Demangle/DLangDemangle.cpp b/llvm/lib/Demangle/DLangDemangle.cpp --- a/llvm/lib/Demangle/DLangDemangle.cpp +++ b/llvm/lib/Demangle/DLangDemangle.cpp @@ -188,6 +188,17 @@ /// \see https://dlang.org/spec/abi.html#QualifiedName const char *parseQualified(OutputString *Decl, const char *Mangled); + /// Extract and demangle a type 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#Type + const char *parseType(OutputString *Decl, const char *Mangled); + /// The string we are demangling. const char *Str; }; @@ -338,8 +349,11 @@ if (*Mangled == 'Z') Mangled++; else { - // TODO: Implement symbols with types - return nullptr; + // Discard the declaration or return type. + OutputString Type = OutputString(); + + Mangled = parseType(&Type, Mangled); + Type.free(); } } @@ -427,6 +441,252 @@ return parseLName(Decl, Mangled, Len); } +const char *Demangler::parseType(OutputString *Decl, const char *Mangled) { + if (Mangled == nullptr || *Mangled == '\0') + return nullptr; + + switch (*Mangled) { + case 'O': /* shared(T) */ + Mangled++; + Decl->append("shared("); + Mangled = parseType(Decl, Mangled); + Decl->append(")"); + return Mangled; + + case 'x': /* const(T) */ + Mangled++; + Decl->append("const("); + Mangled = parseType(Decl, Mangled); + Decl->append(")"); + return Mangled; + + case 'y': /* immutable(T) */ + Mangled++; + Decl->append("immutable("); + Mangled = parseType(Decl, Mangled); + Decl->append(")"); + return Mangled; + + case 'N': + Mangled++; + + switch (*Mangled) { + case 'g': // wild(T) + Mangled++; + Decl->append("inout("); + Mangled = parseType(Decl, Mangled); + Decl->append(")"); + return Mangled; + + case 'h': // vector(T) + Mangled++; + Decl->append("__vector("); + Mangled = parseType(Decl, Mangled); + Decl->append(")"); + return Mangled; + + case 'n': // typeof(*null) + Mangled++; + Decl->append("typeof(*null)"); + return Mangled; + } + + // invalid + return nullptr; + + case 'A': /* dynamic array (T[]) */ + Mangled++; + Mangled = parseType(Decl, Mangled); + Decl->append("[]"); + return Mangled; + + case 'G': /* static array (T[N]) */ + { + const char *NumPtr; + size_t Num = 0; + Mangled++; + + NumPtr = Mangled; + while (std::isdigit(*Mangled)) { + Num++; + Mangled++; + } + Mangled = parseType(Decl, Mangled); + Decl->append("["); + Decl->append(NumPtr, Num); + Decl->append("]"); + return Mangled; + } + + case 'H': /* associative array (T[T]) */ + { + OutputString Type = OutputString(); + size_t Sztype; + Mangled++; + + Mangled = parseType(&Type, Mangled); + Sztype = Type.getLength(); + + Mangled = parseType(Decl, Mangled); + Decl->append("["); + Decl->append(Type.Buffer, Sztype); + Decl->append("]"); + + Type.free(); + return Mangled; + } + + case 'P': /* pointer (T*) */ + Mangled++; + if (!isCallConvention(Mangled)) { + Mangled = parseType(Decl, Mangled); + Decl->append("*"); + return Mangled; + } + + // TODO: Parse function types + + [[clang::fallthrough]]; + case 'C': /* class T */ + case 'S': /* struct T */ + case 'E': /* enum T */ + case 'T': /* typedef T */ + Mangled++; + // TODO: Handle type modifiers and type functions in qualifiers + return parseQualified(Decl, Mangled); + + // TODO: Parse delegate types + // TODO: Parse tuple types + + // Basic types + case 'n': + Mangled++; + Decl->append("typeof(null)"); + return Mangled; + + case 'v': + Mangled++; + Decl->append("void"); + return Mangled; + + case 'g': + Mangled++; + Decl->append("byte"); + return Mangled; + case 'h': + Mangled++; + Decl->append("ubyte"); + return Mangled; + + case 's': + Mangled++; + Decl->append("short"); + return Mangled; + case 't': + Mangled++; + Decl->append("ushort"); + return Mangled; + + case 'i': + Mangled++; + Decl->append("int"); + return Mangled; + case 'k': + Mangled++; + Decl->append("uint"); + return Mangled; + + case 'l': + Mangled++; + Decl->append("long"); + return Mangled; + case 'm': + Mangled++; + Decl->append("ulong"); + return Mangled; + + case 'f': + Mangled++; + Decl->append("float"); + return Mangled; + case 'd': + Mangled++; + Decl->append("double"); + return Mangled; + case 'e': + Mangled++; + Decl->append("real"); + return Mangled; + + // Imaginary types + case 'o': + Mangled++; + Decl->append("ifloat"); + return Mangled; + case 'p': + Mangled++; + Decl->append("idouble"); + return Mangled; + case 'j': + Mangled++; + Decl->append("ireal"); + return Mangled; + + // Complex types + case 'q': + Mangled++; + Decl->append("cfloat"); + return Mangled; + case 'r': + Mangled++; + Decl->append("cdouble"); + return Mangled; + case 'c': + Mangled++; + Decl->append("creal"); + return Mangled; + + // Other types + case 'b': + Mangled++; + Decl->append("bool"); + return Mangled; + + case 'a': + Mangled++; + Decl->append("char"); + return Mangled; + case 'u': + Mangled++; + Decl->append("wchar"); + return Mangled; + case 'w': + Mangled++; + Decl->append("dchar"); + return Mangled; + + case 'z': + Mangled++; + + switch (*Mangled) { + case 'i': + Mangled++; + Decl->append("cent"); + return Mangled; + case 'k': + Mangled++; + Decl->append("ucent"); + return Mangled; + } + return nullptr; + + // TODO: Parse back referenced types + + default: // unhandled + return nullptr; + } +} + const char *Demangler::parseLName(OutputString *Decl, const char *Mangled, unsigned long Len) { switch (Len) { diff --git a/llvm/unittests/Demangle/DLangDemangleTest.cpp b/llvm/unittests/Demangle/DLangDemangleTest.cpp --- a/llvm/unittests/Demangle/DLangDemangleTest.cpp +++ b/llvm/unittests/Demangle/DLangDemangleTest.cpp @@ -34,7 +34,11 @@ {"_D8demangle4test6__vtblZ", "vtable for demangle.test"}, {"_D8demangle4test7__ClassZ", "ClassInfo for demangle.test"}, {"_D8demangle4test11__InterfaceZ", "Interface for demangle.test"}, - {"_D8demangle4test12__ModuleInfoZ", "ModuleInfo for demangle.test"} + {"_D8demangle4test12__ModuleInfoZ", "ModuleInfo for demangle.test"}, + {"_D8demangle1ii", "demangle.i"}, + {"_D8demangle2siOi", "demangle.si"}, + {"_D8demangle1re", "demangle.r"}, + {"_D8demangle1iinvalidtypeseq", nullptr} }; for (ExpectedVal Val : ExpectedArray) {