<div dir="ltr">Builds were broken by this... I tried to fix the most obvious cause (broke my build) in r340721....</div><br><div class="gmail_quote"><div dir="ltr">On Sun, Aug 26, 2018 at 8:48 PM Zachary Turner via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: zturner<br>
Date: Sun Aug 26 20:48:03 2018<br>
New Revision: 340710<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=340710&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=340710&view=rev</a><br>
Log:<br>
[MS Demangler] Re-write the Microsoft demangler.<br>
<br>
This is a pretty large refactor / re-write of the Microsoft<br>
demangler. The previous one was a little hackish because it<br>
evolved as I was learning about all the various edge cases,<br>
exceptions, etc. It didn't have a proper AST and so there was<br>
lots of custom handling of things that should have been much<br>
more clean.<br>
<br>
Taking what was learned from that experience, it's now<br>
re-written with a completely redesigned and much more sensible<br>
AST. It's probably still not perfect, but at least it's<br>
comprehensible now to someone else who wants to come along<br>
and make some modifications or read the code.<br>
<br>
Incidentally, this fixed a couple of bugs, so I've enabled<br>
the tests which now pass.<br>
<br>
Added:<br>
  llvm/trunk/lib/Demangle/MicrosoftDemangleNodes.cpp<br>
  llvm/trunk/lib/Demangle/MicrosoftDemangleNodes.h<br>
Modified:<br>
  llvm/trunk/lib/Demangle/CMakeLists.txt<br>
  llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp<br>
  llvm/trunk/test/Demangle/ms-basic.test<br>
  llvm/trunk/test/Demangle/ms-operators.test<br>
  llvm/trunk/test/Demangle/ms-templates-memptrs-2.test<br>
  llvm/trunk/test/Demangle/ms-templates-memptrs.test<br>
<br>
Modified: llvm/trunk/lib/Demangle/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/CMakeLists.txt?rev=340710&r1=340709&r2=340710&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/CMakeLists.txt?rev=340710&r1=340709&r2=340710&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Demangle/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/Demangle/CMakeLists.txt Sun Aug 26 20:48:03 2018<br>
@@ -1,6 +1,7 @@<br>
 add_llvm_library(LLVMDemangle<br>
  ItaniumDemangle.cpp<br>
  MicrosoftDemangle.cpp<br>
+Â MicrosoftDemangleNodes.cpp<br>
<br>
  ADDITIONAL_HEADER_DIRS<br>
  "${LLVM_MAIN_INCLUDE_DIR}/llvm/Demangle"<br>
<br>
Modified: llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=340710&r1=340709&r2=340710&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=340710&r1=340709&r2=340710&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)<br>
+++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Sun Aug 26 20:48:03 2018<br>
@@ -14,6 +14,7 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
+#include "MicrosoftDemangleNodes.h"<br>
 #include "llvm/Demangle/Demangle.h"<br>
<br>
 #include "llvm/Demangle/Compiler.h"<br>
@@ -25,386 +26,21 @@<br>
 #include <cstdio><br>
 #include <tuple><br>
<br>
-// This memory allocator is extremely fast, but it doesn't call dtors<br>
-// for allocated objects. That means you can't use STL containers<br>
-// (such as std::vector) with this allocator. But it pays off --<br>
-// the demangler is 3x faster with this allocator compared to one with<br>
-// STL containers.<br>
-namespace {<br>
-Â constexpr size_t AllocUnit = 4096;<br>
-<br>
-class ArenaAllocator {<br>
-Â struct AllocatorNode {<br>
-Â Â uint8_t *Buf = nullptr;<br>
-Â Â size_t Used = 0;<br>
-Â Â size_t Capacity = 0;<br>
-Â Â AllocatorNode *Next = nullptr;<br>
-Â };<br>
-<br>
-Â void addNode(size_t Capacity) {<br>
-Â Â AllocatorNode *NewHead = new AllocatorNode;<br>
-Â Â NewHead->Buf = new uint8_t[Capacity];<br>
-Â Â NewHead->Next = Head;<br>
-Â Â NewHead->Capacity = Capacity;<br>
-Â Â Head = NewHead;<br>
-Â Â NewHead->Used = 0;<br>
-Â }<br>
-<br>
-public:<br>
-Â ArenaAllocator() { addNode(AllocUnit); }<br>
-<br>
-Â ~ArenaAllocator() {<br>
-Â Â while (Head) {<br>
-Â Â Â assert(Head->Buf);<br>
-Â Â Â delete[] Head->Buf;<br>
-Â Â Â AllocatorNode *Next = Head->Next;<br>
-Â Â Â delete Head;<br>
-Â Â Â Head = Next;<br>
-Â Â }<br>
-Â }<br>
-<br>
-Â char *allocUnalignedBuffer(size_t Length) {<br>
-Â Â uint8_t *Buf = Head->Buf + Head->Used;<br>
-<br>
-Â Â Head->Used += Length;<br>
-Â Â if (Head->Used > Head->Capacity) {<br>
-Â Â Â // It's possible we need a buffer which is larger than our default unit<br>
-Â Â Â // size, so we need to be careful to add a node with capacity that is at<br>
-Â Â Â // least as large as what we need.<br>
-Â Â Â addNode(std::max(AllocUnit, Length));<br>
-Â Â Â Head->Used = Length;<br>
-Â Â Â Buf = Head->Buf;<br>
-Â Â }<br>
-<br>
-Â Â return reinterpret_cast<char *>(Buf);<br>
-Â }<br>
-<br>
-Â template <typename T, typename... Args> T *alloc(Args &&... ConstructorArgs) {<br>
-<br>
-Â Â size_t Size = sizeof(T);<br>
-Â Â assert(Head && Head->Buf);<br>
-<br>
-Â Â size_t P = (size_t)Head->Buf + Head->Used;<br>
-Â Â uintptr_t AlignedP =<br>
-Â Â Â Â (((size_t)P + alignof(T) - 1) & ~(size_t)(alignof(T) - 1));<br>
-Â Â uint8_t *PP = (uint8_t *)AlignedP;<br>
-Â Â size_t Adjustment = AlignedP - P;<br>
-<br>
-Â Â Head->Used += Size + Adjustment;<br>
-Â Â if (Head->Used < Head->Capacity)<br>
-Â Â Â return new (PP) T(std::forward<Args>(ConstructorArgs)...);<br>
-<br>
-Â Â addNode(AllocUnit);<br>
-Â Â Head->Used = Size;<br>
-Â Â return new (Head->Buf) T(std::forward<Args>(ConstructorArgs)...);<br>
-Â }<br>
-<br>
-private:<br>
-Â AllocatorNode *Head = nullptr;<br>
-};<br>
-} // namespace<br>
+using namespace llvm;<br>
+using namespace ms_demangle;<br>
<br>
 static bool startsWithDigit(StringView S) {<br>
  return !S.empty() && std::isdigit(S.front());<br>
 }<br>
<br>
-// Writes a space if the last token does not end with a punctuation.<br>
-static void outputSpaceIfNecessary(OutputStream &OS) {<br>
-Â if (OS.empty())<br>
-Â Â return;<br>
-<br>
-Â char C = OS.back();<br>
-Â if (isalnum(C) || C == '>')<br>
-Â Â OS << " ";<br>
-}<br>
-<br>
-// Storage classes<br>
-enum Qualifiers : uint8_t {<br>
-Â Q_None = 0,<br>
-Â Q_Const = 1 << 0,<br>
-Â Q_Volatile = 1 << 1,<br>
-Â Q_Far = 1 << 2,<br>
-Â Q_Huge = 1 << 3,<br>
-Â Q_Unaligned = 1 << 4,<br>
-Â Q_Restrict = 1 << 5,<br>
-Â Q_Pointer64 = 1 << 6<br>
-};<br>
-<br>
-enum class StorageClass : uint8_t {<br>
-Â None,<br>
-Â PrivateStatic,<br>
-Â ProtectedStatic,<br>
-Â PublicStatic,<br>
-Â Global,<br>
-Â FunctionLocalStatic,<br>
-};<br>
-<br>
 enum class QualifierMangleMode { Drop, Mangle, Result };<br>
<br>
-enum class PointerAffinity { Pointer, Reference, RValueReference };<br>
-<br>
-// Calling conventions<br>
-enum class CallingConv : uint8_t {<br>
-Â None,<br>
-Â Cdecl,<br>
-Â Pascal,<br>
-Â Thiscall,<br>
-Â Stdcall,<br>
-Â Fastcall,<br>
-Â Clrcall,<br>
-Â Eabi,<br>
-Â Vectorcall,<br>
-Â Regcall,<br>
-};<br>
-<br>
-enum class ReferenceKind : uint8_t { None, LValueRef, RValueRef };<br>
-<br>
-// Types<br>
-enum class PrimTy : uint8_t {<br>
-Â Unknown,<br>
-Â None,<br>
-Â Function,<br>
-Â Ptr,<br>
-Â MemberPtr,<br>
-Â Array,<br>
-<br>
-Â Struct,<br>
-Â Union,<br>
-Â Class,<br>
-Â Enum,<br>
-<br>
-Â Void,<br>
-Â Bool,<br>
-Â Char,<br>
-Â Schar,<br>
-Â Uchar,<br>
-Â Char16,<br>
-Â Char32,<br>
-Â Short,<br>
-Â Ushort,<br>
-Â Int,<br>
-Â Uint,<br>
-Â Long,<br>
-Â Ulong,<br>
-Â Int64,<br>
-Â Uint64,<br>
-Â Wchar,<br>
-Â Float,<br>
-Â Double,<br>
-Â Ldouble,<br>
-Â Nullptr,<br>
-Â Custom,<br>
-Â Vftable,<br>
-Â Vbtable,<br>
-Â LocalStaticGuard<br>
+struct NodeList {<br>
+Â Node *N = nullptr;<br>
+Â NodeList *Next = nullptr;<br>
 };<br>
<br>
-enum class OperatorTy : uint8_t {<br>
- Ctor,          // ?0 # Foo::Foo()<br>
- Dtor,          // ?1 # Foo::~Foo()<br>
- New,           // ?2 # operator new<br>
- Delete,         // ?3 # operator delete<br>
- Assign,         // ?4 # operator=<br>
- RightShift,       // ?5 # operator>><br>
- LeftShift,        // ?6 # operator<<<br>
- LogicalNot,       // ?7 # operator!<br>
- Equals,         // ?8 # operator==<br>
- NotEquals,        // ?9 # operator!=<br>
- ArraySubscript,     // ?A # operator[]<br>
- Conversion,       // ?B # Foo::operator <type>()<br>
- Pointer,         // ?C # operator-><br>
- Dereference,       // ?D # operator*<br>
- Increment,        // ?E # operator++<br>
- Decrement,        // ?F # operator--<br>
- Minus,          // ?G # operator-<br>
- Plus,          // ?H # operator+<br>
- BitwiseAnd,       // ?I # operator&<br>
- MemberPointer,      // ?J # operator->*<br>
- Divide,         // ?K # operator/<br>
- Modulus,         // ?L # operator%<br>
- LessThan,        // ?M operator<<br>
- LessThanEqual,      // ?N operator<=<br>
- GreaterThan,       // ?O operator><br>
- GreaterThanEqual,    // ?P operator>=<br>
- Comma,          // ?Q operator,<br>
- Parens,         // ?R operator()<br>
- BitwiseNot,       // ?S operator~<br>
- BitwiseXor,       // ?T operator^<br>
- BitwiseOr,        // ?U operator|<br>
- LogicalAnd,       // ?V operator&&<br>
- LogicalOr,        // ?W operator||<br>
- TimesEqual,       // ?X operator*=<br>
- PlusEqual,        // ?Y operator+=<br>
- MinusEqual,       // ?Z operator-=<br>
- DivEqual,        // ?_0 operator/=<br>
- ModEqual,        // ?_1 operator%=<br>
- RshEqual,        // ?_2 operator>>=<br>
- LshEqual,        // ?_3 operator<<=<br>
- BitwiseAndEqual,     // ?_4 operator&=<br>
- BitwiseOrEqual,     // ?_5 operator|=<br>
- BitwiseXorEqual,     // ?_6 operator^=<br>
- Vftable,         // ?_7 # vftable<br>
- Vbtable,         // ?_8 # vbtable<br>
- Vcall,          // ?_9 # vcall<br>
- Typeof,         // ?_A # typeof<br>
- LocalStaticGuard,    // ?_B # local static guard<br>
- StringLiteral,      // ?_C # string literal<br>
- VbaseDtor,        // ?_D # vbase destructor<br>
- VecDelDtor,       // ?_E # vector deleting destructor<br>
- DefaultCtorClosure,   // ?_F # default constructor closure<br>
- ScalarDelDtor,      // ?_G # scalar deleting destructor<br>
- VecCtorIter,       // ?_H # vector constructor iterator<br>
- VecDtorIter,       // ?_I # vector destructor iterator<br>
- VecVbaseCtorIter,    // ?_J # vector vbase constructor iterator<br>
- VdispMap,        // ?_K # virtual displacement map<br>
- EHVecCtorIter,      // ?_L # eh vector constructor iterator<br>
- EHVecDtorIter,      // ?_M # eh vector destructor iterator<br>
- EHVecVbaseCtorIter,   // ?_N # eh vector vbase constructor iterator<br>
- CopyCtorClosure,     // ?_O # copy constructor closure<br>
- UdtReturning,      // ?_P<name> # udt returning <name><br>
- Unknown,         // ?_Q # <unknown><br>
- RttiTypeDescriptor,   // ?_R0 # RTTI Type Descriptor<br>
-Â RttiBaseClassDescriptor, // ?_R1 # RTTI Base Class Descriptor at (a,b,c,d)<br>
- RttiBaseClassArray,   // ?_R2 # RTTI Base Class Array<br>
-Â RttiClassHierarchyDescriptor, // ?_R3 # RTTI Class Hierarchy Descriptor<br>
- RttiCompleteObjLocator,    // ?_R4 # RTTI Complete Object Locator<br>
- LocalVftable,         // ?_S # local vftable<br>
- LocalVftableCtorClosure,   // ?_T # local vftable constructor closure<br>
- ArrayNew,           // ?_U operator new[]<br>
- ArrayDelete,         // ?_V operator delete[]<br>
- ManVectorCtorIter,      // ?__A managed vector ctor iterator<br>
- ManVectorDtorIter,      // ?__B managed vector dtor iterator<br>
- EHVectorCopyCtorIter,     // ?__C EH vector copy ctor iterator<br>
- EHVectorVbaseCopyCtorIter,  // ?__D EH vector vbase copy ctor iterator<br>
- DynamicInitializer,      // ?__E dynamic initializer for `T'<br>
- DynamicAtexitDestructor,   // ?__F dynamic atexit destructor for `T'<br>
- VectorCopyCtorIter,      // ?__G vector copy constructor iterator<br>
- VectorVbaseCopyCtorIter,   // ?__H vector vbase copy constructor iterator<br>
- ManVectorVbaseCopyCtorIter,  // ?__I managed vector vbase copy constructor<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â // iterator<br>
- LocalStaticThreadGuard,    // ?__J local static thread guard<br>
- LiteralOperator,       // ?__K operator ""_name<br>
- CoAwait,           // ?__L co_await<br>
- Spaceship,          // operator<=><br>
-};<br>
-<br>
-// A map to translate from operator prefix to operator type.<br>
-struct OperatorMapEntry {<br>
-Â StringView Prefix;<br>
-Â StringView Name;<br>
-Â OperatorTy Operator;<br>
-};<br>
-<br>
-// The entries here must be in the same order as the enumeration so that it can<br>
-// be indexed by enum value.<br>
-OperatorMapEntry OperatorMap[] = {<br>
-Â Â {"0", " <ctor>", OperatorTy::Ctor},<br>
-Â Â {"1", " <dtor>", OperatorTy::Dtor},<br>
-Â Â {"2", "operator new", OperatorTy::New},<br>
-Â Â {"3", "operator delete", OperatorTy::Delete},<br>
-Â Â {"4", "operator=", OperatorTy::Assign},<br>
-Â Â {"5", "operator>>", OperatorTy::RightShift},<br>
-Â Â {"6", "operator<<", OperatorTy::LeftShift},<br>
-Â Â {"7", "operator!", OperatorTy::LogicalNot},<br>
-Â Â {"8", "operator==", OperatorTy::Equals},<br>
-Â Â {"9", "operator!=", OperatorTy::NotEquals},<br>
-Â Â {"A", "operator[]", OperatorTy::ArraySubscript},<br>
-Â Â {"B", "operator <conversion>", OperatorTy::Conversion},<br>
-Â Â {"C", "operator->", OperatorTy::Pointer},<br>
-Â Â {"D", "operator*", OperatorTy::Dereference},<br>
-Â Â {"E", "operator++", OperatorTy::Increment},<br>
-Â Â {"F", "operator--", OperatorTy::Decrement},<br>
-Â Â {"G", "operator-", OperatorTy::Minus},<br>
-Â Â {"H", "operator+", OperatorTy::Plus},<br>
-Â Â {"I", "operator&", OperatorTy::BitwiseAnd},<br>
-Â Â {"J", "operator->*", OperatorTy::MemberPointer},<br>
-Â Â {"K", "operator/", OperatorTy::Divide},<br>
-Â Â {"L", "operator%", OperatorTy::Modulus},<br>
-Â Â {"M", "operator<", OperatorTy::LessThan},<br>
-Â Â {"N", "operator<=", OperatorTy::LessThanEqual},<br>
-Â Â {"O", "operator>", OperatorTy::GreaterThan},<br>
-Â Â {"P", "operator>=", OperatorTy::GreaterThanEqual},<br>
-Â Â {"Q", "operator,", OperatorTy::Comma},<br>
-Â Â {"R", "operator()", OperatorTy::Parens},<br>
-Â Â {"S", "operator~", OperatorTy::BitwiseNot},<br>
-Â Â {"T", "operator^", OperatorTy::BitwiseXor},<br>
-Â Â {"U", "operator|", OperatorTy::BitwiseOr},<br>
-Â Â {"V", "operator&&", OperatorTy::LogicalAnd},<br>
-Â Â {"W", "operator||", OperatorTy::LogicalOr},<br>
-Â Â {"X", "operator*=", OperatorTy::TimesEqual},<br>
-Â Â {"Y", "operator+=", OperatorTy::PlusEqual},<br>
-Â Â {"Z", "operator-=", OperatorTy::MinusEqual},<br>
-Â Â {"_0", "operator/=", OperatorTy::DivEqual},<br>
-Â Â {"_1", "operator%=", OperatorTy::ModEqual},<br>
-Â Â {"_2", "operator>>=", OperatorTy::RshEqual},<br>
-Â Â {"_3", "operator<<=", OperatorTy::LshEqual},<br>
-Â Â {"_4", "operator&=", OperatorTy::BitwiseAndEqual},<br>
-Â Â {"_5", "operator|=", OperatorTy::BitwiseOrEqual},<br>
-Â Â {"_6", "operator^=", OperatorTy::BitwiseXorEqual},<br>
-Â Â {"_7", "`vftable'", OperatorTy::Vftable},<br>
-Â Â {"_8", "`vbtable'", OperatorTy::Vbtable},<br>
-Â Â {"_9", "`vcall'", OperatorTy::Vcall},<br>
-Â Â {"_A", "`typeof'", OperatorTy::Typeof},<br>
-Â Â {"_B", "`local static guard'", OperatorTy::LocalStaticGuard},<br>
-Â Â {"_C", "`string'", OperatorTy::StringLiteral},<br>
-Â Â {"_D", "`vbase dtor'", OperatorTy::VbaseDtor},<br>
-Â Â {"_E", "`vector deleting dtor'", OperatorTy::VecDelDtor},<br>
-Â Â {"_F", "`default ctor closure'", OperatorTy::DefaultCtorClosure},<br>
-Â Â {"_G", "`scalar deleting dtor'", OperatorTy::ScalarDelDtor},<br>
-Â Â {"_H", "`vector ctor iterator'", OperatorTy::VecCtorIter},<br>
-Â Â {"_I", "`vector dtor iterator'", OperatorTy::VecDtorIter},<br>
-Â Â {"_J", "`vector vbase ctor iterator'", OperatorTy::VecVbaseCtorIter},<br>
-Â Â {"_K", "`virtual displacement map'", OperatorTy::VdispMap},<br>
-Â Â {"_L", "`eh vector ctor iterator'", OperatorTy::EHVecCtorIter},<br>
-Â Â {"_M", "`eh vector dtor iterator'", OperatorTy::EHVecDtorIter},<br>
-Â Â {"_N", "`eh vector vbase ctor iterator'", OperatorTy::EHVecVbaseCtorIter},<br>
-Â Â {"_O", "`copy ctor closure'", OperatorTy::CopyCtorClosure},<br>
-Â Â {"_P", "`udt returning'", OperatorTy::UdtReturning},<br>
-Â Â {"_Q", "`unknown'", OperatorTy::Unknown},<br>
-Â Â {"_R0", "`RTTI Type Descriptor'", OperatorTy::RttiTypeDescriptor},<br>
-Â Â {"_R1", "RTTI Base Class Descriptor", OperatorTy::RttiBaseClassDescriptor},<br>
-Â Â {"_R2", "`RTTI Base Class Array'", OperatorTy::RttiBaseClassArray},<br>
-Â Â {"_R3", "`RTTI Class Hierarchy Descriptor'",<br>
-Â Â Â OperatorTy::RttiClassHierarchyDescriptor},<br>
-Â Â {"_R4", "`RTTI Complete Object Locator'",<br>
-Â Â Â OperatorTy::RttiCompleteObjLocator},<br>
-Â Â {"_S", "`local vftable'", OperatorTy::LocalVftable},<br>
-Â Â {"_T", "`local vftable ctor closure'", OperatorTy::LocalVftableCtorClosure},<br>
-Â Â {"_U", "operator new[]", OperatorTy::ArrayNew},<br>
-Â Â {"_V", "operator delete[]", OperatorTy::ArrayDelete},<br>
-Â Â {"__A", "managed vector ctor iterator", OperatorTy::ManVectorCtorIter},<br>
-Â Â {"__B", "managed vector dtor iterator", OperatorTy::ManVectorDtorIter},<br>
-Â Â {"__C", "EH vector copy ctor iterator", OperatorTy::EHVectorCopyCtorIter},<br>
-Â Â {"__D", "EH vector vbase copy ctor iterator",<br>
-Â Â Â OperatorTy::EHVectorVbaseCopyCtorIter},<br>
-Â Â {"__E", "dynamic initializer", OperatorTy::DynamicInitializer},<br>
-Â Â {"__F", "dynamic atexit destructor", OperatorTy::DynamicAtexitDestructor},<br>
-Â Â {"__G", "vector copy ctor iterator", OperatorTy::VectorCopyCtorIter},<br>
-Â Â {"__H", "vector vbase copy constructor iterator",<br>
-Â Â Â OperatorTy::VectorVbaseCopyCtorIter},<br>
-Â Â {"__I", "managed vector vbase copy constructor iterator",<br>
-Â Â Â OperatorTy::ManVectorVbaseCopyCtorIter},<br>
-Â Â {"__J", "local static thread guard", OperatorTy::LocalStaticThreadGuard},<br>
-Â Â {"__K", "operator \"\"", OperatorTy::LiteralOperator},<br>
-Â Â {"__L", "co_await", OperatorTy::CoAwait},<br>
-};<br>
-<br>
-// Function classes<br>
-enum FuncClass : uint16_t {<br>
-Â None = 0,<br>
-Â Public = 1 << 0,<br>
-Â Protected = 1 << 1,<br>
-Â Private = 1 << 2,<br>
-Â Global = 1 << 3,<br>
-Â Static = 1 << 4,<br>
-Â Virtual = 1 << 5,<br>
-Â Far = 1 << 6,<br>
-Â ExternC = 1 << 7,<br>
-Â NoPrototype = 1 << 8,<br>
-Â VirtualThisAdjust = 1 << 9,<br>
-Â VirtualThisAdjustEx = 1 << 10,<br>
-Â StaticThisAdjust = 1 << 11<br>
-};<br>
+enum class FunctionIdentifierCodeGroup { Basic, Under, DoubleUnder };<br>
<br>
 enum NameBackrefBehavior : uint8_t {<br>
  NBB_None = 0,     // don't save any names as backrefs.<br>
@@ -412,237 +48,6 @@ enum NameBackrefBehavior : uint8_t {<br>
  NBB_Simple = 1 << 1,  // save simple names.<br>
 };<br>
<br>
-enum class SymbolCategory {<br>
-Â Unknown,<br>
-Â NamedFunction,<br>
-Â NamedVariable,<br>
-Â UnnamedFunction,<br>
-Â UnnamedVariable,<br>
-Â SpecialOperator<br>
-};<br>
-<br>
-namespace {<br>
-<br>
-struct Type;<br>
-struct Name;<br>
-<br>
-struct FunctionParams {<br>
-Â bool IsVariadic = false;<br>
-<br>
-Â Type *Current = nullptr;<br>
-<br>
-Â FunctionParams *Next = nullptr;<br>
-};<br>
-<br>
-struct TemplateParams {<br>
-Â bool IsTemplateTemplate = false;<br>
-Â bool IsAliasTemplate = false;<br>
-Â bool IsIntegerLiteral = false;<br>
-Â bool IntegerLiteralIsNegative = false;<br>
-Â bool IsEmptyParameterPack = false;<br>
-Â bool PointerToSymbol = false;<br>
-Â bool NullptrLiteral = false;<br>
-Â bool DataMemberPointer = false;<br>
-Â bool ReferenceToSymbol = false;<br>
-<br>
-Â int ThunkOffsetCount = 0;<br>
-Â std::array<int64_t, 3> ThunkOffsets;<br>
-<br>
-Â // If IsIntegerLiteral is true, this is a non-type template parameter<br>
-Â // whose value is contained in this field.<br>
-Â uint64_t IntegralValue = 0;<br>
-<br>
- // Type can be null if this is a template template parameter. In that case<br>
-Â // only Name will be valid.<br>
-Â Type *ParamType = nullptr;<br>
-<br>
-Â // Name can be valid if this is a template template parameter (see above) or<br>
- // this is a function declaration (e.g. foo<&SomeFunc>). In the latter case<br>
-Â // Name contains the name of the function and Type contains the signature.<br>
-Â Name *ParamName = nullptr;<br>
-<br>
-Â TemplateParams *Next = nullptr;<br>
-};<br>
-<br>
-// The type class. Mangled symbols are first parsed and converted to<br>
-// this type and then converted to string.<br>
-struct Type {<br>
-Â virtual ~Type() {}<br>
-<br>
-Â virtual Type *clone(ArenaAllocator &Arena) const;<br>
-<br>
- // Write the "first half" of a given type. This is a static functions to<br>
-Â // give the code a chance to do processing that is common to a subset of<br>
-Â // subclasses<br>
-Â static void outputPre(OutputStream &OS, Type &Ty);<br>
-<br>
- // Write the "second half" of a given type. This is a static functions to<br>
-Â // give the code a chance to do processing that is common to a subset of<br>
-Â // subclasses<br>
-Â static void outputPost(OutputStream &OS, Type &Ty);<br>
-<br>
-Â virtual void outputPre(OutputStream &OS);<br>
-Â virtual void outputPost(OutputStream &OS);<br>
-<br>
-Â // Primitive type such as Int.<br>
-Â PrimTy Prim = PrimTy::Unknown;<br>
-<br>
-Â Qualifiers Quals = Q_None;<br>
-Â StringView Custom;<br>
-Â StorageClass Storage = StorageClass::None; // storage class<br>
-};<br>
-<br>
-// Represents an identifier which may be a template.<br>
-struct Name {<br>
-Â virtual ~Name() = default;<br>
-<br>
-Â bool IsTemplateInstantiation = false;<br>
-Â bool IsOperator = false;<br>
-Â bool IsBackReference = false;<br>
-<br>
-Â // Name read from an MangledName string.<br>
-Â StringView Str;<br>
-<br>
-Â // Template parameters. Only valid if IsTemplateInstantiation is true.<br>
-Â TemplateParams *TParams = nullptr;<br>
-<br>
-Â // Nested BackReferences (e.g. "A::B::C") are represented as a linked list.<br>
-Â Name *Next = nullptr;<br>
-};<br>
-<br>
-struct OperatorInfo : public Name {<br>
-Â explicit OperatorInfo(const OperatorMapEntry &Info) : Info(&Info) {<br>
-Â Â this->IsOperator = true;<br>
-Â }<br>
-Â explicit OperatorInfo(OperatorTy OpType)<br>
-Â Â Â : OperatorInfo(OperatorMap[(int)OpType]) {}<br>
-<br>
-Â const OperatorMapEntry *Info = nullptr;<br>
-Â bool IsIndirectTable = false;<br>
-};<br>
-<br>
-struct IndirectTable : public OperatorInfo {<br>
-Â explicit IndirectTable(const OperatorMapEntry &Info) : OperatorInfo(Info) {<br>
-Â Â this->IsOperator = true;<br>
-Â Â this->IsIndirectTable = true;<br>
-Â }<br>
-Â explicit IndirectTable(OperatorTy OpType)<br>
-Â Â Â : IndirectTable(OperatorMap[(int)OpType]) {}<br>
-<br>
-Â const Name *TableLocation = nullptr;<br>
-Â const Name *TableTarget = nullptr;<br>
-};<br>
-<br>
-struct StringLiteral : public OperatorInfo {<br>
-Â StringLiteral() : OperatorInfo(OperatorTy::StringLiteral) {}<br>
-<br>
-Â PrimTy CharType;<br>
-Â bool IsTruncated = false;<br>
-};<br>
-<br>
-struct RttiBaseClassDescriptor : public OperatorInfo {<br>
-Â RttiBaseClassDescriptor()<br>
-Â Â Â : OperatorInfo(OperatorTy::RttiBaseClassDescriptor) {}<br>
-<br>
-Â uint32_t NVOffset = 0;<br>
-Â int32_t VBPtrOffset = 0;<br>
-Â uint32_t VBTableOffset = 0;<br>
-Â uint32_t Flags = 0;<br>
-};<br>
-<br>
-struct LocalStaticGuardVariable : public OperatorInfo {<br>
-Â LocalStaticGuardVariable() : OperatorInfo(OperatorTy::LocalStaticGuard) {}<br>
-<br>
-Â uint32_t ScopeIndex = 0;<br>
-Â bool IsVisible = false;<br>
-};<br>
-<br>
-struct VirtualMemberPtrThunk : public OperatorInfo {<br>
-Â VirtualMemberPtrThunk() : OperatorInfo(OperatorTy::Vcall) {}<br>
-<br>
-Â uint64_t OffsetInVTable = 0;<br>
-Â CallingConv CC = CallingConv::Cdecl;<br>
-};<br>
-<br>
-struct PointerType : public Type {<br>
-Â Type *clone(ArenaAllocator &Arena) const override;<br>
-Â void outputPre(OutputStream &OS) override;<br>
-Â void outputPost(OutputStream &OS) override;<br>
-<br>
-Â PointerAffinity Affinity;<br>
-<br>
-Â // Represents a type X in "a pointer to X", "a reference to X",<br>
-Â // "an array of X", or "a function returning X".<br>
-Â Type *Pointee = nullptr;<br>
-};<br>
-<br>
-struct MemberPointerType : public Type {<br>
-Â Type *clone(ArenaAllocator &Arena) const override;<br>
-Â void outputPre(OutputStream &OS) override;<br>
-Â void outputPost(OutputStream &OS) override;<br>
-<br>
-Â Name *MemberName = nullptr;<br>
-<br>
-Â // Represents a type X in "a pointer to X", "a reference to X",<br>
-Â // "an array of X", or "a function returning X".<br>
-Â Type *Pointee = nullptr;<br>
-};<br>
-<br>
-struct FunctionType : public Type {<br>
-Â struct ThisAdjustor {<br>
-Â Â uint32_t StaticOffset = 0;<br>
-Â Â int32_t VBPtrOffset = 0;<br>
-Â Â int32_t VBOffsetOffset = 0;<br>
-Â Â int32_t VtordispOffset = 0;<br>
-Â };<br>
-<br>
-Â Type *clone(ArenaAllocator &Arena) const override;<br>
-Â void outputPre(OutputStream &OS) override;<br>
-Â void outputPost(OutputStream &OS) override;<br>
-<br>
-Â // True if this FunctionType instance is the Pointee of a PointerType or<br>
-Â // MemberPointerType.<br>
-Â bool IsFunctionPointer = false;<br>
-Â bool IsThunk = false;<br>
-<br>
-Â Type *ReturnType = nullptr;<br>
-Â // If this is a reference, the type of reference.<br>
-Â ReferenceKind RefKind;<br>
-<br>
-Â CallingConv CallConvention;<br>
-Â FuncClass FunctionClass;<br>
-<br>
-Â // Valid if IsThunk is true.<br>
-Â ThisAdjustor *ThisAdjust = nullptr;<br>
-<br>
-Â FunctionParams Params;<br>
-};<br>
-<br>
-struct UdtType : public Type {<br>
-Â Type *clone(ArenaAllocator &Arena) const override;<br>
-Â void outputPre(OutputStream &OS) override;<br>
-<br>
-Â Name *UdtName = nullptr;<br>
-};<br>
-<br>
-struct ArrayDimension {<br>
-Â uint64_t Dim = 0;<br>
-Â ArrayDimension *Next = nullptr;<br>
-};<br>
-<br>
-struct ArrayType : public Type {<br>
-Â Type *clone(ArenaAllocator &Arena) const override;<br>
-Â void outputPre(OutputStream &OS) override;<br>
-Â void outputPost(OutputStream &OS) override;<br>
-<br>
-Â // Either NextDimension or ElementType will be valid.<br>
-Â ArrayDimension *Dims = nullptr;<br>
-<br>
-Â Type *ElementType = nullptr;<br>
-};<br>
-<br>
-} // namespace<br>
-<br>
 static bool isMemberPointer(StringView MangledName) {<br>
  switch (MangledName.popFront()) {<br>
  case '$':<br>
@@ -697,40 +102,41 @@ static bool isMemberPointer(StringView M<br>
  return false;<br>
 }<br>
<br>
-static void outputCallingConvention(OutputStream &OS, CallingConv CC) {<br>
-Â outputSpaceIfNecessary(OS);<br>
-<br>
-Â switch (CC) {<br>
-Â case CallingConv::Cdecl:<br>
-Â Â OS << "__cdecl";<br>
-Â Â break;<br>
-Â case CallingConv::Fastcall:<br>
-Â Â OS << "__fastcall";<br>
-Â Â break;<br>
-Â case CallingConv::Pascal:<br>
-Â Â OS << "__pascal";<br>
-Â Â break;<br>
-Â case CallingConv::Regcall:<br>
-Â Â OS << "__regcall";<br>
-Â Â break;<br>
-Â case CallingConv::Stdcall:<br>
-Â Â OS << "__stdcall";<br>
-Â Â break;<br>
-Â case CallingConv::Thiscall:<br>
-Â Â OS << "__thiscall";<br>
-Â Â break;<br>
-Â case CallingConv::Eabi:<br>
-Â Â OS << "__eabi";<br>
-Â Â break;<br>
-Â case CallingConv::Vectorcall:<br>
-Â Â OS << "__vectorcall";<br>
-Â Â break;<br>
-Â case CallingConv::Clrcall:<br>
-Â Â OS << "__clrcall";<br>
-Â Â break;<br>
-Â default:<br>
-Â Â break;<br>
-Â }<br>
+static SpecialIntrinsicKind<br>
+consumeSpecialIntrinsicKind(StringView &MangledName) {<br>
+Â if (MangledName.consumeFront("?_7"))<br>
+Â Â return SpecialIntrinsicKind::Vftable;<br>
+Â if (MangledName.consumeFront("?_8"))<br>
+Â Â return SpecialIntrinsicKind::Vbtable;<br>
+Â if (MangledName.consumeFront("?_9"))<br>
+Â Â return SpecialIntrinsicKind::VcallThunk;<br>
+Â if (MangledName.consumeFront("?_A"))<br>
+Â Â return SpecialIntrinsicKind::Typeof;<br>
+Â if (MangledName.consumeFront("?_B"))<br>
+Â Â return SpecialIntrinsicKind::LocalStaticGuard;<br>
+Â if (MangledName.consumeFront("?_C"))<br>
+Â Â return SpecialIntrinsicKind::StringLiteralSymbol;<br>
+Â if (MangledName.consumeFront("?_P"))<br>
+Â Â return SpecialIntrinsicKind::UdtReturning;<br>
+Â if (MangledName.consumeFront("?_R0"))<br>
+Â Â return SpecialIntrinsicKind::RttiTypeDescriptor;<br>
+Â if (MangledName.consumeFront("?_R1"))<br>
+Â Â return SpecialIntrinsicKind::RttiBaseClassDescriptor;<br>
+Â if (MangledName.consumeFront("?_R2"))<br>
+Â Â return SpecialIntrinsicKind::RttiBaseClassArray;<br>
+Â if (MangledName.consumeFront("?_R3"))<br>
+Â Â return SpecialIntrinsicKind::RttiClassHierarchyDescriptor;<br>
+Â if (MangledName.consumeFront("?_R4"))<br>
+Â Â return SpecialIntrinsicKind::RttiCompleteObjLocator;<br>
+Â if (MangledName.consumeFront("?_S"))<br>
+Â Â return SpecialIntrinsicKind::LocalVftable;<br>
+Â if (MangledName.consumeFront("?__E"))<br>
+Â Â return SpecialIntrinsicKind::DynamicInitializer;<br>
+Â if (MangledName.consumeFront("?__F"))<br>
+Â Â return SpecialIntrinsicKind::DynamicAtexitDestructor;<br>
+Â if (MangledName.consumeFront("?__J"))<br>
+Â Â return SpecialIntrinsicKind::LocalStaticThreadGuard;<br>
+Â return SpecialIntrinsicKind::None;<br>
 }<br>
<br>
 static bool startsWithLocalScopePattern(StringView S) {<br>
@@ -774,623 +180,81 @@ static bool startsWithLocalScopePattern(<br>
  return true;<br>
 }<br>
<br>
-// Write a function or template parameter list.<br>
-static void outputParameterList(OutputStream &OS,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const FunctionParams &Params) {<br>
-Â if (!Params.Current) {<br>
-Â Â OS << "void";<br>
-Â Â return;<br>
-Â }<br>
-<br>
-Â const FunctionParams *Head = &Params;<br>
-Â while (Head) {<br>
-Â Â Type::outputPre(OS, *Head->Current);<br>
-Â Â Type::outputPost(OS, *Head->Current);<br>
-<br>
-Â Â Head = Head->Next;<br>
-<br>
-Â Â if (Head)<br>
-Â Â Â OS << ", ";<br>
-Â }<br>
-}<br>
-<br>
-static void outputStringLiteral(OutputStream &OS, const StringLiteral &Str) {<br>
-Â switch (Str.CharType) {<br>
-Â case PrimTy::Wchar:<br>
-Â Â OS << "const wchar_t * {L\"";<br>
-Â Â break;<br>
-Â case PrimTy::Char:<br>
-Â Â OS << "const char * {\"";<br>
-Â Â break;<br>
-Â case PrimTy::Char16:<br>
-Â Â OS << "const char16_t * {u\"";<br>
-Â Â break;<br>
-Â case PrimTy::Char32:<br>
-Â Â OS << "const char32_t * {U\"";<br>
-Â Â break;<br>
-Â default:<br>
-Â Â LLVM_BUILTIN_UNREACHABLE;<br>
-Â }<br>
-Â OS << Str.Str << "\"";<br>
-Â if (Str.IsTruncated)<br>
-Â Â OS << "...";<br>
-Â OS << "}";<br>
-}<br>
-<br>
-static void outputName(OutputStream &OS, const Name *TheName, const Type *Ty);<br>
-<br>
-static void outputParameterList(OutputStream &OS,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const TemplateParams &Params) {<br>
-Â if (Params.IsEmptyParameterPack) {<br>
-Â Â OS << "<>";<br>
-Â Â return;<br>
-Â }<br>
-<br>
-Â OS << "<";<br>
-Â const TemplateParams *Head = &Params;<br>
-Â while (Head) {<br>
-Â Â // Type can be null if this is a template template parameter,<br>
-Â Â // and Name can be null if this is a simple type.<br>
-<br>
-Â Â if (Head->IsIntegerLiteral) {<br>
-Â Â Â if (Head->IntegerLiteralIsNegative)<br>
-Â Â Â Â OS << '-';<br>
-Â Â Â OS << Head->IntegralValue;<br>
-Â Â } else if (Head->PointerToSymbol || Head->ReferenceToSymbol) {<br>
-Â Â Â if (Head->NullptrLiteral)<br>
-Â Â Â Â OS << "nullptr";<br>
-Â Â Â else {<br>
-Â Â Â Â if (Head->ThunkOffsetCount > 0)<br>
-Â Â Â Â Â OS << "{";<br>
-Â Â Â Â else if (Head->PointerToSymbol)<br>
-Â Â Â Â Â OS << "&";<br>
-Â Â Â Â if (Head->ParamType)<br>
-Â Â Â Â Â Type::outputPre(OS, *Head->ParamType);<br>
-Â Â Â Â outputName(OS, Head->ParamName, Head->ParamType);<br>
-Â Â Â Â if (Head->ParamType)<br>
-Â Â Â Â Â Type::outputPost(OS, *Head->ParamType);<br>
-Â Â Â Â if (Head->ThunkOffsetCount > 0) {<br>
-Â Â Â Â Â for (int I = 0; I < Head->ThunkOffsetCount; ++I) {<br>
-Â Â Â Â Â Â OS << ", " << Head->ThunkOffsets[I];<br>
-Â Â Â Â Â }<br>
-Â Â Â Â Â OS << "}";<br>
-Â Â Â Â }<br>
-Â Â Â }<br>
-Â Â } else if (Head->DataMemberPointer) {<br>
-Â Â Â OS << "{" << Head->ThunkOffsets[0];<br>
-Â Â Â for (int I = 1; I < Head->ThunkOffsetCount; ++I)<br>
-Â Â Â Â OS << ", " << Head->ThunkOffsets[I];<br>
-Â Â Â OS << "}";<br>
-Â Â } else if (Head->ParamType) {<br>
-Â Â Â // simple type.<br>
-Â Â Â Type::outputPre(OS, *Head->ParamType);<br>
-Â Â Â Type::outputPost(OS, *Head->ParamType);<br>
-Â Â } else {<br>
-Â Â Â // Template alias.<br>
-Â Â Â outputName(OS, Head->ParamName, Head->ParamType);<br>
-Â Â }<br>
-<br>
-Â Â Head = Head->Next;<br>
-<br>
-Â Â if (Head)<br>
-Â Â Â OS << ", ";<br>
-Â }<br>
-Â OS << ">";<br>
-}<br>
-<br>
-static void outputQualifiers(OutputStream &OS, Qualifiers Q) {<br>
-Â if (Q & Q_Const) {<br>
-Â Â outputSpaceIfNecessary(OS);<br>
-Â Â OS << "const";<br>
-Â }<br>
-<br>
-Â if (Q & Q_Volatile) {<br>
-Â Â outputSpaceIfNecessary(OS);<br>
-Â Â OS << "volatile";<br>
-Â }<br>
-<br>
-Â if (Q & Q_Restrict) {<br>
-Â Â outputSpaceIfNecessary(OS);<br>
-Â Â OS << "__restrict";<br>
-Â }<br>
-}<br>
-<br>
-static void outputNameComponent(OutputStream &OS, const Name &N) {<br>
-Â OS << N.Str;<br>
-<br>
-Â if (N.IsTemplateInstantiation && N.TParams)<br>
-Â Â outputParameterList(OS, *N.TParams);<br>
-}<br>
-<br>
-static const OperatorInfo *lastComponentAsOperator(const Name *TheName) {<br>
-Â if (!TheName)<br>
-Â Â return nullptr;<br>
-Â while (TheName->Next)<br>
-Â Â TheName = TheName->Next;<br>
-Â if (TheName->IsOperator)<br>
-Â Â return static_cast<const OperatorInfo *>(TheName);<br>
-Â return nullptr;<br>
-}<br>
-<br>
-static void outputName(OutputStream &OS, const Name *TheName, const Type *Ty) {<br>
-Â if (!TheName)<br>
-Â Â return;<br>
-<br>
-Â outputSpaceIfNecessary(OS);<br>
-<br>
-Â const OperatorInfo *Operator = lastComponentAsOperator(TheName);<br>
-Â const VirtualMemberPtrThunk *Thunk = nullptr;<br>
-Â bool PrintLastScopeSeparator = true;<br>
-Â if (Operator) {<br>
-Â Â if (Operator->IsIndirectTable) {<br>
-Â Â Â const IndirectTable *Table = static_cast<const IndirectTable *>(Operator);<br>
-Â Â Â outputName(OS, Table->TableLocation, nullptr);<br>
-Â Â Â OS << "{for `";<br>
-Â Â Â outputName(OS, Table->TableTarget, nullptr);<br>
-Â Â Â OS << "'}";<br>
-Â Â Â return;<br>
-Â Â }<br>
-Â Â if (Operator->Info->Operator == OperatorTy::Vcall) {<br>
-Â Â Â Thunk = static_cast<const VirtualMemberPtrThunk *>(Operator);<br>
-Â Â Â OS << "[thunk]: ";<br>
-Â Â Â outputCallingConvention(OS, Thunk->CC);<br>
-Â Â Â OS << " ";<br>
-Â Â } else if (Operator->Info->Operator == OperatorTy::DynamicInitializer) {<br>
-Â Â Â OS << "`dynamic initializer for '";<br>
-Â Â Â PrintLastScopeSeparator = false;<br>
-Â Â } else if (Operator->Info->Operator ==<br>
-Â Â Â Â Â Â Â Â OperatorTy::DynamicAtexitDestructor) {<br>
-Â Â Â OS << "`dynamic atexit destructor for '";<br>
-Â Â Â PrintLastScopeSeparator = false;<br>
-Â Â }<br>
-Â }<br>
-<br>
-Â const Name *Previous = nullptr;<br>
-Â // Print out namespaces or outer class BackReferences.<br>
-Â for (; TheName->Next; TheName = TheName->Next) {<br>
-Â Â Previous = TheName;<br>
-Â Â outputNameComponent(OS, *TheName);<br>
-Â Â if (TheName->Next != Operator || PrintLastScopeSeparator)<br>
-Â Â Â OS << "::";<br>
-Â }<br>
-<br>
-Â // Print out a regular name.<br>
-Â if (!TheName->IsOperator) {<br>
-Â Â outputNameComponent(OS, *TheName);<br>
-Â Â return;<br>
-Â }<br>
-<br>
-<br>
-Â // Print out ctor or dtor.<br>
-Â switch (Operator->Info->Operator) {<br>
-Â case OperatorTy::Dtor:<br>
-Â Â OS << "~";<br>
-Â Â LLVM_FALLTHROUGH;<br>
-Â case OperatorTy::Ctor:<br>
-Â Â // Output the class name with template arguments a second time.<br>
-Â Â outputNameComponent(OS, *Previous);<br>
-<br>
-Â Â // Structors don't have a name, so outputting the name here actually is a<br>
-  // no-op. But for template constructors, it needs to output the template<br>
-  // argument list. e.g.<br>
-Â Â //<br>
-Â Â // template<typename T><br>
-Â Â // struct Foo {<br>
-Â Â //Â Â template<typename U><br>
-Â Â //Â Â Foo(U);<br>
-Â Â // };<br>
-Â Â // should demangle as -- for example -- Foo<int><double>(double);<br>
-Â Â outputNameComponent(OS, *TheName);<br>
-Â Â break;<br>
-Â case OperatorTy::Conversion:<br>
-Â Â OS << "operator";<br>
-Â Â if (TheName->IsTemplateInstantiation && TheName->TParams)<br>
-Â Â Â outputParameterList(OS, *TheName->TParams);<br>
-Â Â OS << " ";<br>
-Â Â if (Ty) {<br>
-Â Â Â const FunctionType *FTy = static_cast<const FunctionType *>(Ty);<br>
-Â Â Â Type::outputPre(OS, *FTy->ReturnType);<br>
-Â Â Â Type::outputPost(OS, *FTy->ReturnType);<br>
-Â Â } else {<br>
-Â Â Â OS << "<conversion>";<br>
-Â Â }<br>
-Â Â break;<br>
-Â case OperatorTy::LiteralOperator:<br>
-Â Â OS << Operator->Info->Name;<br>
-Â Â outputNameComponent(OS, *TheName);<br>
-Â Â break;<br>
-Â case OperatorTy::RttiBaseClassDescriptor: {<br>
-Â Â const RttiBaseClassDescriptor &BCD =<br>
-Â Â Â Â static_cast<const RttiBaseClassDescriptor &>(*Operator);<br>
-Â Â OS << "`" << Operator->Info->Name << " at (";<br>
-Â Â OS << BCD.NVOffset << ", " << BCD.VBPtrOffset << ", " << BCD.VBTableOffset<br>
-Â Â Â Â << ", " << BCD.Flags;<br>
-Â Â OS << ")'";<br>
-Â Â break;<br>
-Â }<br>
-Â case OperatorTy::Vcall: {<br>
-Â Â OS << "`vcall'{";<br>
-Â Â OS << Thunk->OffsetInVTable << ", {flat}}";<br>
-Â Â break;<br>
-Â }<br>
-Â case OperatorTy::DynamicInitializer:<br>
-Â case OperatorTy::DynamicAtexitDestructor:<br>
-Â Â OS << "''";<br>
-Â Â break;<br>
-<br>
-Â case OperatorTy::LocalStaticGuard: {<br>
-Â Â const LocalStaticGuardVariable &LSG =<br>
-Â Â Â Â static_cast<const LocalStaticGuardVariable &>(*Operator);<br>
-Â Â OS << Operator->Info->Name;<br>
-Â Â if (LSG.ScopeIndex > 0)<br>
-Â Â Â OS << "{" << LSG.ScopeIndex << "}";<br>
-Â Â break;<br>
-Â }<br>
-Â default:<br>
-Â Â OS << Operator->Info->Name;<br>
-Â Â if (Operator->IsTemplateInstantiation)<br>
-Â Â Â outputParameterList(OS, *Operator->TParams);<br>
-Â Â break;<br>
-Â }<br>
-}<br>
-<br>
-static void outputSpecialOperator(OutputStream &OS, const Name *OuterName) {<br>
-Â assert(OuterName);<br>
-Â // The last component should be an operator.<br>
-Â const OperatorInfo *Operator = lastComponentAsOperator(OuterName);<br>
-<br>
-Â assert(Operator->IsOperator);<br>
-Â const OperatorInfo &Oper = static_cast<const OperatorInfo &>(*Operator);<br>
-Â switch (Oper.Info->Operator) {<br>
-Â case OperatorTy::StringLiteral: {<br>
-Â Â const StringLiteral &SL = static_cast<const StringLiteral &>(Oper);<br>
-Â Â outputStringLiteral(OS, SL);<br>
-Â Â break;<br>
-Â }<br>
-Â case OperatorTy::Vcall: {<br>
-Â Â const VirtualMemberPtrThunk &Thunk =<br>
-Â Â Â Â static_cast<const VirtualMemberPtrThunk &>(Oper);<br>
-Â Â OS << "[thunk]: ";<br>
-Â Â outputCallingConvention(OS, Thunk.CC);<br>
-Â Â OS << " ";<br>
-Â Â // Print out namespaces or outer class BackReferences.<br>
-Â Â const Name *N = OuterName;<br>
-Â Â for (; N->Next; N = N->Next) {<br>
-Â Â Â outputNameComponent(OS, *N);<br>
-Â Â Â OS << "::";<br>
-Â Â }<br>
-Â Â OS << "`vcall'{";<br>
-Â Â OS << Thunk.OffsetInVTable << ", {flat}}";<br>
-Â Â break;<br>
-Â }<br>
-Â default:<br>
-Â Â // There are no other special operator categories.<br>
-Â Â LLVM_BUILTIN_UNREACHABLE;<br>
-Â }<br>
-}<br>
-<br>
-namespace {<br>
-<br>
-Type *Type::clone(ArenaAllocator &Arena) const {<br>
-Â return Arena.alloc<Type>(*this);<br>
-}<br>
-<br>
-// Write the "first half" of a given type.<br>
-void Type::outputPre(OutputStream &OS, Type &Ty) {<br>
-Â // Function types require custom handling of const and static so we<br>
- // handle them separately. All other types use the same decoration<br>
-Â // for these modifiers, so handle them here in common code.<br>
-Â if (Ty.Prim == PrimTy::Function) {<br>
-Â Â Ty.outputPre(OS);<br>
-Â Â return;<br>
-Â }<br>
-<br>
-Â switch (Ty.Storage) {<br>
-Â case StorageClass::PrivateStatic:<br>
-Â case StorageClass::PublicStatic:<br>
-Â case StorageClass::ProtectedStatic:<br>
-Â Â OS << "static ";<br>
-Â default:<br>
-Â Â break;<br>
-Â }<br>
-Â Ty.outputPre(OS);<br>
-<br>
-Â outputQualifiers(OS, Ty.Quals);<br>
-}<br>
-<br>
-// Write the "second half" of a given type.<br>
-void Type::outputPost(OutputStream &OS, Type &Ty) { Ty.outputPost(OS); }<br>
-<br>
-void Type::outputPre(OutputStream &OS) {<br>
-Â switch (Prim) {<br>
-Â case PrimTy::Void:<br>
-Â Â OS << "void";<br>
-Â Â break;<br>
-Â case PrimTy::Bool:<br>
-Â Â OS << "bool";<br>
-Â Â break;<br>
-Â case PrimTy::Char:<br>
-Â Â OS << "char";<br>
-Â Â break;<br>
-Â case PrimTy::Schar:<br>
-Â Â OS << "signed char";<br>
-Â Â break;<br>
-Â case PrimTy::Uchar:<br>
-Â Â OS << "unsigned char";<br>
-Â Â break;<br>
-Â case PrimTy::Char16:<br>
-Â Â OS << "char16_t";<br>
-Â Â break;<br>
-Â case PrimTy::Char32:<br>
-Â Â OS << "char32_t";<br>
-Â Â break;<br>
-Â case PrimTy::Short:<br>
-Â Â OS << "short";<br>
-Â Â break;<br>
-Â case PrimTy::Ushort:<br>
-Â Â OS << "unsigned short";<br>
-Â Â break;<br>
-Â case PrimTy::Int:<br>
-Â Â OS << "int";<br>
-Â Â break;<br>
-Â case PrimTy::Uint:<br>
-Â Â OS << "unsigned int";<br>
-Â Â break;<br>
-Â case PrimTy::Long:<br>
-Â Â OS << "long";<br>
-Â Â break;<br>
-Â case PrimTy::Ulong:<br>
-Â Â OS << "unsigned long";<br>
-Â Â break;<br>
-Â case PrimTy::Int64:<br>
-Â Â OS << "__int64";<br>
-Â Â break;<br>
-Â case PrimTy::Uint64:<br>
-Â Â OS << "unsigned __int64";<br>
-Â Â break;<br>
-Â case PrimTy::Wchar:<br>
-Â Â OS << "wchar_t";<br>
-Â Â break;<br>
-Â case PrimTy::Float:<br>
-Â Â OS << "float";<br>
-Â Â break;<br>
-Â case PrimTy::Double:<br>
-Â Â OS << "double";<br>
-Â Â break;<br>
-Â case PrimTy::Ldouble:<br>
-Â Â OS << "long double";<br>
-Â Â break;<br>
-Â case PrimTy::Nullptr:<br>
-Â Â OS << "std::nullptr_t";<br>
-Â Â break;<br>
-Â case PrimTy::Custom:<br>
-Â Â OS << Custom;<br>
-Â Â break;<br>
-Â case PrimTy::Vbtable:<br>
-Â case PrimTy::Vftable:<br>
-Â Â break;<br>
-Â default:<br>
-Â Â assert(false && "Invalid primitive type!");<br>
+static bool isTagType(StringView S) {<br>
+Â switch (S.front()) {<br>
+Â case 'T': // union<br>
+Â case 'U': // struct<br>
+Â case 'V': // class<br>
+Â case 'W': // enum<br>
+Â Â return true;<br>
  }<br>
-}<br>
-void Type::outputPost(OutputStream &OS) {}<br>
-<br>
-Type *PointerType::clone(ArenaAllocator &Arena) const {<br>
-Â return Arena.alloc<PointerType>(*this);<br>
+Â return false;<br>
 }<br>
<br>
-static void outputPointerIndicator(OutputStream &OS, PointerAffinity Affinity,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const Name *MemberName,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const Type *Pointee) {<br>
-Â // "[]" and "()" (for function parameters) take precedence over "*",<br>
-Â // so "int *x(int)" means "x is a function returning int *". We need<br>
-Â // parentheses to supercede the default precedence. (e.g. we want to<br>
-Â // emit something like "int (*x)(int)".)<br>
-Â if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array) {<br>
-Â Â OS << "(";<br>
-Â Â if (Pointee->Prim == PrimTy::Function) {<br>
-Â Â Â const FunctionType *FTy = static_cast<const FunctionType *>(Pointee);<br>
-Â Â Â assert(FTy->IsFunctionPointer);<br>
-Â Â Â outputCallingConvention(OS, FTy->CallConvention);<br>
-Â Â Â OS << " ";<br>
-Â Â }<br>
-Â }<br>
+static bool isPointerType(StringView S) {<br>
+Â if (S.startsWith("$$Q")) // foo &&<br>
+Â Â return true;<br>
<br>
-Â if (MemberName) {<br>
-Â Â outputName(OS, MemberName, Pointee);<br>
-Â Â OS << "::";<br>
+Â switch (S.front()) {<br>
+Â case 'A': // foo &<br>
+Â case 'P': // foo *<br>
+Â case 'Q': // foo *const<br>
+Â case 'R': // foo *volatile<br>
+Â case 'S': // foo *const volatile<br>
+Â Â return true;<br>
  }<br>
-<br>
-Â if (Affinity == PointerAffinity::Pointer)<br>
-Â Â OS << "*";<br>
-Â else if (Affinity == PointerAffinity::Reference)<br>
-Â Â OS << "&";<br>
-Â else<br>
-Â Â OS << "&&";<br>
-}<br>
-<br>
-void PointerType::outputPre(OutputStream &OS) {<br>
-Â Type::outputPre(OS, *Pointee);<br>
-<br>
-Â outputSpaceIfNecessary(OS);<br>
-<br>
-Â if (Quals & Q_Unaligned)<br>
-Â Â OS << "__unaligned ";<br>
-<br>
-Â outputPointerIndicator(OS, Affinity, nullptr, Pointee);<br>
-<br>
-Â // FIXME: We should output this, but it requires updating lots of tests.<br>
-Â // if (Ty.Quals & Q_Pointer64)<br>
-Â //Â OS << " __ptr64";<br>
-}<br>
-<br>
-void PointerType::outputPost(OutputStream &OS) {<br>
-Â if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array)<br>
-Â Â OS << ")";<br>
-<br>
-Â Type::outputPost(OS, *Pointee);<br>
-}<br>
-<br>
-Type *MemberPointerType::clone(ArenaAllocator &Arena) const {<br>
-Â return Arena.alloc<MemberPointerType>(*this);<br>
-}<br>
-<br>
-void MemberPointerType::outputPre(OutputStream &OS) {<br>
-Â Type::outputPre(OS, *Pointee);<br>
-<br>
-Â outputSpaceIfNecessary(OS);<br>
-<br>
-Â outputPointerIndicator(OS, PointerAffinity::Pointer, MemberName, Pointee);<br>
-<br>
-Â // FIXME: We should output this, but it requires updating lots of tests.<br>
-Â // if (Ty.Quals & Q_Pointer64)<br>
-Â //Â OS << " __ptr64";<br>
-}<br>
-<br>
-void MemberPointerType::outputPost(OutputStream &OS) {<br>
-Â if (Pointee->Prim == PrimTy::Function || Pointee->Prim == PrimTy::Array)<br>
-Â Â OS << ")";<br>
-<br>
-Â Type::outputPost(OS, *Pointee);<br>
-}<br>
-<br>
-Type *FunctionType::clone(ArenaAllocator &Arena) const {<br>
-Â return Arena.alloc<FunctionType>(*this);<br>
+Â return false;<br>
 }<br>
<br>
-void FunctionType::outputPre(OutputStream &OS) {<br>
-Â if ((FunctionClass & StaticThisAdjust) || (FunctionClass & VirtualThisAdjust))<br>
-Â Â OS << "[thunk]: ";<br>
-<br>
-Â if (!(FunctionClass & Global)) {<br>
-Â Â if (FunctionClass & Static)<br>
-Â Â Â OS << "static ";<br>
-Â }<br>
-Â if (FunctionClass & ExternC)<br>
-Â Â OS << "extern \"C\" ";<br>
-<br>
-Â if (FunctionClass & Virtual)<br>
-Â Â OS << "virtual ";<br>
-<br>
-Â if (ReturnType) {<br>
-Â Â Type::outputPre(OS, *ReturnType);<br>
-Â Â OS << " ";<br>
-Â }<br>
+static bool isArrayType(StringView S) { return S[0] == 'Y'; }<br>
<br>
-Â // Function pointers print the calling convention as void (__cdecl *)(params)<br>
- // rather than void __cdecl (*)(params). So we need to let the PointerType<br>
-Â // class handle this.<br>
-Â if (!IsFunctionPointer)<br>
-Â Â outputCallingConvention(OS, CallConvention);<br>
+static bool isFunctionType(StringView S) {<br>
+Â return S.startsWith("$$A8@@") || S.startsWith("$$A6");<br>
 }<br>
<br>
-void FunctionType::outputPost(OutputStream &OS) {<br>
-Â // extern "C" functions don't have a prototype.<br>
-Â if (FunctionClass & NoPrototype)<br>
-Â Â return;<br>
-<br>
-Â if (FunctionClass & StaticThisAdjust) {<br>
-Â Â OS << "`adjustor{" << ThisAdjust->StaticOffset << "}'";<br>
-Â } else if (FunctionClass & VirtualThisAdjust) {<br>
-Â Â if (FunctionClass & VirtualThisAdjustEx) {<br>
-Â Â Â OS << "`vtordispex{" << ThisAdjust->VBPtrOffset << ", "<br>
-Â Â Â Â Â << ThisAdjust->VBOffsetOffset << ", " << ThisAdjust->VtordispOffset<br>
-Â Â Â Â Â << ", " << ThisAdjust->StaticOffset << "}'";<br>
-Â Â } else {<br>
-Â Â Â OS << "`vtordisp{" << ThisAdjust->VtordispOffset << ", "<br>
-Â Â Â Â Â << ThisAdjust->StaticOffset << "}'";<br>
-Â Â }<br>
-Â }<br>
-<br>
-Â OS << "(";<br>
-Â outputParameterList(OS, Params);<br>
-Â OS << ")";<br>
-Â if (Quals & Q_Const)<br>
-Â Â OS << " const";<br>
-Â if (Quals & Q_Volatile)<br>
-Â Â OS << " volatile";<br>
-Â if (Quals & Q_Restrict)<br>
-Â Â OS << " __restrict";<br>
-Â if (Quals & Q_Unaligned)<br>
-Â Â OS << " __unaligned";<br>
-<br>
-Â if (RefKind == ReferenceKind::LValueRef)<br>
-Â Â OS << " &";<br>
-Â else if (RefKind == ReferenceKind::RValueRef)<br>
-Â Â OS << " &&";<br>
-<br>
-Â if (ReturnType)<br>
-Â Â Type::outputPost(OS, *ReturnType);<br>
-Â return;<br>
+static FunctionRefQualifier<br>
+demangleFunctionRefQualifier(StringView &MangledName) {<br>
+Â if (MangledName.consumeFront('G'))<br>
+Â Â return FunctionRefQualifier::Reference;<br>
+Â else if (MangledName.consumeFront('H'))<br>
+Â Â return FunctionRefQualifier::RValueReference;<br>
+Â return FunctionRefQualifier::None;<br>
 }<br>
<br>
-Type *UdtType::clone(ArenaAllocator &Arena) const {<br>
-Â return Arena.alloc<UdtType>(*this);<br>
-}<br>
+static std::pair<Qualifiers, PointerAffinity><br>
+demanglePointerCVQualifiers(StringView &MangledName) {<br>
+Â if (MangledName.consumeFront("$$Q"))<br>
+Â Â return std::make_pair(Q_None, PointerAffinity::RValueReference);<br>
<br>
-void UdtType::outputPre(OutputStream &OS) {<br>
-Â switch (Prim) {<br>
-Â case PrimTy::Class:<br>
-Â Â OS << "class ";<br>
-Â Â break;<br>
-Â case PrimTy::Struct:<br>
-Â Â OS << "struct ";<br>
-Â Â break;<br>
-Â case PrimTy::Union:<br>
-Â Â OS << "union ";<br>
-Â Â break;<br>
-Â case PrimTy::Enum:<br>
-Â Â OS << "enum ";<br>
-Â Â break;<br>
+Â switch (MangledName.popFront()) {<br>
+Â case 'A':<br>
+Â Â return std::make_pair(Q_None, PointerAffinity::Reference);<br>
+Â case 'P':<br>
+Â Â return std::make_pair(Q_None, PointerAffinity::Pointer);<br>
+Â case 'Q':<br>
+Â Â return std::make_pair(Q_Const, PointerAffinity::Pointer);<br>
+Â case 'R':<br>
+Â Â return std::make_pair(Q_Volatile, PointerAffinity::Pointer);<br>
+Â case 'S':<br>
+Â Â return std::make_pair(Qualifiers(Q_Const | Q_Volatile),<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â PointerAffinity::Pointer);<br>
  default:<br>
-Â Â assert(false && "Not a udt type!");<br>
-Â }<br>
-<br>
-Â outputName(OS, UdtName, this);<br>
-}<br>
-<br>
-Type *ArrayType::clone(ArenaAllocator &Arena) const {<br>
-Â return Arena.alloc<ArrayType>(*this);<br>
-}<br>
-<br>
-void ArrayType::outputPre(OutputStream &OS) {<br>
-Â Type::outputPre(OS, *ElementType);<br>
-}<br>
-<br>
-void ArrayType::outputPost(OutputStream &OS) {<br>
-Â ArrayDimension *D = Dims;<br>
-Â while (D) {<br>
-Â Â OS << "[";<br>
-Â Â if (D->Dim > 0)<br>
-Â Â Â OS << D->Dim;<br>
-Â Â OS << "]";<br>
-Â Â D = D->Next;<br>
+Â Â assert(false && "Ty is not a pointer type!");<br>
  }<br>
-<br>
-Â Type::outputPost(OS, *ElementType);<br>
+Â return std::make_pair(Q_None, PointerAffinity::Pointer);<br>
 }<br>
<br>
-struct Symbol {<br>
-Â SymbolCategory Category;<br>
-<br>
-Â Qualifiers SymbolQuals = Q_None;<br>
-Â Name *SymbolName = nullptr;<br>
-Â Type *SymbolType = nullptr;<br>
-};<br>
-<br>
-} // namespace<br>
-<br>
 namespace {<br>
<br>
 struct BackrefContext {<br>
  static constexpr size_t Max = 10;<br>
<br>
-Â Type *FunctionParams[Max];<br>
+Â TypeNode *FunctionParams[Max];<br>
  size_t FunctionParamCount = 0;<br>
<br>
  // The first 10 BackReferences in a mangled name can be back-referenced by<br>
  // special name @[0-9]. This is a storage for the first 10 BackReferences.<br>
-Â StringView Names[Max];<br>
+Â NamedIdentifierNode *Names[Max];<br>
  size_t NamesCount = 0;<br>
 };<br>
<br>
@@ -1404,10 +268,7 @@ public:<br>
<br>
  // You are supposed to call parse() first and then check if error is true. If<br>
  // it is false, call output() to write the formatted name to the given stream.<br>
-Â Symbol *parse(StringView &MangledName);<br>
-Â Symbol *parseOperator(StringView &MangledName);<br>
-<br>
-Â void output(const Symbol *S, OutputStream &OS);<br>
+Â SymbolNode *parse(StringView &MangledName);<br>
<br>
  // True if an error occurred.<br>
  bool Error = false;<br>
@@ -1415,28 +276,28 @@ public:<br>
  void dumpBackReferences();<br>
<br>
 private:<br>
-Â std::pair<SymbolCategory, Type *><br>
-Â demangleSymbolCategoryAndType(StringView &MangledName);<br>
+Â SymbolNode *demangleEncodedSymbol(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â QualifiedNameNode *QN);<br>
<br>
-Â Type *demangleVariableEncoding(StringView &MangledName, StorageClass SC);<br>
-Â Type *demangleFunctionEncoding(StringView &MangledName);<br>
-Â uint64_t demangleThunkThisAdjust(StringView &MangledName);<br>
+Â VariableSymbolNode *demangleVariableEncoding(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â StorageClass SC);<br>
+Â FunctionSymbolNode *demangleFunctionEncoding(StringView &MangledName);<br>
<br>
  Qualifiers demanglePointerExtQualifiers(StringView &MangledName);<br>
<br>
  // Parser functions. This is a recursive-descent parser.<br>
-Â Type *demangleType(StringView &MangledName, QualifierMangleMode QMM);<br>
-Â Type *demangleBasicType(StringView &MangledName);<br>
-Â UdtType *demangleClassType(StringView &MangledName);<br>
-Â PointerType *demanglePointerType(StringView &MangledName);<br>
-Â MemberPointerType *demangleMemberPointerType(StringView &MangledName);<br>
-Â FunctionType *demangleFunctionType(StringView &MangledName, bool HasThisQuals,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool IsFunctionPointer);<br>
+Â TypeNode *demangleType(StringView &MangledName, QualifierMangleMode QMM);<br>
+Â PrimitiveTypeNode *demanglePrimitiveType(StringView &MangledName);<br>
+Â TagTypeNode *demangleClassType(StringView &MangledName);<br>
+Â PointerTypeNode *demanglePointerType(StringView &MangledName);<br>
+Â PointerTypeNode *demangleMemberPointerType(StringView &MangledName);<br>
+Â FunctionSignatureNode *demangleFunctionType(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool HasThisQuals);<br>
<br>
-Â ArrayType *demangleArrayType(StringView &MangledName);<br>
+Â ArrayTypeNode *demangleArrayType(StringView &MangledName);<br>
<br>
-Â TemplateParams *demangleTemplateParameterList(StringView &MangledName);<br>
-Â FunctionParams demangleFunctionParameterList(StringView &MangledName);<br>
+Â NodeArrayNode *demangleTemplateParameterList(StringView &MangledName);<br>
+Â NodeArrayNode *demangleFunctionParameterList(StringView &MangledName);<br>
<br>
  std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);<br>
  uint64_t demangleUnsigned(StringView &MangledName);<br>
@@ -1447,32 +308,59 @@ private:<br>
  /// Allocate a copy of \p Borrowed into memory that we own.<br>
  StringView copyString(StringView Borrowed);<br>
<br>
-Â Name *demangleFullyQualifiedTypeName(StringView &MangledName);<br>
-Â Name *demangleFullyQualifiedSymbolName(StringView &MangledName);<br>
+Â QualifiedNameNode *demangleFullyQualifiedTypeName(StringView &MangledName);<br>
+Â QualifiedNameNode *demangleFullyQualifiedSymbolName(StringView &MangledName);<br>
<br>
-Â Name *demangleUnqualifiedTypeName(StringView &MangledName, bool Memorize);<br>
-Â Name *demangleUnqualifiedSymbolName(StringView &MangledName,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NameBackrefBehavior NBB);<br>
-<br>
-Â Name *demangleNameScopeChain(StringView &MangledName, Name *UnqualifiedName);<br>
-Â Name *demangleNameScopePiece(StringView &MangledName);<br>
-<br>
-Â Name *demangleBackRefName(StringView &MangledName);<br>
-Â Name *demangleTemplateInstantiationName(StringView &MangledName,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NameBackrefBehavior NBB);<br>
-Â std::pair<OperatorTy, Name *> demangleOperatorName(StringView &MangledName,<br>
-Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool FullyQualified);<br>
-Â Name *demangleSimpleName(StringView &MangledName, bool Memorize);<br>
-Â Name *demangleAnonymousNamespaceName(StringView &MangledName);<br>
-Â Name *demangleLocallyScopedNamePiece(StringView &MangledName);<br>
-Â StringLiteral *demangleStringLiteral(StringView &MangledName);<br>
+Â IdentifierNode *demangleUnqualifiedTypeName(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool Memorize);<br>
+Â IdentifierNode *demangleUnqualifiedSymbolName(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NameBackrefBehavior NBB);<br>
+<br>
+Â QualifiedNameNode *demangleNameScopeChain(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â IdentifierNode *UnqualifiedName);<br>
+Â IdentifierNode *demangleNameScopePiece(StringView &MangledName);<br>
+<br>
+Â NamedIdentifierNode *demangleBackRefName(StringView &MangledName);<br>
+Â IdentifierNode *demangleTemplateInstantiationName(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NameBackrefBehavior NBB);<br>
+Â IdentifierNode *demangleFunctionIdentifierCode(StringView &MangledName);<br>
+Â IdentifierNode *<br>
+Â demangleFunctionIdentifierCode(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â FunctionIdentifierCodeGroup Group);<br>
+Â StructorIdentifierNode *demangleStructorIdentifier(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool IsDestructor);<br>
+Â ConversionOperatorIdentifierNode *<br>
+Â demangleConversionOperatorIdentifier(StringView &MangledName);<br>
+Â LiteralOperatorIdentifierNode *<br>
+Â demangleLiteralOperatorIdentifier(StringView &MangledName);<br>
+<br>
+Â SymbolNode *demangleSpecialIntrinsic(StringView &MangledName);<br>
+Â SpecialTableSymbolNode *<br>
+Â demangleSpecialTableSymbolNode(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SpecialIntrinsicKind SIK);<br>
+Â LocalStaticGuardVariableNode *<br>
+Â demangleLocalStaticGuard(StringView &MangledName);<br>
+Â VariableSymbolNode *demangleUntypedVariable(ArenaAllocator &Arena,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â StringView VariableName);<br>
+Â VariableSymbolNode *<br>
+Â demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â StringView &MangledName);<br>
+Â FunctionSymbolNode *demangleDynamicStructorFunction(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool IsDestructor);<br>
+<br>
+Â NamedIdentifierNode *demangleSimpleName(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool Memorize);<br>
+Â NamedIdentifierNode *demangleAnonymousNamespaceName(StringView &MangledName);<br>
+Â NamedIdentifierNode *demangleLocallyScopedNamePiece(StringView &MangledName);<br>
+Â EncodedStringLiteralNode *demangleStringLiteral(StringView &MangledName);<br>
+Â FunctionSymbolNode *demangleVcallThunkNode(StringView &MangledName);<br>
<br>
  StringView demangleSimpleString(StringView &MangledName, bool Memorize);<br>
<br>
  FuncClass demangleFunctionClass(StringView &MangledName);<br>
  CallingConv demangleCallingConvention(StringView &MangledName);<br>
  StorageClass demangleVariableStorageClass(StringView &MangledName);<br>
-Â ReferenceKind demangleReferenceKind(StringView &MangledName);<br>
  void demangleThrowSpecification(StringView &MangledName);<br>
  wchar_t demangleWcharLiteral(StringView &MangledName);<br>
  uint8_t demangleCharLiteral(StringView &MangledName);<br>
@@ -1506,121 +394,455 @@ StringView Demangler::copyString(StringV<br>
  return {Stable, Borrowed.size()};<br>
 }<br>
<br>
-Symbol *Demangler::parseOperator(StringView &MangledName) {<br>
-Â Symbol *S = Arena.alloc<Symbol>();<br>
-<br>
-Â bool IsMember = false;<br>
-Â OperatorTy OTy;<br>
-Â std::tie(OTy, S->SymbolName) = demangleOperatorName(MangledName, true);<br>
-Â switch (OTy) {<br>
-Â case OperatorTy::StringLiteral:<br>
-Â Â S->Category = SymbolCategory::SpecialOperator;<br>
+SpecialTableSymbolNode *<br>
+Demangler::demangleSpecialTableSymbolNode(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SpecialIntrinsicKind K) {<br>
+Â NamedIdentifierNode *NI = Arena.alloc<NamedIdentifierNode>();<br>
+Â switch (K) {<br>
+Â case SpecialIntrinsicKind::Vftable:<br>
+Â Â NI->Name = "`vftable'";<br>
   break;<br>
-Â case OperatorTy::Vcall:<br>
-Â Â S->Category = SymbolCategory::UnnamedFunction;<br>
+Â case SpecialIntrinsicKind::Vbtable:<br>
+Â Â NI->Name = "`vbtable'";<br>
   break;<br>
-Â case OperatorTy::LocalStaticGuard:<br>
-Â Â S->Category = SymbolCategory::UnnamedVariable;<br>
+Â case SpecialIntrinsicKind::LocalVftable:<br>
+Â Â NI->Name = "`local vftable'";<br>
   break;<br>
-Â case OperatorTy::Vftable:Â Â Â Â Â Â Â Â // Foo@@6B@<br>
-Â case OperatorTy::LocalVftable:Â Â Â Â Â Â // Foo@@6B@<br>
-Â case OperatorTy::RttiCompleteObjLocator: // Foo@@6B@<br>
-Â case OperatorTy::Vbtable:Â Â Â Â Â Â Â Â // Foo@@7B@<br>
-Â Â S->Category = SymbolCategory::UnnamedVariable;<br>
-Â Â switch (MangledName.popFront()) {<br>
-Â Â case '6':<br>
-Â Â case '7': {<br>
-Â Â Â std::tie(S->SymbolQuals, IsMember) = demangleQualifiers(MangledName);<br>
-Â Â Â if (!MangledName.consumeFront('@')) {<br>
-Â Â Â Â IndirectTable *Table = Arena.alloc<IndirectTable>(OTy);<br>
-Â Â Â Â Table->TableTarget = demangleFullyQualifiedTypeName(MangledName);<br>
-Â Â Â Â Table->TableLocation = S->SymbolName;<br>
-Â Â Â Â S->SymbolName = Table;<br>
-Â Â Â }<br>
-Â Â Â break;<br>
-Â Â }<br>
-Â Â default:<br>
-Â Â Â Error = true;<br>
-Â Â Â break;<br>
-Â Â }<br>
+Â case SpecialIntrinsicKind::RttiCompleteObjLocator:<br>
+Â Â NI->Name = "`RTTI Complete Object Locator'";<br>
   break;<br>
-Â case OperatorTy::RttiTypeDescriptor: // <type>@@8<br>
-Â Â S->Category = SymbolCategory::UnnamedVariable;<br>
-Â Â S->SymbolType = demangleType(MangledName, QualifierMangleMode::Result);<br>
+Â default:<br>
+Â Â LLVM_BUILTIN_UNREACHABLE;<br>
+Â }<br>
+Â QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);<br>
+Â SpecialTableSymbolNode *STSN = Arena.alloc<SpecialTableSymbolNode>();<br>
+Â STSN->Name = QN;<br>
+Â bool IsMember = false;<br>
+Â char Front = MangledName.popFront();<br>
+Â if (Front != '6' && Front != '7') {<br>
+Â Â Error = true;<br>
+Â Â return nullptr;<br>
+Â }<br>
+<br>
+Â std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName);<br>
+Â if (!MangledName.consumeFront('@'))<br>
+Â Â STSN->TargetName = demangleFullyQualifiedTypeName(MangledName);<br>
+Â return STSN;<br>
+}<br>
+<br>
+LocalStaticGuardVariableNode *<br>
+Demangler::demangleLocalStaticGuard(StringView &MangledName) {<br>
+Â LocalStaticGuardIdentifierNode *LSGI =<br>
+Â Â Â Arena.alloc<LocalStaticGuardIdentifierNode>();<br>
+Â QualifiedNameNode *QN = demangleNameScopeChain(MangledName, LSGI);<br>
+Â LocalStaticGuardVariableNode *LSGVN =<br>
+Â Â Â Arena.alloc<LocalStaticGuardVariableNode>();<br>
+Â LSGVN->Name = QN;<br>
+<br>
+Â if (MangledName.consumeFront("4IA"))<br>
+Â Â LSGVN->IsVisible = false;<br>
+Â else if (MangledName.consumeFront("5"))<br>
+Â Â LSGVN->IsVisible = true;<br>
+Â else {<br>
+Â Â Error = true;<br>
+Â Â return nullptr;<br>
+Â }<br>
+<br>
+Â if (!MangledName.empty())<br>
+Â Â LSGI->ScopeIndex = demangleUnsigned(MangledName);<br>
+Â return LSGVN;<br>
+}<br>
+<br>
+static NamedIdentifierNode *synthesizeNamedIdentifier(ArenaAllocator &Arena,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â StringView Name) {<br>
+Â NamedIdentifierNode *Id = Arena.alloc<NamedIdentifierNode>();<br>
+Â Id->Name = Name;<br>
+Â return Id;<br>
+}<br>
+<br>
+static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â IdentifierNode *Identifier) {<br>
+Â QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>();<br>
+Â QN->Components = Arena.alloc<NodeArrayNode>();<br>
+Â QN->Components->Count = 1;<br>
+Â QN->Components->Nodes = Arena.allocArray<Node *>(1);<br>
+Â QN->Components->Nodes[0] = Identifier;<br>
+Â return QN;<br>
+}<br>
+<br>
+static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â StringView Name) {<br>
+Â NamedIdentifierNode *Id = synthesizeNamedIdentifier(Arena, Name);<br>
+Â return synthesizeQualifiedName(Arena, Id);<br>
+}<br>
+<br>
+static VariableSymbolNode *synthesizeVariable(ArenaAllocator &Arena,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â TypeNode *Type,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â StringView VariableName) {<br>
+Â VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();<br>
+Â VSN->Type = Type;<br>
+Â VSN->Name = synthesizeQualifiedName(Arena, VariableName);<br>
+Â return VSN;<br>
+}<br>
+<br>
+VariableSymbolNode *Demangler::demangleUntypedVariable(<br>
+Â Â ArenaAllocator &Arena, StringView &MangledName, StringView VariableName) {<br>
+Â NamedIdentifierNode *NI = synthesizeNamedIdentifier(Arena, VariableName);<br>
+Â QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);<br>
+Â VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();<br>
+Â VSN->Name = QN;<br>
+Â if (MangledName.consumeFront("8"))<br>
+Â Â return VSN;<br>
+<br>
+Â Error = true;<br>
+Â return nullptr;<br>
+}<br>
+<br>
+VariableSymbolNode *<br>
+Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â StringView &MangledName) {<br>
+Â RttiBaseClassDescriptorNode *RBCDN =<br>
+Â Â Â Arena.alloc<RttiBaseClassDescriptorNode>();<br>
+Â RBCDN->NVOffset = demangleUnsigned(MangledName);<br>
+Â RBCDN->VBPtrOffset = demangleSigned(MangledName);<br>
+Â RBCDN->VBTableOffset = demangleUnsigned(MangledName);<br>
+Â RBCDN->Flags = demangleUnsigned(MangledName);<br>
+Â if (Error)<br>
+Â Â return nullptr;<br>
+<br>
+Â VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();<br>
+Â VSN->Name = demangleNameScopeChain(MangledName, RBCDN);<br>
+Â MangledName.consumeFront('8');<br>
+Â return VSN;<br>
+}<br>
+<br>
+FunctionSymbolNode *<br>
+Demangler::demangleDynamicStructorFunction(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool IsDestructor) {<br>
+Â DynamicStructorIdentifierNode *DSIN =<br>
+Â Â Â Arena.alloc<DynamicStructorIdentifierNode>();<br>
+Â DSIN->IsDestructor = IsDestructor;<br>
+Â DSIN->Name = demangleFullyQualifiedTypeName(MangledName);<br>
+Â QualifiedNameNode *QNN = synthesizeQualifiedName(Arena, DSIN);<br>
+Â FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName);<br>
+Â FSN->Name = QNN;<br>
+Â return FSN;<br>
+}<br>
+<br>
+SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) {<br>
+Â SpecialIntrinsicKind SIK = consumeSpecialIntrinsicKind(MangledName);<br>
+Â if (SIK == SpecialIntrinsicKind::None)<br>
+Â Â return nullptr;<br>
+<br>
+Â switch (SIK) {<br>
+Â case SpecialIntrinsicKind::StringLiteralSymbol:<br>
+Â Â return demangleStringLiteral(MangledName);<br>
+Â case SpecialIntrinsicKind::Vftable:<br>
+Â case SpecialIntrinsicKind::Vbtable:<br>
+Â case SpecialIntrinsicKind::LocalVftable:<br>
+Â case SpecialIntrinsicKind::RttiCompleteObjLocator:<br>
+Â Â return demangleSpecialTableSymbolNode(MangledName, SIK);<br>
+Â case SpecialIntrinsicKind::VcallThunk:<br>
+Â Â return demangleVcallThunkNode(MangledName);<br>
+Â case SpecialIntrinsicKind::LocalStaticGuard:<br>
+Â Â return demangleLocalStaticGuard(MangledName);<br>
+Â case SpecialIntrinsicKind::RttiTypeDescriptor: {<br>
+Â Â TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result);<br>
   if (Error)<br>
    break;<br>
   if (!MangledName.consumeFront("@8"))<br>
-Â Â Â Error = true;<br>
+Â Â Â break;<br>
   if (!MangledName.empty())<br>
-Â Â Â Error = true;<br>
-Â Â break;<br>
+Â Â Â break;<br>
+Â Â return synthesizeVariable(Arena, T, "`RTTI Type Descriptor'");<br>
+Â }<br>
+Â case SpecialIntrinsicKind::RttiBaseClassArray:<br>
+Â Â return demangleUntypedVariable(Arena, MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â "`RTTI Base Class Array'");<br>
+Â case SpecialIntrinsicKind::RttiClassHierarchyDescriptor:<br>
+Â Â return demangleUntypedVariable(Arena, MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â "`RTTI Class Hierarchy Descriptor'");<br>
+Â case SpecialIntrinsicKind::RttiBaseClassDescriptor:<br>
+Â Â return demangleRttiBaseClassDescriptorNode(Arena, MangledName);<br>
+Â case SpecialIntrinsicKind::DynamicInitializer:<br>
+Â Â return demangleDynamicStructorFunction(MangledName, false);<br>
+Â case SpecialIntrinsicKind::DynamicAtexitDestructor:<br>
+Â Â return demangleDynamicStructorFunction(MangledName, true);<br>
  default:<br>
-Â Â if (!Error)<br>
-Â Â Â std::tie(S->Category, S->SymbolType) =<br>
-Â Â Â Â Â demangleSymbolCategoryAndType(MangledName);<br>
   break;<br>
  }<br>
+Â Error = true;<br>
+Â return nullptr;<br>
+}<br>
+<br>
+IdentifierNode *<br>
+Demangler::demangleFunctionIdentifierCode(StringView &MangledName) {<br>
+Â assert(MangledName.startsWith('?'));<br>
+Â MangledName = MangledName.dropFront();<br>
+<br>
+Â if (MangledName.consumeFront("__"))<br>
+Â Â return demangleFunctionIdentifierCode(<br>
+Â Â Â Â MangledName, FunctionIdentifierCodeGroup::DoubleUnder);<br>
+Â else if (MangledName.consumeFront("_"))<br>
+Â Â return demangleFunctionIdentifierCode(MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â FunctionIdentifierCodeGroup::Under);<br>
+Â return demangleFunctionIdentifierCode(MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â FunctionIdentifierCodeGroup::Basic);<br>
+}<br>
+<br>
+StructorIdentifierNode *<br>
+Demangler::demangleStructorIdentifier(StringView &MangledName,<br>
+Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â bool IsDestructor) {<br>
+Â StructorIdentifierNode *N = Arena.alloc<StructorIdentifierNode>();<br>
+Â N->IsDestructor = IsDestructor;<br>
+Â return N;<br>
+}<br>
+<br>
+ConversionOperatorIdentifierNode *<br>
+Demangler::demangleConversionOperatorIdentifier(StringView &MangledName) {<br>
+Â ConversionOperatorIdentifierNode *N =<br>
+Â Â Â Arena.alloc<ConversionOperatorIdentifierNode>();<br>
+Â return N;<br>
+}<br>
+<br>
+LiteralOperatorIdentifierNode *<br>
+Demangler::demangleLiteralOperatorIdentifier(StringView &MangledName) {<br>
+Â LiteralOperatorIdentifierNode *N =<br>
+Â Â Â Arena.alloc<LiteralOperatorIdentifierNode>();<br>
+Â N->Name = demangleSimpleString(MangledName, false);<br>
+Â return N;<br>
+}<br>
+<br>
+IntrinsicFunctionKind<br>
+translateIntrinsicFunctionCode(char CH, FunctionIdentifierCodeGroup Group) {<br>
+ // Not all ? identifiers are intrinsics *functions*. This function only maps<br>
+Â // operator codes for the special functions, all others are handled elsewhere,<br>
+Â // hence the IFK::None entries in the table.<br>
+Â using IFK = IntrinsicFunctionKind;<br>
+Â static IFK Basic[36] = {<br>
+   IFK::None,       // ?0 # Foo::Foo()<br>
+   IFK::None,       // ?1 # Foo::~Foo()<br>
+   IFK::New,       // ?2 # operator new<br>
+   IFK::Delete,      // ?3 # operator delete<br>
+   IFK::Assign,      // ?4 # operator=<br>
+   IFK::RightShift,    // ?5 # operator>><br>
+   IFK::LeftShift,    // ?6 # operator<<<br>
+   IFK::LogicalNot,    // ?7 # operator!<br>
+   IFK::Equals,      // ?8 # operator==<br>
+   IFK::NotEquals,    // ?9 # operator!=<br>
+   IFK::ArraySubscript,  // ?A # operator[]<br>
+   IFK::None,       // ?B # Foo::operator <type>()<br>
+   IFK::Pointer,     // ?C # operator-><br>
+   IFK::Dereference,   // ?D # operator*<br>
+   IFK::Increment,    // ?E # operator++<br>
+   IFK::Decrement,    // ?F # operator--<br>
+   IFK::Minus,      // ?G # operator-<br>
+   IFK::Plus,       // ?H # operator+<br>
+Â Â Â IFK::BitwiseA</blockquote></div>