diff --git a/llvm/include/llvm/Demangle/RustDemangle.h b/llvm/include/llvm/Demangle/RustDemangle.h index 1302203f6f8876..c2372cd8acb12e 100644 --- a/llvm/include/llvm/Demangle/RustDemangle.h +++ b/llvm/include/llvm/Demangle/RustDemangle.h @@ -57,6 +57,11 @@ enum class InType { Yes, }; +enum class LeaveOpen { + No, + Yes, +}; + class Demangler { // Maximum recursion level. Used to avoid stack overflow. size_t MaxRecursionLevel; @@ -84,7 +89,7 @@ class Demangler { bool demangle(StringView MangledName); private: - void demanglePath(InType InType); + bool demanglePath(InType InType, LeaveOpen LeaveOpen = LeaveOpen::No); void demangleImplPath(InType InType); void demangleGenericArg(); void demangleType(); diff --git a/llvm/lib/Demangle/RustDemangle.cpp b/llvm/lib/Demangle/RustDemangle.cpp index cbb52fa43b18c5..9513a00628d1a8 100644 --- a/llvm/lib/Demangle/RustDemangle.cpp +++ b/llvm/lib/Demangle/RustDemangle.cpp @@ -121,7 +121,10 @@ bool Demangler::demangle(StringView Mangled) { return !Error; } -// Demangles a path. InType indicates whether a path is inside a type. +// Demangles a path. InType indicates whether a path is inside a type. When +// LeaveOpen is true, a closing `>` after generic arguments is omitted from the +// output. Return value indicates whether generics arguments have been left +// open. // // = "C" // crate root // | "M" // (inherent impl) @@ -135,10 +138,10 @@ bool Demangler::demangle(StringView Mangled) { // | "S" // shim // | // other special namespaces // | // internal namespaces -void Demangler::demanglePath(InType InType) { +bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) { if (Error || RecursionLevel >= MaxRecursionLevel) { Error = true; - return; + return false; } SwapAndRestore SaveRecursionLevel(RecursionLevel, RecursionLevel + 1); @@ -220,7 +223,10 @@ void Demangler::demanglePath(InType InType) { print(", "); demangleGenericArg(); } - print(">"); + if (LeaveOpen == rust_demangle::LeaveOpen::Yes) + return true; + else + print(">"); break; } default: @@ -228,6 +234,8 @@ void Demangler::demanglePath(InType InType) { Error = true; break; } + + return false; } // = [] @@ -555,8 +563,20 @@ void Demangler::demangleDynBounds() { // = {} // = "p" void Demangler::demangleDynTrait() { - demanglePath(InType::Yes); - // FIXME demangle {} + bool IsOpen = demanglePath(InType::Yes, LeaveOpen::Yes); + while (!Error && consumeIf('p')) { + if (!IsOpen) { + IsOpen = true; + print('<'); + } else { + print(", "); + } + print(parseIdentifier().Name); + print(" = "); + demangleType(); + } + if (IsOpen) + print(">"); } // Demangles optional binder and updates the number of bound lifetimes. diff --git a/llvm/test/Demangle/rust.test b/llvm/test/Demangle/rust.test index 59b41f68d51173..04af35b76d6e39 100644 --- a/llvm/test/Demangle/rust.test +++ b/llvm/test/Demangle/rust.test @@ -252,6 +252,15 @@ CHECK: trait:: CHECK: trait:: Display> _RIC5traitDG_C7DisplayEL_E +CHECK: trait::> + _RIC5traitDIC12IntoIteratorpEp4ItempEL_E + +CHECK: trait::> + _RIC5traitDC12IntoIteratorp4ItempEL_E + +CHECK: trait::> + _RIC5traitDC12IntoIteratorp4Itempp8IntoIterpEL_E + ; Invalid trait object, missing lifetime. CHECK: _RIC5traitDEE