diff --git a/llvm/include/llvm/Demangle/RustDemangle.h b/llvm/include/llvm/Demangle/RustDemangle.h --- a/llvm/include/llvm/Demangle/RustDemangle.h +++ b/llvm/include/llvm/Demangle/RustDemangle.h @@ -52,6 +52,11 @@ Never, }; +enum class InType { + No, + Yes, +}; + class Demangler { // Maximum recursion level. Used to avoid stack overflow. size_t MaxRecursionLevel; @@ -79,8 +84,8 @@ bool demangle(StringView MangledName); private: - void demanglePath(); - void demangleImplPath(); + void demanglePath(InType InType); + void demangleImplPath(InType InType); void demangleGenericArg(); void demangleType(); void demangleConst(); diff --git a/llvm/lib/Demangle/RustDemangle.cpp b/llvm/lib/Demangle/RustDemangle.cpp --- a/llvm/lib/Demangle/RustDemangle.cpp +++ b/llvm/lib/Demangle/RustDemangle.cpp @@ -110,7 +110,7 @@ } Input = Mangled; - demanglePath(); + demanglePath(InType::No); // FIXME parse optional . @@ -120,6 +120,8 @@ return !Error; } +// Demangles a path. InType indicates whether a path is inside a type. +// // = "C" // crate root // | "M" // (inherent impl) // | "X" // (trait impl) @@ -132,7 +134,7 @@ // | "S" // shim // | // other special namespaces // | // internal namespaces -void Demangler::demanglePath() { +void Demangler::demanglePath(InType InType) { if (Error || RecursionLevel >= MaxRecursionLevel) { Error = true; return; @@ -147,18 +149,18 @@ break; } case 'M': { - demangleImplPath(); + demangleImplPath(InType); print("<"); demangleType(); print(">"); break; } case 'X': { - demangleImplPath(); + demangleImplPath(InType); print("<"); demangleType(); print(" as "); - demanglePath(); + demanglePath(InType::Yes); print(">"); break; } @@ -166,7 +168,7 @@ print("<"); demangleType(); print(" as "); - demanglePath(); + demanglePath(InType::Yes); print(">"); break; } @@ -176,7 +178,7 @@ Error = true; break; } - demanglePath(); + demanglePath(InType); uint64_t Disambiguator = parseOptionalBase62Number('s'); Identifier Ident = parseIdentifier(); @@ -207,8 +209,11 @@ break; } case 'I': { - demanglePath(); - print("::<"); + demanglePath(InType); + // Omit "::" when in a type, where it is optional. + if (InType == InType::No) + print("::"); + print("<"); for (size_t I = 0; !Error && !consumeIf('E'); ++I) { if (I > 0) print(", "); @@ -226,10 +231,10 @@ // = [] // = "s" -void Demangler::demangleImplPath() { +void Demangler::demangleImplPath(InType InType) { SwapAndRestore SavePrint(Print, false); parseOptionalBase62Number('s'); - demanglePath(); + demanglePath(InType); } // = @@ -416,11 +421,14 @@ // | "D" // dyn Trait + Send + 'a // | // backref void Demangler::demangleType() { + char C = look(); BasicType Type; - if (parseBasicType(consume(), Type)) - printBasicType(Type); - else - Error = true; // FIXME parse remaining productions. + if (parseBasicType(C, Type)) { + consume(); + return printBasicType(Type); + } + + demanglePath(InType::Yes); } // = diff --git a/llvm/test/Demangle/rust.test b/llvm/test/Demangle/rust.test --- a/llvm/test/Demangle/rust.test +++ b/llvm/test/Demangle/rust.test @@ -135,6 +135,26 @@ CHECK: basic:: _RIC5basiczE +; Named types. Test possible paths productions. + +CHECK: named:: + _RIC5namedC4nameE + +CHECK: named::<<_>> + _RIC5namedMC5cratepE + +CHECK: named::<<_ as Name>> + _RIC5namedXC5cratepC4NameE + +CHECK: named::<<_ as Name>> + _RIC5namedYpC4NameE + +CHECK: named:: + _RIC5namedNvC4name4NameE + +CHECK: named::> + _RIC5namedIC4NameEE + ; Integer constants. Test value demangling. CHECK: integer::<0>