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 @@ -97,6 +97,21 @@ void demangleConstBool(); void demangleConstChar(); + template void demangleBackref(Callable Demangler) { + uint64_t Backref = parseBase62Number(); + if (Error || Backref >= Position) { + Error = true; + return; + } + + if (!Print) + return; + + SwapAndRestore SavePosition(Position, Position); + Position = Backref; + Demangler(); + } + Identifier parseIdentifier(); uint64_t parseOptionalBase62Number(char Tag); uint64_t parseBase62Number(); 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 @@ -230,8 +230,10 @@ print(">"); break; } + case 'B': + demangleBackref([&] { IsOpen = demanglePath(InType, LeaveOpen); }); + break; default: - // FIXME parse remaining productions. Error = true; break; } @@ -432,8 +434,13 @@ // | "D" // dyn Trait + Send + 'a // | // backref void Demangler::demangleType() { - size_t Start = Position; + if (Error || RecursionLevel >= MaxRecursionLevel) { + Error = true; + return; + } + SwapAndRestore SaveRecursionLevel(RecursionLevel, RecursionLevel + 1); + size_t Start = Position; char C = consume(); BasicType Type; if (parseBasicType(C, Type)) @@ -500,6 +507,9 @@ Error = true; } break; + case 'B': + demangleBackref([&] { demangleType(); }); + break; default: Position = Start; demanglePath(rust_demangle::InType::Yes); @@ -611,8 +621,15 @@ // | "p" // placeholder // | void Demangler::demangleConst() { + if (Error || RecursionLevel >= MaxRecursionLevel) { + Error = true; + return; + } + SwapAndRestore SaveRecursionLevel(RecursionLevel, RecursionLevel + 1); + + char C = consume(); BasicType Type; - if (parseBasicType(consume(), Type)) { + if (parseBasicType(C, Type)) { switch (Type) { case BasicType::I8: case BasicType::I16: @@ -638,10 +655,11 @@ print('_'); break; default: - // FIXME demangle backreferences. Error = true; break; } + } else if (C == 'B') { + demangleBackref([&] { demangleConst(); }); } else { Error = true; } 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 @@ -415,6 +415,28 @@ CHECK: _RIC4charKc1234567_E _RIC4charKc1234567_E +; Backreferences + +CHECK: backref::<7, 7> + _RIC7backrefKi7_KBa_E + +CHECK: backref::<(), ()> + _RIC7backrefuB9_E + +CHECK: backref:: + _RIC7backrefNvB0_5identE + +; Invalid backreferences + +CHECK: _RB_ + _RB_ + +CHECK: _RB5_ + _RB5_ + +CHECK: _RNvB_1a + _RNvB_1a + ; Invalid mangled characters CHECK: _RNvC2a.1c