[Demangle][Rust] Parse dyn-trait-assoc-binding
authorTomasz Miąsko <tomasz.miasko@gmail.com>
Mon, 7 Jun 2021 16:14:06 +0000 (18:14 +0200)
committerTomasz Miąsko <tomasz.miasko@gmail.com>
Mon, 7 Jun 2021 16:18:31 +0000 (18:18 +0200)
Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D103364

llvm/include/llvm/Demangle/RustDemangle.h
llvm/lib/Demangle/RustDemangle.cpp
llvm/test/Demangle/rust.test

index 1302203f6f88760c6afd0eab526ed32807c24c52..c2372cd8acb12e301e0be17e0a3653fe8e21a57a 100644 (file)
@@ -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 @@ public:
   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();
index cbb52fa43b18c5766743d0af7f2eeab84ed0a44b..9513a00628d1a8a398808384b2976ce5bfff30e6 100644 (file)
@@ -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.
 //
 // <path> = "C" <identifier>               // crate root
 //        | "M" <impl-path> <type>         // <T> (inherent impl)
@@ -135,10 +138,10 @@ bool Demangler::demangle(StringView Mangled) {
 //      | "S"      // shim
 //      | <A-Z>    // other special namespaces
 //      | <a-z>    // internal namespaces
-void Demangler::demanglePath(InType InType) {
+bool Demangler::demanglePath(InType InType, LeaveOpen LeaveOpen) {
   if (Error || RecursionLevel >= MaxRecursionLevel) {
     Error = true;
-    return;
+    return false;
   }
   SwapAndRestore<size_t> 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;
 }
 
 // <impl-path> = [<disambiguator>] <path>
@@ -555,8 +563,20 @@ void Demangler::demangleDynBounds() {
 // <dyn-trait> = <path> {<dyn-trait-assoc-binding>}
 // <dyn-trait-assoc-binding> = "p" <undisambiguated-identifier> <type>
 void Demangler::demangleDynTrait() {
-  demanglePath(InType::Yes);
-  // FIXME demangle {<dyn-trait-assoc-binding>}
+  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.
index 59b41f68d51173fc368b30071b67bb12376c9ef1..04af35b76d6e390f146d0616150713a36fb2fed0 100644 (file)
@@ -252,6 +252,15 @@ CHECK: trait::<dyn Display + Send + Sync>
 CHECK: trait::<dyn for<'a> Display>
        _RIC5traitDG_C7DisplayEL_E
 
+CHECK: trait::<dyn IntoIterator<_, Item = _>>
+       _RIC5traitDIC12IntoIteratorpEp4ItempEL_E
+
+CHECK: trait::<dyn IntoIterator<Item = _>>
+       _RIC5traitDC12IntoIteratorp4ItempEL_E
+
+CHECK: trait::<dyn IntoIterator<Item = _, IntoIter = _>>
+       _RIC5traitDC12IntoIteratorp4Itempp8IntoIterpEL_E
+
 ; Invalid trait object, missing lifetime.
 
 CHECK: _RIC5traitDEE