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 @@ -84,11 +84,13 @@ bool demangle(StringView MangledName); private: - void demanglePath(InType InType); + bool demanglePath(InType InType, bool LeaveOpen = false); void demangleImplPath(InType InType); void demangleGenericArg(); void demangleType(); void demangleFnSig(); + void demangleDynBounds(); + void demangleDynTrait(); void demangleBinder(); void demangleConst(); void demangleConstInt(); 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 @@ -121,7 +121,10 @@ 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,12 +138,13 @@ // | "S" // shim // | // other special namespaces // | // internal namespaces -void Demangler::demanglePath(InType InType) { +bool Demangler::demanglePath(InType InType, bool LeaveOpen) { if (Error || RecursionLevel >= MaxRecursionLevel) { Error = true; - return; + return false; } SwapAndRestore SaveRecursionLevel(RecursionLevel, RecursionLevel + 1); + bool IsOpen = false; switch (consume()) { case 'C': { @@ -220,7 +224,10 @@ print(", "); demangleGenericArg(); } - print(">"); + if (LeaveOpen) + IsOpen = true; + else + print(">"); break; } default: @@ -228,6 +235,8 @@ Error = true; break; } + + return IsOpen; } // = [] @@ -480,6 +489,17 @@ case 'F': demangleFnSig(); break; + case 'D': + demangleDynBounds(); + if (consumeIf('L')) { + if (auto Lifetime = parseBase62Number()) { + print(" + "); + printLifetime(Lifetime); + } + } else { + Error = true; + } + break; default: Position = Start; demanglePath(rust_demangle::InType::Yes); @@ -529,6 +549,37 @@ } } +// = [] {} "E" +void Demangler::demangleDynBounds() { + SwapAndRestore SaveBoundLifetimes(BoundLifetimes, BoundLifetimes); + print("dyn "); + demangleBinder(); + for (size_t I = 0; !Error && !consumeIf('E'); ++I) { + if (I > 0) + print(" + "); + demangleDynTrait(); + } +} + +// = {} +// = "p" +void Demangler::demangleDynTrait() { + bool IsOpen = demanglePath(InType::Yes, true /* LeaveOpen */); + 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. // // = ["G" ] 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 @@ -232,6 +232,31 @@ CHECK: function:: _RIC8functionFUK21C_cmse_nonsecure_callEuE +; Trait objects + +CHECK: trait:: + _RIC5traitDC7DisplayEL_E + +CHECK: trait:: + _RIC5traitDC7DisplayC4SendC4SyncEL_E + +CHECK: trait::> + _RIC5traitDIC8IteratorpEp4ItempEL_E + +CHECK: trait::> + _RIC5traitDC8Iteratorp4ItempEL_E + +CHECK: trait:: Display> + _RIC5traitDG_C7DisplayEL_E + +CHECK: trait:: Foo Bar + 'a>> + _RIC5traitDG_IC3FooDG_C3BarEL0_EEL_E + +; Invalid trait object, missing lifetime. + +CHECK: _RIC5traitDC7DisplayEE + _RIC5traitDC7DisplayEE + ; Binders CHECK: binders:: fn(&'a _)>