[MS Demangler] NFC - Remove state from Demangler class.
authorZachary Turner <zturner@google.com>
Sun, 29 Jul 2018 16:38:02 +0000 (16:38 +0000)
committerZachary Turner <zturner@google.com>
Sun, 29 Jul 2018 16:38:02 +0000 (16:38 +0000)
We need to be able to initiate a nested demangling from inside
of an "outer" demangling.  These need to be able to share some
state, such as back-references.  As a result, we can't store
things like the output stream or the mangled name in the Demangler
class, since each demangling will have different values.  So
remove this state and pass it through the necessary methods.

llvm-svn: 338219

llvm/lib/Demangle/MicrosoftDemangle.cpp

index 6e187854d75147901326f7c2564decbbe84f75fd..551bcdcb6206f60b4cfb63b0f05c61cf245dd7fd 100644 (file)
@@ -716,6 +716,11 @@ void ArrayType::outputPost(OutputStream &OS) {
     Type::outputPost(OS, *ElementType);
 }
 
+struct Symbol {
+  Name *SymbolName = nullptr;
+  Type *SymbolType = nullptr;
+};
+
 } // namespace
 
 namespace {
@@ -725,74 +730,62 @@ namespace {
 // It also has a set of functions to cnovert Type instances to strings.
 class Demangler {
 public:
-  Demangler(OutputStream &OS, StringView s) : OS(OS), MangledName(s) {}
+  Demangler() = default;
 
   // You are supposed to call parse() first and then check if error is true.  If
   // it is false, call output() to write the formatted name to the given stream.
-  void parse();
-  void output();
+  Symbol *parse(StringView &MangledName);
+  void output(const Symbol *S, OutputStream &OS);
 
   // True if an error occurred.
   bool Error = false;
 
 private:
-  Type *demangleVariableEncoding();
-  Type *demangleFunctionEncoding();
+  Type *demangleVariableEncoding(StringView &MangledName);
+  Type *demangleFunctionEncoding(StringView &MangledName);
 
-  Qualifiers demanglePointerExtQualifiers();
+  Qualifiers demanglePointerExtQualifiers(StringView &MangledName);
 
   // Parser functions. This is a recursive-descent parser.
-  Type *demangleType(QualifierMangleMode QMM);
-  Type *demangleBasicType();
-  UdtType *demangleClassType();
-  PointerType *demanglePointerType();
-  MemberPointerType *demangleMemberPointerType();
-  FunctionType *demangleFunctionType(bool HasThisQuals, bool IsFunctionPointer);
+  Type *demangleType(StringView &MangledName, QualifierMangleMode QMM);
+  Type *demangleBasicType(StringView &MangledName);
+  UdtType *demangleClassType(StringView &MangledName);
+  PointerType *demanglePointerType(StringView &MangledName);
+  MemberPointerType *demangleMemberPointerType(StringView &MangledName);
+  FunctionType *demangleFunctionType(StringView &MangledName, bool HasThisQuals,
+                                     bool IsFunctionPointer);
 
-  ArrayType *demangleArrayType();
+  ArrayType *demangleArrayType(StringView &MangledName);
 
-  ParamList demangleTemplateParameterList();
-  ParamList demangleFunctionParameterList();
+  ParamList demangleTemplateParameterList(StringView &MangledName);
+  ParamList demangleFunctionParameterList(StringView &MangledName);
 
-  int demangleNumber();
+  int demangleNumber(StringView &MangledName);
 
   void memorizeString(StringView s);
-  Name *demangleFullyQualifiedTypeName();
-  Name *demangleFullyQualifiedSymbolName();
-
-  Name *demangleUnqualifiedTypeName();
-  Name *demangleUnqualifiedSymbolName();
+  Name *demangleFullyQualifiedTypeName(StringView &MangledName);
+  Name *demangleFullyQualifiedSymbolName(StringView &MangledName);
 
-  Name *demangleNameScopeChain(Name *UnqualifiedName);
-  Name *demangleNameScopePiece();
+  Name *demangleUnqualifiedTypeName(StringView &MangledName);
+  Name *demangleUnqualifiedSymbolName(StringView &MangledName);
 
-  Name *demangleBackRefName();
-  Name *demangleClassTemplateName();
-  Name *demangleOperatorName();
-  Name *demangleSimpleName(bool Memorize);
-  Name *demangleAnonymousNamespaceName();
+  Name *demangleNameScopeChain(StringView &MangledName, Name *UnqualifiedName);
+  Name *demangleNameScopePiece(StringView &MangledName);
 
-  void demangleOperator(Name *);
-  FuncClass demangleFunctionClass();
-  CallingConv demangleCallingConvention();
-  StorageClass demangleVariableStorageClass();
-  ReferenceKind demangleReferenceKind();
-  void demangleThrowSpecification();
+  Name *demangleBackRefName(StringView &MangledName);
+  Name *demangleClassTemplateName(StringView &MangledName);
+  Name *demangleOperatorName(StringView &MangledName);
+  Name *demangleSimpleName(StringView &MangledName, bool Memorize);
+  Name *demangleAnonymousNamespaceName(StringView &MangledName);
 
-  std::pair<Qualifiers, bool> demangleQualifiers();
+  void demangleOperator(StringView &MangledName, Name *);
+  FuncClass demangleFunctionClass(StringView &MangledName);
+  CallingConv demangleCallingConvention(StringView &MangledName);
+  StorageClass demangleVariableStorageClass(StringView &MangledName);
+  ReferenceKind demangleReferenceKind(StringView &MangledName);
+  void demangleThrowSpecification(StringView &MangledName);
 
-  // The result is written to this stream.
-  OutputStream OS;
-
-  // Mangled symbol. demangle* functions shorten this string
-  // as they parse it.
-  StringView MangledName;
-
-  // A parsed mangled symbol.
-  Type *SymbolType = nullptr;
-
-  // The main symbol name. (e.g. "ns::foo" in "int ns::foo()".)
-  Name *SymbolName = nullptr;
+  std::pair<Qualifiers, bool> demangleQualifiers(StringView &MangledName);
 
   // Memory allocator.
   ArenaAllocator Arena;
@@ -821,27 +814,28 @@ private:
 } // namespace
 
 // Parser entry point.
-void Demangler::parse() {
+Symbol *Demangler::parse(StringView &MangledName) {
+  Symbol *S = Arena.alloc<Symbol>();
+
   // MSVC-style mangled symbols must start with '?'.
   if (!MangledName.consumeFront("?")) {
-    SymbolName = Arena.alloc<Name>();
-    SymbolName->Str = MangledName;
-    SymbolType = Arena.alloc<Type>();
-    SymbolType->Prim = PrimTy::Unknown;
+    S->SymbolName = Arena.alloc<Name>();
+    S->SymbolName->Str = MangledName;
+    S->SymbolType = Arena.alloc<Type>();
+    S->SymbolType->Prim = PrimTy::Unknown;
+    return S;
   }
 
   // What follows is a main symbol name. This may include
   // namespaces or class BackReferences.
-  SymbolName = demangleFullyQualifiedSymbolName();
+  S->SymbolName = demangleFullyQualifiedSymbolName(MangledName);
 
   // Read a variable.
-  if (startsWithDigit(MangledName)) {
-    SymbolType = demangleVariableEncoding();
-    return;
-  }
+  S->SymbolType = startsWithDigit(MangledName)
+                      ? demangleVariableEncoding(MangledName)
+                      : demangleFunctionEncoding(MangledName);
 
-  // Read a function.
-  SymbolType = demangleFunctionEncoding();
+  return S;
 }
 
 // <type-encoding> ::= <storage-class> <variable-type>
@@ -851,10 +845,10 @@ void Demangler::parse() {
 //                 ::= 3  # global
 //                 ::= 4  # static local
 
-Type *Demangler::demangleVariableEncoding() {
-  StorageClass SC = demangleVariableStorageClass();
+Type *Demangler::demangleVariableEncoding(StringView &MangledName) {
+  StorageClass SC = demangleVariableStorageClass(MangledName);
 
-  Type *Ty = demangleType(QualifierMangleMode::Drop);
+  Type *Ty = demangleType(MangledName, QualifierMangleMode::Drop);
 
   Ty->Storage = SC;
 
@@ -865,14 +859,15 @@ Type *Demangler::demangleVariableEncoding() {
   case PrimTy::Ref:
   case PrimTy::MemberPtr: {
     Qualifiers ExtraChildQuals = Q_None;
-    Ty->Quals = Qualifiers(Ty->Quals | demanglePointerExtQualifiers());
+    Ty->Quals =
+        Qualifiers(Ty->Quals | demanglePointerExtQualifiers(MangledName));
 
     bool IsMember = false;
-    std::tie(ExtraChildQuals, IsMember) = demangleQualifiers();
+    std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(MangledName);
 
     if (Ty->Prim == PrimTy::MemberPtr) {
       assert(IsMember);
-      Name *BackRefName = demangleFullyQualifiedTypeName();
+      Name *BackRefName = demangleFullyQualifiedTypeName(MangledName);
       (void)BackRefName;
       MemberPointerType *MPTy = static_cast<MemberPointerType *>(Ty);
       MPTy->Pointee->Quals = Qualifiers(MPTy->Pointee->Quals | ExtraChildQuals);
@@ -884,7 +879,7 @@ Type *Demangler::demangleVariableEncoding() {
     break;
   }
   default:
-    Ty->Quals = demangleQualifiers().first;
+    Ty->Quals = demangleQualifiers(MangledName).first;
     break;
   }
 
@@ -902,7 +897,7 @@ Type *Demangler::demangleVariableEncoding() {
 //                        ::= <hex digit>+ @  # when Numbrer == 0 or >= 10
 //
 // <hex-digit>            ::= [A-P]           # A = 0, B = 1, ...
-int Demangler::demangleNumber() {
+int Demangler::demangleNumber(StringView &MangledName) {
   bool neg = MangledName.consumeFront("?");
 
   if (startsWithDigit(MangledName)) {
@@ -940,7 +935,7 @@ void Demangler::memorizeString(StringView S) {
   BackReferences[BackRefCount++] = S;
 }
 
-Name *Demangler::demangleBackRefName() {
+Name *Demangler::demangleBackRefName(StringView &MangledName) {
   assert(startsWithDigit(MangledName));
 
   size_t I = MangledName[0] - '0';
@@ -955,20 +950,20 @@ Name *Demangler::demangleBackRefName() {
   return Node;
 }
 
-Name *Demangler::demangleClassTemplateName() {
+Name *Demangler::demangleClassTemplateName(StringView &MangledName) {
   assert(MangledName.startsWith("?$"));
   MangledName.consumeFront("?$");
 
-  Name *Node = demangleSimpleName(false);
-  Node->TemplateParams = demangleTemplateParameterList();
+  Name *Node = demangleSimpleName(MangledName, false);
+  Node->TemplateParams = demangleTemplateParameterList(MangledName);
   return Node;
 }
 
-Name *Demangler::demangleOperatorName() {
+Name *Demangler::demangleOperatorName(StringView &MangledName) {
   assert(MangledName.startsWith('?'));
   MangledName.consumeFront('?');
 
-  auto NameString = [this]() -> StringView {
+  auto NameString = [this, &MangledName]() -> StringView {
     switch (MangledName.popFront()) {
     case '0':
       return "ctor";
@@ -1078,7 +1073,7 @@ Name *Demangler::demangleOperatorName() {
   return Node;
 }
 
-Name *Demangler::demangleSimpleName(bool Memorize) {
+Name *Demangler::demangleSimpleName(StringView &MangledName, bool Memorize) {
   Name *Node = Arena.alloc<Name>();
   for (size_t i = 0; i < MangledName.size(); ++i) {
     if (MangledName[i] != '@')
@@ -1095,7 +1090,7 @@ Name *Demangler::demangleSimpleName(bool Memorize) {
   return nullptr;
 }
 
-Name *Demangler::demangleAnonymousNamespaceName() {
+Name *Demangler::demangleAnonymousNamespaceName(StringView &MangledName) {
   assert(MangledName.startsWith("?A"));
   MangledName.consumeFront("?A");
 
@@ -1109,11 +1104,11 @@ Name *Demangler::demangleAnonymousNamespaceName() {
 }
 
 // Parses a type name in the form of A@B@C@@ which represents C::B::A.
-Name *Demangler::demangleFullyQualifiedTypeName() {
-  Name *TypeName = demangleUnqualifiedTypeName();
+Name *Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) {
+  Name *TypeName = demangleUnqualifiedTypeName(MangledName);
   assert(TypeName);
 
-  Name *QualName = demangleNameScopeChain(TypeName);
+  Name *QualName = demangleNameScopeChain(MangledName, TypeName);
   assert(QualName);
   return QualName;
 }
@@ -1121,49 +1116,50 @@ Name *Demangler::demangleFullyQualifiedTypeName() {
 // Parses a symbol name in the form of A@B@C@@ which represents C::B::A.
 // Symbol names have slightly different rules regarding what can appear
 // so we separate out the implementations for flexibility.
-Name *Demangler::demangleFullyQualifiedSymbolName() {
-  Name *SymbolName = demangleUnqualifiedSymbolName();
+Name *Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) {
+  Name *SymbolName = demangleUnqualifiedSymbolName(MangledName);
   assert(SymbolName);
 
-  Name *QualName = demangleNameScopeChain(SymbolName);
+  Name *QualName = demangleNameScopeChain(MangledName, SymbolName);
   assert(QualName);
   return QualName;
 }
 
-Name *Demangler::demangleUnqualifiedTypeName() {
+Name *Demangler::demangleUnqualifiedTypeName(StringView &MangledName) {
   // An inner-most name can be a back-reference, because a fully-qualified name
   // (e.g. Scope + Inner) can contain other fully qualified names inside of
   // them (for example template parameters), and these nested parameters can
   // refer to previously mangled types.
   if (startsWithDigit(MangledName))
-    return demangleBackRefName();
+    return demangleBackRefName(MangledName);
 
   if (MangledName.startsWith("?$"))
-    return demangleClassTemplateName();
+    return demangleClassTemplateName(MangledName);
 
-  return demangleSimpleName(true);
+  return demangleSimpleName(MangledName, true);
 }
 
-Name *Demangler::demangleUnqualifiedSymbolName() {
+Name *Demangler::demangleUnqualifiedSymbolName(StringView &MangledName) {
   if (MangledName.startsWith('?'))
-    return demangleOperatorName();
-  return demangleSimpleName(true);
+    return demangleOperatorName(MangledName);
+  return demangleSimpleName(MangledName, true);
 }
 
-Name *Demangler::demangleNameScopePiece() {
+Name *Demangler::demangleNameScopePiece(StringView &MangledName) {
   if (startsWithDigit(MangledName))
-    return demangleBackRefName();
+    return demangleBackRefName(MangledName);
 
   if (MangledName.startsWith("?$"))
-    return demangleClassTemplateName();
+    return demangleClassTemplateName(MangledName);
 
   if (MangledName.startsWith("?A"))
-    return demangleAnonymousNamespaceName();
+    return demangleAnonymousNamespaceName(MangledName);
 
-  return demangleSimpleName(true);
+  return demangleSimpleName(MangledName, true);
 }
 
-Name *Demangler::demangleNameScopeChain(Name *UnqualifiedName) {
+Name *Demangler::demangleNameScopeChain(StringView &MangledName,
+                                        Name *UnqualifiedName) {
   Name *Head = UnqualifiedName;
 
   while (!MangledName.consumeFront("@")) {
@@ -1173,7 +1169,7 @@ Name *Demangler::demangleNameScopeChain(Name *UnqualifiedName) {
     }
 
     assert(!Error);
-    Name *Elem = demangleNameScopePiece();
+    Name *Elem = demangleNameScopePiece(MangledName);
     if (Error)
       return nullptr;
 
@@ -1183,7 +1179,7 @@ Name *Demangler::demangleNameScopeChain(Name *UnqualifiedName) {
   return Head;
 }
 
-FuncClass Demangler::demangleFunctionClass() {
+FuncClass Demangler::demangleFunctionClass(StringView &MangledName) {
   SwapAndRestore<StringView> RestoreOnError(MangledName, MangledName);
   RestoreOnError.shouldRestore(false);
 
@@ -1235,7 +1231,7 @@ FuncClass Demangler::demangleFunctionClass() {
   return Public;
 }
 
-CallingConv Demangler::demangleCallingConvention() {
+CallingConv Demangler::demangleCallingConvention(StringView &MangledName) {
   switch (MangledName.popFront()) {
   case 'A':
   case 'B':
@@ -1265,7 +1261,7 @@ CallingConv Demangler::demangleCallingConvention() {
   return CallingConv::None;
 }
 
-StorageClass Demangler::demangleVariableStorageClass() {
+StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) {
   assert(std::isdigit(MangledName.front()));
 
   switch (MangledName.popFront()) {
@@ -1284,7 +1280,8 @@ StorageClass Demangler::demangleVariableStorageClass() {
   return StorageClass::None;
 }
 
-std::pair<Qualifiers, bool> Demangler::demangleQualifiers() {
+std::pair<Qualifiers, bool>
+Demangler::demangleQualifiers(StringView &MangledName) {
 
   switch (MangledName.popFront()) {
   // Member qualifiers
@@ -1312,16 +1309,17 @@ std::pair<Qualifiers, bool> Demangler::demangleQualifiers() {
 
 // <variable-type> ::= <type> <cvr-qualifiers>
 //                 ::= <type> <pointee-cvr-qualifiers> # pointers, references
-Type *Demangler::demangleType(QualifierMangleMode QMM) {
+Type *Demangler::demangleType(StringView &MangledName,
+                              QualifierMangleMode QMM) {
   Qualifiers Quals = Q_None;
   bool IsMember = false;
   bool IsMemberKnown = false;
   if (QMM == QualifierMangleMode::Mangle) {
-    std::tie(Quals, IsMember) = demangleQualifiers();
+    std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
     IsMemberKnown = true;
   } else if (QMM == QualifierMangleMode::Result) {
     if (MangledName.consumeFront('?')) {
-      std::tie(Quals, IsMember) = demangleQualifiers();
+      std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
       IsMemberKnown = true;
     }
   }
@@ -1332,7 +1330,7 @@ Type *Demangler::demangleType(QualifierMangleMode QMM) {
   case 'U': // struct
   case 'V': // class
   case 'W': // enum
-    Ty = demangleClassType();
+    Ty = demangleClassType(MangledName);
     break;
   case 'A': // foo &
   case 'P': // foo *
@@ -1342,22 +1340,22 @@ Type *Demangler::demangleType(QualifierMangleMode QMM) {
     if (!IsMemberKnown)
       IsMember = isMemberPointer(MangledName);
     if (IsMember)
-      Ty = demangleMemberPointerType();
+      Ty = demangleMemberPointerType(MangledName);
     else
-      Ty = demanglePointerType();
+      Ty = demanglePointerType(MangledName);
     break;
   case 'Y':
-    Ty = demangleArrayType();
+    Ty = demangleArrayType(MangledName);
     break;
   default:
-    Ty = demangleBasicType();
+    Ty = demangleBasicType(MangledName);
     break;
   }
   Ty->Quals = Qualifiers(Ty->Quals | Quals);
   return Ty;
 }
 
-ReferenceKind Demangler::demangleReferenceKind() {
+ReferenceKind Demangler::demangleReferenceKind(StringView &MangledName) {
   if (MangledName.consumeFront('G'))
     return ReferenceKind::LValueRef;
   else if (MangledName.consumeFront('H'))
@@ -1365,53 +1363,54 @@ ReferenceKind Demangler::demangleReferenceKind() {
   return ReferenceKind::None;
 }
 
-void Demangler::demangleThrowSpecification() {
+void Demangler::demangleThrowSpecification(StringView &MangledName) {
   if (MangledName.consumeFront('Z'))
     return;
 
   Error = true;
 }
 
-FunctionType *Demangler::demangleFunctionType(bool HasThisQuals,
+FunctionType *Demangler::demangleFunctionType(StringView &MangledName,
+                                              bool HasThisQuals,
                                               bool IsFunctionPointer) {
   FunctionType *FTy = Arena.alloc<FunctionType>();
   FTy->Prim = PrimTy::Function;
   FTy->IsFunctionPointer = IsFunctionPointer;
 
   if (HasThisQuals) {
-    FTy->Quals = demanglePointerExtQualifiers();
-    FTy->RefKind = demangleReferenceKind();
-    FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers().first);
+    FTy->Quals = demanglePointerExtQualifiers(MangledName);
+    FTy->RefKind = demangleReferenceKind(MangledName);
+    FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers(MangledName).first);
   }
 
   // Fields that appear on both member and non-member functions.
-  FTy->CallConvention = demangleCallingConvention();
+  FTy->CallConvention = demangleCallingConvention(MangledName);
 
   // <return-type> ::= <type>
   //               ::= @ # structors (they have no declared return type)
   bool IsStructor = MangledName.consumeFront('@');
   if (!IsStructor)
-    FTy->ReturnType = demangleType(QualifierMangleMode::Result);
+    FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result);
 
-  FTy->Params = demangleFunctionParameterList();
+  FTy->Params = demangleFunctionParameterList(MangledName);
 
-  demangleThrowSpecification();
+  demangleThrowSpecification(MangledName);
 
   return FTy;
 }
 
-Type *Demangler::demangleFunctionEncoding() {
-  FuncClass FC = demangleFunctionClass();
+Type *Demangler::demangleFunctionEncoding(StringView &MangledName) {
+  FuncClass FC = demangleFunctionClass(MangledName);
 
   bool HasThisQuals = !(FC & (Global | Static));
-  FunctionType *FTy = demangleFunctionType(HasThisQuals, false);
+  FunctionType *FTy = demangleFunctionType(MangledName, HasThisQuals, false);
   FTy->FunctionClass = FC;
 
   return FTy;
 }
 
 // Reads a primitive type.
-Type *Demangler::demangleBasicType() {
+Type *Demangler::demangleBasicType(StringView &MangledName) {
   Type *Ty = Arena.alloc<Type>();
 
   switch (MangledName.popFront()) {
@@ -1481,7 +1480,7 @@ Type *Demangler::demangleBasicType() {
   return Ty;
 }
 
-UdtType *Demangler::demangleClassType() {
+UdtType *Demangler::demangleClassType(StringView &MangledName) {
   UdtType *UTy = Arena.alloc<UdtType>();
 
   switch (MangledName.popFront()) {
@@ -1505,7 +1504,7 @@ UdtType *Demangler::demangleClassType() {
     assert(false);
   }
 
-  UTy->UdtName = demangleFullyQualifiedTypeName();
+  UTy->UdtName = demangleFullyQualifiedTypeName(MangledName);
   return UTy;
 }
 
@@ -1531,7 +1530,7 @@ demanglePointerCVQualifiers(StringView &MangledName) {
 
 // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type>
 //                       # the E is required for 64-bit non-static pointers
-PointerType *Demangler::demanglePointerType() {
+PointerType *Demangler::demanglePointerType(StringView &MangledName) {
   PointerType *Pointer = Arena.alloc<PointerType>();
 
   PointerAffinity Affinity;
@@ -1540,18 +1539,19 @@ PointerType *Demangler::demanglePointerType() {
   Pointer->Prim =
       (Affinity == PointerAffinity::Pointer) ? PrimTy::Ptr : PrimTy::Ref;
   if (MangledName.consumeFront("6")) {
-    Pointer->Pointee = demangleFunctionType(false, true);
+    Pointer->Pointee = demangleFunctionType(MangledName, false, true);
     return Pointer;
   }
 
-  Qualifiers ExtQuals = demanglePointerExtQualifiers();
+  Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
   Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
 
-  Pointer->Pointee = demangleType(QualifierMangleMode::Mangle);
+  Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Mangle);
   return Pointer;
 }
 
-MemberPointerType *Demangler::demangleMemberPointerType() {
+MemberPointerType *
+Demangler::demangleMemberPointerType(StringView &MangledName) {
   MemberPointerType *Pointer = Arena.alloc<MemberPointerType>();
   Pointer->Prim = PrimTy::MemberPtr;
 
@@ -1559,27 +1559,27 @@ MemberPointerType *Demangler::demangleMemberPointerType() {
   std::tie(Pointer->Quals, Affinity) = demanglePointerCVQualifiers(MangledName);
   assert(Affinity == PointerAffinity::Pointer);
 
-  Qualifiers ExtQuals = demanglePointerExtQualifiers();
+  Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
   Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
 
   if (MangledName.consumeFront("8")) {
-    Pointer->MemberName = demangleFullyQualifiedSymbolName();
-    Pointer->Pointee = demangleFunctionType(true, true);
+    Pointer->MemberName = demangleFullyQualifiedSymbolName(MangledName);
+    Pointer->Pointee = demangleFunctionType(MangledName, true, true);
   } else {
     Qualifiers PointeeQuals = Q_None;
     bool IsMember = false;
-    std::tie(PointeeQuals, IsMember) = demangleQualifiers();
+    std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName);
     assert(IsMember);
-    Pointer->MemberName = demangleFullyQualifiedSymbolName();
+    Pointer->MemberName = demangleFullyQualifiedSymbolName(MangledName);
 
-    Pointer->Pointee = demangleType(QualifierMangleMode::Drop);
+    Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop);
     Pointer->Pointee->Quals = PointeeQuals;
   }
 
   return Pointer;
 }
 
-Qualifiers Demangler::demanglePointerExtQualifiers() {
+Qualifiers Demangler::demanglePointerExtQualifiers(StringView &MangledName) {
   Qualifiers Quals = Q_None;
   if (MangledName.consumeFront('E'))
     Quals = Qualifiers(Quals | Q_Pointer64);
@@ -1591,11 +1591,11 @@ Qualifiers Demangler::demanglePointerExtQualifiers() {
   return Quals;
 }
 
-ArrayType *Demangler::demangleArrayType() {
+ArrayType *Demangler::demangleArrayType(StringView &MangledName) {
   assert(MangledName.front() == 'Y');
   MangledName.popFront();
 
-  int Dimension = demangleNumber();
+  int Dimension = demangleNumber(MangledName);
   if (Dimension <= 0) {
     Error = true;
     return nullptr;
@@ -1605,7 +1605,7 @@ ArrayType *Demangler::demangleArrayType() {
   ArrayType *Dim = ATy;
   for (int I = 0; I < Dimension; ++I) {
     Dim->Prim = PrimTy::Array;
-    Dim->ArrayDimension = demangleNumber();
+    Dim->ArrayDimension = demangleNumber(MangledName);
     Dim->NextDimension = Arena.alloc<ArrayType>();
     Dim = Dim->NextDimension;
   }
@@ -1619,13 +1619,13 @@ ArrayType *Demangler::demangleArrayType() {
       Error = true;
   }
 
-  ATy->ElementType = demangleType(QualifierMangleMode::Drop);
+  ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop);
   Dim->ElementType = ATy->ElementType;
   return ATy;
 }
 
 // Reads a function or a template parameters.
-ParamList Demangler::demangleFunctionParameterList() {
+ParamList Demangler::demangleFunctionParameterList(StringView &MangledName) {
   // Empty parameter list.
   if (MangledName.consumeFront('X'))
     return {};
@@ -1652,7 +1652,7 @@ ParamList Demangler::demangleFunctionParameterList() {
     size_t OldSize = MangledName.size();
 
     *Current = Arena.alloc<ParamList>();
-    (*Current)->Current = demangleType(QualifierMangleMode::Drop);
+    (*Current)->Current = demangleType(MangledName, QualifierMangleMode::Drop);
 
     size_t CharsConsumed = OldSize - MangledName.size();
     assert(CharsConsumed != 0);
@@ -1683,14 +1683,14 @@ ParamList Demangler::demangleFunctionParameterList() {
   return {};
 }
 
-ParamList Demangler::demangleTemplateParameterList() {
+ParamList Demangler::demangleTemplateParameterList(StringView &MangledName) {
   ParamList *Head;
   ParamList **Current = &Head;
   while (!Error && !MangledName.startsWith('@')) {
 
     // Template parameter lists don't participate in back-referencing.
     *Current = Arena.alloc<ParamList>();
-    (*Current)->Current = demangleType(QualifierMangleMode::Drop);
+    (*Current)->Current = demangleType(MangledName, QualifierMangleMode::Drop);
 
     Current = &(*Current)->Next;
   }
@@ -1706,7 +1706,7 @@ ParamList Demangler::demangleTemplateParameterList() {
   return {};
 }
 
-void Demangler::output() {
+void Demangler::output(const Symbol *S, OutputStream &OS) {
   // Converts an AST to a string.
   //
   // Converting an AST representing a C++ type to a string is tricky due
@@ -1724,9 +1724,9 @@ void Demangler::output() {
   // the "first half" of type declaration, and outputPost() writes the
   // "second half". For example, outputPre() writes a return type for a
   // function and outputPost() writes an parameter list.
-  Type::outputPre(OS, *SymbolType);
-  outputName(OS, SymbolName);
-  Type::outputPost(OS, *SymbolType);
+  Type::outputPre(OS, *S->SymbolType);
+  outputName(OS, S->SymbolName);
+  Type::outputPost(OS, *S->SymbolType);
 
   // Null terminate the buffer.
   OS << '\0';
@@ -1734,16 +1734,16 @@ void Demangler::output() {
 
 char *llvm::microsoftDemangle(const char *MangledName, char *Buf, size_t *N,
                               int *Status) {
-  OutputStream OS = OutputStream::create(Buf, N, 1024);
-
-  Demangler D(OS, StringView(MangledName));
-  D.parse();
+  Demangler D;
+  StringView Name{MangledName};
+  Symbol *S = D.parse(Name);
 
   if (D.Error)
     *Status = llvm::demangle_invalid_mangled_name;
   else
     *Status = llvm::demangle_success;
 
-  D.output();
+  OutputStream OS = OutputStream::create(Buf, N, 1024);
+  D.output(S, OS);
   return OS.getBuffer();
 }