Index: llvm/lib/Demangle/DLangDemangle.cpp =================================================================== --- llvm/lib/Demangle/DLangDemangle.cpp +++ llvm/lib/Demangle/DLangDemangle.cpp @@ -173,12 +173,15 @@ /// /// \param Decl output buffer to write the demangled name /// \param Mangled mangled symbol to be demangled + /// \param IsFunction whether the backreferenced type is expected to be a + /// function /// /// \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(OutputString *Decl, const char *Mangled); + const char *parseTypeBackref(OutputString *Decl, const char *Mangled, + bool IsFunction); /// Check whether it is a function calling convention /// @@ -548,7 +551,8 @@ return Mangled; } -const char *Demangler::parseTypeBackref(OutputString *Decl, const char *Mangled) { +const char *Demangler::parseTypeBackref(OutputString *Decl, const char *Mangled, + bool IsFunction) { /* A type back reference always points to a letter. TypeBackRef: Q NumberBackRef @@ -567,8 +571,11 @@ // Get position of the back reference Mangled = decodeBackref(Mangled, &Backref); - // TODO: Add support for function type back references - Backref = parseType(Decl, Backref); + // Must point to a type + if (IsFunction) + Backref = parseFunctionType(Decl, Backref); + else + Backref = parseType(Decl, Backref); LastBackref = SaveRefPos; @@ -1132,7 +1139,27 @@ Mangled++; return parseQualified(Decl, Mangled, false); - // TODO: Parse delegate types + case 'D': /* delegate T */ + { + OutputString Mods = OutputString(); + size_t Szmods; + Mangled++; + + Mangled = parseTypeModifiers(&Mods, Mangled); + Szmods = Mods.getLength(); + + // Back referenced function type + if (Mangled && *Mangled == 'Q') + Mangled = parseTypeBackref(Decl, Mangled, true); + else + Mangled = parseFunctionType(Decl, Mangled); + + Decl->append("delegate"); + Decl->append(Mods.Buffer, Szmods); + + Mods.free(); + return Mangled; + } case 'B': /* tuple T */ Mangled++; @@ -1262,7 +1289,7 @@ // Back referenced type case 'Q': - return parseTypeBackref(Decl, Mangled); + return parseTypeBackref(Decl, Mangled, false); default: // unhandled return nullptr; Index: llvm/unittests/Demangle/DLangDemangleTest.cpp =================================================================== --- llvm/unittests/Demangle/DLangDemangleTest.cpp +++ llvm/unittests/Demangle/DLangDemangleTest.cpp @@ -135,7 +135,114 @@ {"_D8demangle4testFB1aZv", "demangle.test(tuple(char))"}, {"_D8demangle4testFB2aaZv", "demangle.test(tuple(char, char))"}, {"_D8demangle4testFB3aaaZv", "demangle.test(tuple(char, char, char))"}, - {"_D8demangle4testFB2OaaZv", "demangle.test(tuple(shared(char), char))"} + {"_D8demangle4testFB2OaaZv", "demangle.test(tuple(shared(char), char))"}, + {"_D8demangle4testFB3aDFZaaZv", + "demangle.test(tuple(char, char() delegate, char))"}, + {"_D8demangle4testFDFZaZv", "demangle.test(char() delegate)"}, + {"_D8demangle4testFDUZaZv", "demangle.test(extern(C) char() delegate)"}, + {"_D8demangle4testFDWZaZv", + "demangle.test(extern(Windows) char() delegate)"}, + {"_D8demangle4testFDVZaZv", + "demangle.test(extern(Pascal) char() delegate)"}, + {"_D8demangle4testFDRZaZv", "demangle.test(extern(C++) char() delegate)"}, + {"_D8demangle4testFDYZaZv", + "demangle.test(extern(Objective-C) char() delegate)"}, + {"_D8demangle4testFPFZaZv", "demangle.test(char() function)"}, + {"_D8demangle4testFPUZaZv", "demangle.test(extern(C) char() function)"}, + {"_D8demangle4testFPWZaZv", + "demangle.test(extern(Windows) char() function)"}, + {"_D8demangle4testFPVZaZv", + "demangle.test(extern(Pascal) char() function)"}, + {"_D8demangle4testFPRZaZv", "demangle.test(extern(C++) char() function)"}, + {"_D8demangle4testFPYZaZv", + "demangle.test(extern(Objective-C) char() function)"}, + {"_D8demangle4testFDFNaZaZv", "demangle.test(char() pure delegate)"}, + {"_D8demangle4testFDFNbZaZv", "demangle.test(char() nothrow delegate)"}, + {"_D8demangle4testFDFNcZaZv", "demangle.test(char() ref delegate)"}, + {"_D8demangle4testFDFNdZaZv", "demangle.test(char() @property delegate)"}, + {"_D8demangle4testFDFNeZaZv", "demangle.test(char() @trusted delegate)"}, + {"_D8demangle4testFDFNfZaZv", "demangle.test(char() @safe delegate)"}, + {"_D8demangle4testFDFNiZaZv", "demangle.test(char() @nogc delegate)"}, + {"_D8demangle4testFDFNmZaZv", "demangle.test(char() @live delegate)"}, + {"_D8demangle4testFDFNaNbZaZv", + "demangle.test(char() pure nothrow delegate)"}, + {"_D8demangle4testFDFNbNaZaZv", + "demangle.test(char() nothrow pure delegate)"}, + {"_D8demangle4testFDFNdNfNaZaZv", + "demangle.test(char() @property @safe pure delegate)"}, + {"_D8demangle4testFNjDFZaZv", "demangle.test(char() delegate)"}, + {"_D8demangle4testFNkDFZaZv", "demangle.test(return char() delegate)"}, + {"_D8demangle4testFDFNjZaZv", "demangle.test(char() return delegate)"}, + {"_D8demangle4testFNjNkDFNjZaZv", + "demangle.test(return char() return delegate)"}, + {"_D8demangle4testFNlDFZaZv", "demangle.test(char() delegate)"}, + {"_D8demangle4testFMDFZaZv", "demangle.test(scope char() delegate)"}, + {"_D8demangle4testFDFNlZaZv", "demangle.test(char() scope delegate)"}, + {"_D8demangle4testFMDFNlZaZv", + "demangle.test(scope char() scope delegate)"}, + {"_D8demangle4testFNlMDFNlZaZv", + "demangle.test(scope char() scope delegate)"}, + {"_D8demangle4testFPFNaZaZv", "demangle.test(char() pure function)"}, + {"_D8demangle4testFPFNbZaZv", "demangle.test(char() nothrow function)"}, + {"_D8demangle4testFPFNcZaZv", "demangle.test(char() ref function)"}, + {"_D8demangle4testFPFNdZaZv", "demangle.test(char() @property function)"}, + {"_D8demangle4testFPFNeZaZv", "demangle.test(char() @trusted function)"}, + {"_D8demangle4testFPFNfZaZv", "demangle.test(char() @safe function)"}, + {"_D8demangle4testFPFNiZaZv", "demangle.test(char() @nogc function)"}, + {"_D8demangle4testFPFNmZaZv", "demangle.test(char() @live function)"}, + {"_D8demangle4testFPFNaNbZaZv", + "demangle.test(char() pure nothrow function)"}, + {"_D8demangle4testFPFNbNaZaZv", + "demangle.test(char() nothrow pure function)"}, + {"_D8demangle4testFPFNdNfNaZaZv", + "demangle.test(char() @property @safe pure function)"}, + {"_D8demangle4testFNjPFZaZv", "demangle.test(char() function)"}, + {"_D8demangle4testFNkPFZaZv", "demangle.test(return char() function)"}, + {"_D8demangle4testFPFNjZaZv", "demangle.test(char() return function)"}, + {"_D8demangle4testFNjNkPFNjZaZv", + "demangle.test(return char() return function)"}, + {"_D8demangle4testFNlPFZaZv", "demangle.test(char() function)"}, + {"_D8demangle4testFMPFZaZv", "demangle.test(scope char() function)"}, + {"_D8demangle4testFPFNlZaZv", "demangle.test(char() scope function)"}, + {"_D8demangle4testFMPFNlZaZv", + "demangle.test(scope char() scope function)"}, + {"_D8demangle4testFNlMPFNlZaZv", + "demangle.test(scope char() scope function)"}, + {"_D8demangle4test6__ctorMFZv", "demangle.test.this()"}, + {"_D8demangle4test6__dtorMFZv", "demangle.test.~this()"}, + {"_D8demangle4test10__postblitMFZv", "demangle.test.this(this)"}, + {"_D8demangle4testFHAbaZv", "demangle.test(char[bool[]])"}, + {"_D8demangle4testFHG42caZv", "demangle.test(char[creal[42]])"}, + {"_D8demangle4testFAiXv", "demangle.test(int[]...)"}, + {"_D8demangle4testFLAiXv", "demangle.test(lazy int[]...)"}, + {"_D8demangle4testFAiYv", "demangle.test(int[], ...)"}, + {"_D8demangle4testFLAiYv", "demangle.test(lazy int[], ...)"}, + {"_D8demangle4testFLilZv", "demangle.test(lazy int, long)"}, + {"_D8demangle4testFLliZv", "demangle.test(lazy long, int)"}, + {"_D8demangle4testFLC6ObjectLDFLiZiZi", + "demangle.test(lazy Object, lazy int(lazy int) delegate)"}, + {"_D8demangle4testMxFZv", "demangle.test() const"}, + {"_D8demangle4testMyFZv", "demangle.test() immutable"}, + {"_D8demangle4testMNgFZv", "demangle.test() inout"}, + {"_D8demangle4testMNgxFZv", "demangle.test() inout const"}, + {"_D8demangle4testMOFZv", "demangle.test() shared"}, + {"_D8demangle4testMOxFZv", "demangle.test() shared const"}, + {"_D8demangle4testMONgFZv", "demangle.test() shared inout"}, + {"_D8demangle4testMONgxFZv", "demangle.test() shared inout const"}, + {"_D8demangle4testFDxFZaZv", "demangle.test(char() delegate const)"}, + {"_D8demangle4testFDyFZaZv", "demangle.test(char() delegate immutable)"}, + {"_D8demangle4testFDNgFZaZv", "demangle.test(char() delegate inout)"}, + {"_D8demangle4testFDNgxFZaZv", + "demangle.test(char() delegate inout const)"}, + {"_D8demangle4testFDOFZaZv", "demangle.test(char() delegate shared)"}, + {"_D8demangle4testFDOxFZaZv", + "demangle.test(char() delegate shared const)"}, + {"_D8demangle4testFDONgFZaZv", + "demangle.test(char() delegate shared inout)"}, + {"_D8demangle4testFDONgxFZaZv", + "demangle.test(char() delegate shared inout const)"}, + {"_D8demangle004testFaZv", "demangle.test(char)"}, + {"_D8demangle000000004testFaZv", "demangle.test(char)"} }; for (ExpectedVal Val : ExpectedArray) {