1f435a7eaSZachary Turner //===- MicrosoftDemangle.cpp ----------------------------------------------===//
2f435a7eaSZachary Turner //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f435a7eaSZachary Turner //
7f435a7eaSZachary Turner //===----------------------------------------------------------------------===//
8f435a7eaSZachary Turner //
9f435a7eaSZachary Turner // This file defines a demangler for MSVC-style mangled symbols.
10f435a7eaSZachary Turner //
11f435a7eaSZachary Turner // This file has no dependencies on the rest of LLVM so that it can be
12f435a7eaSZachary Turner // easily reused in other programs such as libcxxabi.
13f435a7eaSZachary Turner //
14f435a7eaSZachary Turner //===----------------------------------------------------------------------===//
15f435a7eaSZachary Turner 
167ba90563SZachary Turner #include "llvm/Demangle/MicrosoftDemangle.h"
17f435a7eaSZachary Turner #include "llvm/Demangle/Demangle.h"
187ba90563SZachary Turner #include "llvm/Demangle/MicrosoftDemangleNodes.h"
19f435a7eaSZachary Turner 
205094e5efSErik Pilkington #include "llvm/Demangle/DemangleConfig.h"
218a57f2e0SRichard Smith #include "llvm/Demangle/StringView.h"
228a57f2e0SRichard Smith #include "llvm/Demangle/Utility.h"
23f435a7eaSZachary Turner 
2466555a7bSZachary Turner #include <array>
25f435a7eaSZachary Turner #include <cctype>
265ae08b85SZachary Turner #include <cstdio>
27d742d645SZachary Turner #include <tuple>
28f435a7eaSZachary Turner 
2903312863SZachary Turner using namespace llvm;
3003312863SZachary Turner using namespace ms_demangle;
31f435a7eaSZachary Turner 
startsWithDigit(StringView S)32f435a7eaSZachary Turner static bool startsWithDigit(StringView S) {
33f435a7eaSZachary Turner   return !S.empty() && std::isdigit(S.front());
34f435a7eaSZachary Turner }
35f435a7eaSZachary Turner 
36d742d645SZachary Turner 
3703312863SZachary Turner struct NodeList {
3803312863SZachary Turner   Node *N = nullptr;
3903312863SZachary Turner   NodeList *Next = nullptr;
40f435a7eaSZachary Turner };
41f435a7eaSZachary Turner 
isMemberPointer(StringView MangledName,bool & Error)428fb9a71dSZachary Turner static bool isMemberPointer(StringView MangledName, bool &Error) {
438fb9a71dSZachary Turner   Error = false;
44d742d645SZachary Turner   switch (MangledName.popFront()) {
45931e879cSZachary Turner   case '$':
46931e879cSZachary Turner     // This is probably an rvalue reference (e.g. $$Q), and you cannot have an
47931e879cSZachary Turner     // rvalue reference to a member.
48931e879cSZachary Turner     return false;
49d742d645SZachary Turner   case 'A':
50d742d645SZachary Turner     // 'A' indicates a reference, and you cannot have a reference to a member
51931e879cSZachary Turner     // function or member.
52d742d645SZachary Turner     return false;
53d742d645SZachary Turner   case 'P':
54d742d645SZachary Turner   case 'Q':
55d742d645SZachary Turner   case 'R':
56d742d645SZachary Turner   case 'S':
57d742d645SZachary Turner     // These 4 values indicate some kind of pointer, but we still don't know
58d742d645SZachary Turner     // what.
59d742d645SZachary Turner     break;
60d742d645SZachary Turner   default:
61880d21d3SNico Weber     // isMemberPointer() is called only if isPointerType() returns true,
62880d21d3SNico Weber     // and it rejects other prefixes.
63880d21d3SNico Weber     DEMANGLE_UNREACHABLE;
64d742d645SZachary Turner   }
65d742d645SZachary Turner 
66d742d645SZachary Turner   // If it starts with a number, then 6 indicates a non-member function
67d742d645SZachary Turner   // pointer, and 8 indicates a member function pointer.
68d742d645SZachary Turner   if (startsWithDigit(MangledName)) {
6963b97d2aSNico Weber     if (MangledName[0] != '6' && MangledName[0] != '8') {
7063b97d2aSNico Weber       Error = true;
7163b97d2aSNico Weber       return false;
7263b97d2aSNico Weber     }
73d742d645SZachary Turner     return (MangledName[0] == '8');
74d742d645SZachary Turner   }
75d742d645SZachary Turner 
76d742d645SZachary Turner   // Remove ext qualifiers since those can appear on either type and are
77d742d645SZachary Turner   // therefore not indicative.
78d742d645SZachary Turner   MangledName.consumeFront('E'); // 64-bit
79d742d645SZachary Turner   MangledName.consumeFront('I'); // restrict
80d742d645SZachary Turner   MangledName.consumeFront('F'); // unaligned
81d742d645SZachary Turner 
8263b97d2aSNico Weber   if (MangledName.empty()) {
8363b97d2aSNico Weber     Error = true;
8463b97d2aSNico Weber     return false;
8563b97d2aSNico Weber   }
86d742d645SZachary Turner 
87d742d645SZachary Turner   // The next value should be either ABCD (non-member) or QRST (member).
88d742d645SZachary Turner   switch (MangledName.front()) {
89d742d645SZachary Turner   case 'A':
90d742d645SZachary Turner   case 'B':
91d742d645SZachary Turner   case 'C':
92d742d645SZachary Turner   case 'D':
93d742d645SZachary Turner     return false;
94d742d645SZachary Turner   case 'Q':
95d742d645SZachary Turner   case 'R':
96d742d645SZachary Turner   case 'S':
97d742d645SZachary Turner   case 'T':
98d742d645SZachary Turner     return true;
99d742d645SZachary Turner   default:
1008fb9a71dSZachary Turner     Error = true;
101d742d645SZachary Turner     return false;
102d742d645SZachary Turner   }
1038fb9a71dSZachary Turner }
104d742d645SZachary Turner 
10503312863SZachary Turner static SpecialIntrinsicKind
consumeSpecialIntrinsicKind(StringView & MangledName)10603312863SZachary Turner consumeSpecialIntrinsicKind(StringView &MangledName) {
10703312863SZachary Turner   if (MangledName.consumeFront("?_7"))
10803312863SZachary Turner     return SpecialIntrinsicKind::Vftable;
10903312863SZachary Turner   if (MangledName.consumeFront("?_8"))
11003312863SZachary Turner     return SpecialIntrinsicKind::Vbtable;
11103312863SZachary Turner   if (MangledName.consumeFront("?_9"))
11203312863SZachary Turner     return SpecialIntrinsicKind::VcallThunk;
11303312863SZachary Turner   if (MangledName.consumeFront("?_A"))
11403312863SZachary Turner     return SpecialIntrinsicKind::Typeof;
11503312863SZachary Turner   if (MangledName.consumeFront("?_B"))
11603312863SZachary Turner     return SpecialIntrinsicKind::LocalStaticGuard;
11703312863SZachary Turner   if (MangledName.consumeFront("?_C"))
11803312863SZachary Turner     return SpecialIntrinsicKind::StringLiteralSymbol;
11903312863SZachary Turner   if (MangledName.consumeFront("?_P"))
12003312863SZachary Turner     return SpecialIntrinsicKind::UdtReturning;
12103312863SZachary Turner   if (MangledName.consumeFront("?_R0"))
12203312863SZachary Turner     return SpecialIntrinsicKind::RttiTypeDescriptor;
12303312863SZachary Turner   if (MangledName.consumeFront("?_R1"))
12403312863SZachary Turner     return SpecialIntrinsicKind::RttiBaseClassDescriptor;
12503312863SZachary Turner   if (MangledName.consumeFront("?_R2"))
12603312863SZachary Turner     return SpecialIntrinsicKind::RttiBaseClassArray;
12703312863SZachary Turner   if (MangledName.consumeFront("?_R3"))
12803312863SZachary Turner     return SpecialIntrinsicKind::RttiClassHierarchyDescriptor;
12903312863SZachary Turner   if (MangledName.consumeFront("?_R4"))
13003312863SZachary Turner     return SpecialIntrinsicKind::RttiCompleteObjLocator;
13103312863SZachary Turner   if (MangledName.consumeFront("?_S"))
13203312863SZachary Turner     return SpecialIntrinsicKind::LocalVftable;
13303312863SZachary Turner   if (MangledName.consumeFront("?__E"))
13403312863SZachary Turner     return SpecialIntrinsicKind::DynamicInitializer;
13503312863SZachary Turner   if (MangledName.consumeFront("?__F"))
13603312863SZachary Turner     return SpecialIntrinsicKind::DynamicAtexitDestructor;
13703312863SZachary Turner   if (MangledName.consumeFront("?__J"))
13803312863SZachary Turner     return SpecialIntrinsicKind::LocalStaticThreadGuard;
13903312863SZachary Turner   return SpecialIntrinsicKind::None;
140f435a7eaSZachary Turner }
141f435a7eaSZachary Turner 
startsWithLocalScopePattern(StringView S)14271c91f94SZachary Turner static bool startsWithLocalScopePattern(StringView S) {
14371c91f94SZachary Turner   if (!S.consumeFront('?'))
14471c91f94SZachary Turner     return false;
14571c91f94SZachary Turner 
14671c91f94SZachary Turner   size_t End = S.find('?');
14771c91f94SZachary Turner   if (End == StringView::npos)
14871c91f94SZachary Turner     return false;
14971c91f94SZachary Turner   StringView Candidate = S.substr(0, End);
15071c91f94SZachary Turner   if (Candidate.empty())
15171c91f94SZachary Turner     return false;
15271c91f94SZachary Turner 
15371c91f94SZachary Turner   // \?[0-9]\?
15471c91f94SZachary Turner   // ?@? is the discriminator 0.
15571c91f94SZachary Turner   if (Candidate.size() == 1)
15671c91f94SZachary Turner     return Candidate[0] == '@' || (Candidate[0] >= '0' && Candidate[0] <= '9');
15771c91f94SZachary Turner 
15871c91f94SZachary Turner   // If it's not 0-9, then it's an encoded number terminated with an @
15971c91f94SZachary Turner   if (Candidate.back() != '@')
16071c91f94SZachary Turner     return false;
16171c91f94SZachary Turner   Candidate = Candidate.dropBack();
16271c91f94SZachary Turner 
16371c91f94SZachary Turner   // An encoded number starts with B-P and all subsequent digits are in A-P.
16471c91f94SZachary Turner   // Note that the reason the first digit cannot be A is two fold.  First, it
16571c91f94SZachary Turner   // would create an ambiguity with ?A which delimits the beginning of an
16671c91f94SZachary Turner   // anonymous namespace.  Second, A represents 0, and you don't start a multi
16771c91f94SZachary Turner   // digit number with a leading 0.  Presumably the anonymous namespace
16871c91f94SZachary Turner   // ambiguity is also why single digit encoded numbers use 0-9 rather than A-J.
16971c91f94SZachary Turner   if (Candidate[0] < 'B' || Candidate[0] > 'P')
17071c91f94SZachary Turner     return false;
17171c91f94SZachary Turner   Candidate = Candidate.dropFront();
17271c91f94SZachary Turner   while (!Candidate.empty()) {
17371c91f94SZachary Turner     if (Candidate[0] < 'A' || Candidate[0] > 'P')
17471c91f94SZachary Turner       return false;
17571c91f94SZachary Turner     Candidate = Candidate.dropFront();
17671c91f94SZachary Turner   }
17771c91f94SZachary Turner 
17871c91f94SZachary Turner   return true;
17971c91f94SZachary Turner }
18071c91f94SZachary Turner 
isTagType(StringView S)18103312863SZachary Turner static bool isTagType(StringView S) {
18203312863SZachary Turner   switch (S.front()) {
18303312863SZachary Turner   case 'T': // union
18403312863SZachary Turner   case 'U': // struct
18503312863SZachary Turner   case 'V': // class
18603312863SZachary Turner   case 'W': // enum
18703312863SZachary Turner     return true;
18803312863SZachary Turner   }
18903312863SZachary Turner   return false;
19038b78a7fSZachary Turner }
19138b78a7fSZachary Turner 
isCustomType(StringView S)192b2fef1a0SZachary Turner static bool isCustomType(StringView S) { return S[0] == '?'; }
193b2fef1a0SZachary Turner 
isPointerType(StringView S)19403312863SZachary Turner static bool isPointerType(StringView S) {
19503312863SZachary Turner   if (S.startsWith("$$Q")) // foo &&
19603312863SZachary Turner     return true;
197f435a7eaSZachary Turner 
19803312863SZachary Turner   switch (S.front()) {
19903312863SZachary Turner   case 'A': // foo &
20003312863SZachary Turner   case 'P': // foo *
20103312863SZachary Turner   case 'Q': // foo *const
20203312863SZachary Turner   case 'R': // foo *volatile
20303312863SZachary Turner   case 'S': // foo *const volatile
20403312863SZachary Turner     return true;
205f435a7eaSZachary Turner   }
20603312863SZachary Turner   return false;
207f435a7eaSZachary Turner }
208f435a7eaSZachary Turner 
isArrayType(StringView S)20903312863SZachary Turner static bool isArrayType(StringView S) { return S[0] == 'Y'; }
21003312863SZachary Turner 
isFunctionType(StringView S)21103312863SZachary Turner static bool isFunctionType(StringView S) {
21203312863SZachary Turner   return S.startsWith("$$A8@@") || S.startsWith("$$A6");
21303312863SZachary Turner }
21403312863SZachary Turner 
21503312863SZachary Turner static FunctionRefQualifier
demangleFunctionRefQualifier(StringView & MangledName)21603312863SZachary Turner demangleFunctionRefQualifier(StringView &MangledName) {
21703312863SZachary Turner   if (MangledName.consumeFront('G'))
21803312863SZachary Turner     return FunctionRefQualifier::Reference;
21903312863SZachary Turner   else if (MangledName.consumeFront('H'))
22003312863SZachary Turner     return FunctionRefQualifier::RValueReference;
22103312863SZachary Turner   return FunctionRefQualifier::None;
22203312863SZachary Turner }
22303312863SZachary Turner 
22403312863SZachary Turner static std::pair<Qualifiers, PointerAffinity>
demanglePointerCVQualifiers(StringView & MangledName)22503312863SZachary Turner demanglePointerCVQualifiers(StringView &MangledName) {
22603312863SZachary Turner   if (MangledName.consumeFront("$$Q"))
22703312863SZachary Turner     return std::make_pair(Q_None, PointerAffinity::RValueReference);
22803312863SZachary Turner 
22903312863SZachary Turner   switch (MangledName.popFront()) {
23003312863SZachary Turner   case 'A':
23103312863SZachary Turner     return std::make_pair(Q_None, PointerAffinity::Reference);
23203312863SZachary Turner   case 'P':
23303312863SZachary Turner     return std::make_pair(Q_None, PointerAffinity::Pointer);
23403312863SZachary Turner   case 'Q':
23503312863SZachary Turner     return std::make_pair(Q_Const, PointerAffinity::Pointer);
23603312863SZachary Turner   case 'R':
23703312863SZachary Turner     return std::make_pair(Q_Volatile, PointerAffinity::Pointer);
23803312863SZachary Turner   case 'S':
23903312863SZachary Turner     return std::make_pair(Qualifiers(Q_Const | Q_Volatile),
24003312863SZachary Turner                           PointerAffinity::Pointer);
241970fdc32SZachary Turner   }
242c1a0e6feSNico Weber   // This function is only called if isPointerType() returns true,
243c1a0e6feSNico Weber   // and it only returns true for the six cases listed above.
244c1a0e6feSNico Weber   DEMANGLE_UNREACHABLE;
245970fdc32SZachary Turner }
246970fdc32SZachary Turner 
copyString(StringView Borrowed)24771c91f94SZachary Turner StringView Demangler::copyString(StringView Borrowed) {
248d1587c38SNathan Sidwell   char *Stable = Arena.allocUnalignedBuffer(Borrowed.size());
249d1587c38SNathan Sidwell   std::memcpy(Stable, Borrowed.begin(), Borrowed.size());
25071c91f94SZachary Turner 
25171c91f94SZachary Turner   return {Stable, Borrowed.size()};
25271c91f94SZachary Turner }
25371c91f94SZachary Turner 
25403312863SZachary Turner SpecialTableSymbolNode *
demangleSpecialTableSymbolNode(StringView & MangledName,SpecialIntrinsicKind K)25503312863SZachary Turner Demangler::demangleSpecialTableSymbolNode(StringView &MangledName,
25603312863SZachary Turner                                           SpecialIntrinsicKind K) {
25703312863SZachary Turner   NamedIdentifierNode *NI = Arena.alloc<NamedIdentifierNode>();
25803312863SZachary Turner   switch (K) {
25903312863SZachary Turner   case SpecialIntrinsicKind::Vftable:
26003312863SZachary Turner     NI->Name = "`vftable'";
261469f0763SZachary Turner     break;
26203312863SZachary Turner   case SpecialIntrinsicKind::Vbtable:
26303312863SZachary Turner     NI->Name = "`vbtable'";
26466555a7bSZachary Turner     break;
26503312863SZachary Turner   case SpecialIntrinsicKind::LocalVftable:
26603312863SZachary Turner     NI->Name = "`local vftable'";
26766555a7bSZachary Turner     break;
26803312863SZachary Turner   case SpecialIntrinsicKind::RttiCompleteObjLocator:
26903312863SZachary Turner     NI->Name = "`RTTI Complete Object Locator'";
270469f0763SZachary Turner     break;
271469f0763SZachary Turner   default:
2725094e5efSErik Pilkington     DEMANGLE_UNREACHABLE;
273469f0763SZachary Turner   }
27403312863SZachary Turner   QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
27503312863SZachary Turner   SpecialTableSymbolNode *STSN = Arena.alloc<SpecialTableSymbolNode>();
27603312863SZachary Turner   STSN->Name = QN;
27703312863SZachary Turner   bool IsMember = false;
278ae050d21SNico Weber   if (MangledName.empty()) {
279ae050d21SNico Weber     Error = true;
280ae050d21SNico Weber     return nullptr;
281ae050d21SNico Weber   }
28203312863SZachary Turner   char Front = MangledName.popFront();
28303312863SZachary Turner   if (Front != '6' && Front != '7') {
28403312863SZachary Turner     Error = true;
28503312863SZachary Turner     return nullptr;
28603312863SZachary Turner   }
28703312863SZachary Turner 
28803312863SZachary Turner   std::tie(STSN->Quals, IsMember) = demangleQualifiers(MangledName);
28903312863SZachary Turner   if (!MangledName.consumeFront('@'))
29003312863SZachary Turner     STSN->TargetName = demangleFullyQualifiedTypeName(MangledName);
29103312863SZachary Turner   return STSN;
29203312863SZachary Turner }
29303312863SZachary Turner 
29403312863SZachary Turner LocalStaticGuardVariableNode *
demangleLocalStaticGuard(StringView & MangledName,bool IsThread)29588ab281bSNico Weber Demangler::demangleLocalStaticGuard(StringView &MangledName, bool IsThread) {
29603312863SZachary Turner   LocalStaticGuardIdentifierNode *LSGI =
29703312863SZachary Turner       Arena.alloc<LocalStaticGuardIdentifierNode>();
29888ab281bSNico Weber   LSGI->IsThread = IsThread;
29903312863SZachary Turner   QualifiedNameNode *QN = demangleNameScopeChain(MangledName, LSGI);
30003312863SZachary Turner   LocalStaticGuardVariableNode *LSGVN =
30103312863SZachary Turner       Arena.alloc<LocalStaticGuardVariableNode>();
30203312863SZachary Turner   LSGVN->Name = QN;
30303312863SZachary Turner 
30403312863SZachary Turner   if (MangledName.consumeFront("4IA"))
30503312863SZachary Turner     LSGVN->IsVisible = false;
30603312863SZachary Turner   else if (MangledName.consumeFront("5"))
30703312863SZachary Turner     LSGVN->IsVisible = true;
30803312863SZachary Turner   else {
30903312863SZachary Turner     Error = true;
31003312863SZachary Turner     return nullptr;
31103312863SZachary Turner   }
31203312863SZachary Turner 
31303312863SZachary Turner   if (!MangledName.empty())
31403312863SZachary Turner     LSGI->ScopeIndex = demangleUnsigned(MangledName);
31503312863SZachary Turner   return LSGVN;
31603312863SZachary Turner }
31703312863SZachary Turner 
synthesizeNamedIdentifier(ArenaAllocator & Arena,StringView Name)31803312863SZachary Turner static NamedIdentifierNode *synthesizeNamedIdentifier(ArenaAllocator &Arena,
31903312863SZachary Turner                                                       StringView Name) {
32003312863SZachary Turner   NamedIdentifierNode *Id = Arena.alloc<NamedIdentifierNode>();
32103312863SZachary Turner   Id->Name = Name;
32203312863SZachary Turner   return Id;
32303312863SZachary Turner }
32403312863SZachary Turner 
synthesizeQualifiedName(ArenaAllocator & Arena,IdentifierNode * Identifier)32503312863SZachary Turner static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena,
32603312863SZachary Turner                                                   IdentifierNode *Identifier) {
32703312863SZachary Turner   QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>();
32803312863SZachary Turner   QN->Components = Arena.alloc<NodeArrayNode>();
32903312863SZachary Turner   QN->Components->Count = 1;
33003312863SZachary Turner   QN->Components->Nodes = Arena.allocArray<Node *>(1);
33103312863SZachary Turner   QN->Components->Nodes[0] = Identifier;
33203312863SZachary Turner   return QN;
33303312863SZachary Turner }
33403312863SZachary Turner 
synthesizeQualifiedName(ArenaAllocator & Arena,StringView Name)33503312863SZachary Turner static QualifiedNameNode *synthesizeQualifiedName(ArenaAllocator &Arena,
33603312863SZachary Turner                                                   StringView Name) {
33703312863SZachary Turner   NamedIdentifierNode *Id = synthesizeNamedIdentifier(Arena, Name);
33803312863SZachary Turner   return synthesizeQualifiedName(Arena, Id);
33903312863SZachary Turner }
34003312863SZachary Turner 
synthesizeVariable(ArenaAllocator & Arena,TypeNode * Type,StringView VariableName)34103312863SZachary Turner static VariableSymbolNode *synthesizeVariable(ArenaAllocator &Arena,
34203312863SZachary Turner                                               TypeNode *Type,
34303312863SZachary Turner                                               StringView VariableName) {
34403312863SZachary Turner   VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
34503312863SZachary Turner   VSN->Type = Type;
34603312863SZachary Turner   VSN->Name = synthesizeQualifiedName(Arena, VariableName);
34703312863SZachary Turner   return VSN;
34803312863SZachary Turner }
34903312863SZachary Turner 
demangleUntypedVariable(ArenaAllocator & Arena,StringView & MangledName,StringView VariableName)35003312863SZachary Turner VariableSymbolNode *Demangler::demangleUntypedVariable(
35103312863SZachary Turner     ArenaAllocator &Arena, StringView &MangledName, StringView VariableName) {
35203312863SZachary Turner   NamedIdentifierNode *NI = synthesizeNamedIdentifier(Arena, VariableName);
35303312863SZachary Turner   QualifiedNameNode *QN = demangleNameScopeChain(MangledName, NI);
35403312863SZachary Turner   VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
35503312863SZachary Turner   VSN->Name = QN;
35603312863SZachary Turner   if (MangledName.consumeFront("8"))
35703312863SZachary Turner     return VSN;
35803312863SZachary Turner 
35903312863SZachary Turner   Error = true;
36003312863SZachary Turner   return nullptr;
36103312863SZachary Turner }
36203312863SZachary Turner 
36303312863SZachary Turner VariableSymbolNode *
demangleRttiBaseClassDescriptorNode(ArenaAllocator & Arena,StringView & MangledName)36403312863SZachary Turner Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator &Arena,
36503312863SZachary Turner                                                StringView &MangledName) {
36603312863SZachary Turner   RttiBaseClassDescriptorNode *RBCDN =
36703312863SZachary Turner       Arena.alloc<RttiBaseClassDescriptorNode>();
36803312863SZachary Turner   RBCDN->NVOffset = demangleUnsigned(MangledName);
36903312863SZachary Turner   RBCDN->VBPtrOffset = demangleSigned(MangledName);
37003312863SZachary Turner   RBCDN->VBTableOffset = demangleUnsigned(MangledName);
37103312863SZachary Turner   RBCDN->Flags = demangleUnsigned(MangledName);
37203312863SZachary Turner   if (Error)
37303312863SZachary Turner     return nullptr;
37403312863SZachary Turner 
37503312863SZachary Turner   VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
37603312863SZachary Turner   VSN->Name = demangleNameScopeChain(MangledName, RBCDN);
37703312863SZachary Turner   MangledName.consumeFront('8');
37803312863SZachary Turner   return VSN;
37903312863SZachary Turner }
38003312863SZachary Turner 
demangleInitFiniStub(StringView & MangledName,bool IsDestructor)38132a8a202SZachary Turner FunctionSymbolNode *Demangler::demangleInitFiniStub(StringView &MangledName,
38203312863SZachary Turner                                                     bool IsDestructor) {
38303312863SZachary Turner   DynamicStructorIdentifierNode *DSIN =
38403312863SZachary Turner       Arena.alloc<DynamicStructorIdentifierNode>();
38503312863SZachary Turner   DSIN->IsDestructor = IsDestructor;
38632a8a202SZachary Turner 
38778ab3cb2SZachary Turner   bool IsKnownStaticDataMember = false;
38878ab3cb2SZachary Turner   if (MangledName.consumeFront('?'))
38978ab3cb2SZachary Turner     IsKnownStaticDataMember = true;
39078ab3cb2SZachary Turner 
39163b97d2aSNico Weber   SymbolNode *Symbol = demangleDeclarator(MangledName);
39263b97d2aSNico Weber   if (Error)
39363b97d2aSNico Weber     return nullptr;
39432a8a202SZachary Turner 
39532a8a202SZachary Turner   FunctionSymbolNode *FSN = nullptr;
39632a8a202SZachary Turner 
39732a8a202SZachary Turner   if (Symbol->kind() == NodeKind::VariableSymbol) {
39832a8a202SZachary Turner     DSIN->Variable = static_cast<VariableSymbolNode *>(Symbol);
39978ab3cb2SZachary Turner 
40078ab3cb2SZachary Turner     // Older versions of clang mangled this type of symbol incorrectly.  They
40178ab3cb2SZachary Turner     // would omit the leading ? and they would only emit a single @ at the end.
40278ab3cb2SZachary Turner     // The correct mangling is a leading ? and 2 trailing @ signs.  Handle
40378ab3cb2SZachary Turner     // both cases.
40478ab3cb2SZachary Turner     int AtCount = IsKnownStaticDataMember ? 2 : 1;
40578ab3cb2SZachary Turner     for (int I = 0; I < AtCount; ++I) {
40678ab3cb2SZachary Turner       if (MangledName.consumeFront('@'))
40778ab3cb2SZachary Turner         continue;
40832a8a202SZachary Turner       Error = true;
40932a8a202SZachary Turner       return nullptr;
41032a8a202SZachary Turner     }
41132a8a202SZachary Turner 
41232a8a202SZachary Turner     FSN = demangleFunctionEncoding(MangledName);
41363b97d2aSNico Weber     if (FSN)
41432a8a202SZachary Turner       FSN->Name = synthesizeQualifiedName(Arena, DSIN);
41532a8a202SZachary Turner   } else {
41678ab3cb2SZachary Turner     if (IsKnownStaticDataMember) {
41778ab3cb2SZachary Turner       // This was supposed to be a static data member, but we got a function.
41878ab3cb2SZachary Turner       Error = true;
41978ab3cb2SZachary Turner       return nullptr;
42078ab3cb2SZachary Turner     }
42178ab3cb2SZachary Turner 
42232a8a202SZachary Turner     FSN = static_cast<FunctionSymbolNode *>(Symbol);
42332a8a202SZachary Turner     DSIN->Name = Symbol->Name;
42432a8a202SZachary Turner     FSN->Name = synthesizeQualifiedName(Arena, DSIN);
42532a8a202SZachary Turner   }
42632a8a202SZachary Turner 
42703312863SZachary Turner   return FSN;
42803312863SZachary Turner }
42903312863SZachary Turner 
demangleSpecialIntrinsic(StringView & MangledName)43003312863SZachary Turner SymbolNode *Demangler::demangleSpecialIntrinsic(StringView &MangledName) {
43103312863SZachary Turner   SpecialIntrinsicKind SIK = consumeSpecialIntrinsicKind(MangledName);
43203312863SZachary Turner 
43303312863SZachary Turner   switch (SIK) {
434d98a0a36SNico Weber   case SpecialIntrinsicKind::None:
435d98a0a36SNico Weber     return nullptr;
43603312863SZachary Turner   case SpecialIntrinsicKind::StringLiteralSymbol:
43703312863SZachary Turner     return demangleStringLiteral(MangledName);
43803312863SZachary Turner   case SpecialIntrinsicKind::Vftable:
43903312863SZachary Turner   case SpecialIntrinsicKind::Vbtable:
44003312863SZachary Turner   case SpecialIntrinsicKind::LocalVftable:
44103312863SZachary Turner   case SpecialIntrinsicKind::RttiCompleteObjLocator:
44203312863SZachary Turner     return demangleSpecialTableSymbolNode(MangledName, SIK);
44303312863SZachary Turner   case SpecialIntrinsicKind::VcallThunk:
44403312863SZachary Turner     return demangleVcallThunkNode(MangledName);
44503312863SZachary Turner   case SpecialIntrinsicKind::LocalStaticGuard:
44688ab281bSNico Weber     return demangleLocalStaticGuard(MangledName, /*IsThread=*/false);
44788ab281bSNico Weber   case SpecialIntrinsicKind::LocalStaticThreadGuard:
44888ab281bSNico Weber     return demangleLocalStaticGuard(MangledName, /*IsThread=*/true);
44903312863SZachary Turner   case SpecialIntrinsicKind::RttiTypeDescriptor: {
45003312863SZachary Turner     TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result);
451469f0763SZachary Turner     if (Error)
452469f0763SZachary Turner       break;
453469f0763SZachary Turner     if (!MangledName.consumeFront("@8"))
45403312863SZachary Turner       break;
455469f0763SZachary Turner     if (!MangledName.empty())
456469f0763SZachary Turner       break;
45703312863SZachary Turner     return synthesizeVariable(Arena, T, "`RTTI Type Descriptor'");
45803312863SZachary Turner   }
45903312863SZachary Turner   case SpecialIntrinsicKind::RttiBaseClassArray:
46003312863SZachary Turner     return demangleUntypedVariable(Arena, MangledName,
46103312863SZachary Turner                                    "`RTTI Base Class Array'");
46203312863SZachary Turner   case SpecialIntrinsicKind::RttiClassHierarchyDescriptor:
46303312863SZachary Turner     return demangleUntypedVariable(Arena, MangledName,
46403312863SZachary Turner                                    "`RTTI Class Hierarchy Descriptor'");
46503312863SZachary Turner   case SpecialIntrinsicKind::RttiBaseClassDescriptor:
46603312863SZachary Turner     return demangleRttiBaseClassDescriptorNode(Arena, MangledName);
46703312863SZachary Turner   case SpecialIntrinsicKind::DynamicInitializer:
468878df1c2SNico Weber     return demangleInitFiniStub(MangledName, /*IsDestructor=*/false);
46903312863SZachary Turner   case SpecialIntrinsicKind::DynamicAtexitDestructor:
470878df1c2SNico Weber     return demangleInitFiniStub(MangledName, /*IsDestructor=*/true);
471d98a0a36SNico Weber   case SpecialIntrinsicKind::Typeof:
472d98a0a36SNico Weber   case SpecialIntrinsicKind::UdtReturning:
473d98a0a36SNico Weber     // It's unclear which tools produces these manglings, so demangling
474d98a0a36SNico Weber     // support is not (yet?) implemented.
475469f0763SZachary Turner     break;
476d98a0a36SNico Weber   case SpecialIntrinsicKind::Unknown:
477d98a0a36SNico Weber     DEMANGLE_UNREACHABLE; // Never returned by consumeSpecialIntrinsicKind.
478469f0763SZachary Turner   }
47903312863SZachary Turner   Error = true;
48003312863SZachary Turner   return nullptr;
481469f0763SZachary Turner }
482469f0763SZachary Turner 
48303312863SZachary Turner IdentifierNode *
demangleFunctionIdentifierCode(StringView & MangledName)48403312863SZachary Turner Demangler::demangleFunctionIdentifierCode(StringView &MangledName) {
48503312863SZachary Turner   assert(MangledName.startsWith('?'));
48603312863SZachary Turner   MangledName = MangledName.dropFront();
487321de48aSNico Weber   if (MangledName.empty()) {
488321de48aSNico Weber     Error = true;
489321de48aSNico Weber     return nullptr;
490321de48aSNico Weber   }
49103312863SZachary Turner 
49203312863SZachary Turner   if (MangledName.consumeFront("__"))
49303312863SZachary Turner     return demangleFunctionIdentifierCode(
49403312863SZachary Turner         MangledName, FunctionIdentifierCodeGroup::DoubleUnder);
495b4f33bbbSNico Weber   if (MangledName.consumeFront("_"))
49603312863SZachary Turner     return demangleFunctionIdentifierCode(MangledName,
49703312863SZachary Turner                                           FunctionIdentifierCodeGroup::Under);
49803312863SZachary Turner   return demangleFunctionIdentifierCode(MangledName,
49903312863SZachary Turner                                         FunctionIdentifierCodeGroup::Basic);
50003312863SZachary Turner }
50103312863SZachary Turner 
50203312863SZachary Turner StructorIdentifierNode *
demangleStructorIdentifier(StringView & MangledName,bool IsDestructor)50303312863SZachary Turner Demangler::demangleStructorIdentifier(StringView &MangledName,
50403312863SZachary Turner                                       bool IsDestructor) {
50503312863SZachary Turner   StructorIdentifierNode *N = Arena.alloc<StructorIdentifierNode>();
50603312863SZachary Turner   N->IsDestructor = IsDestructor;
50703312863SZachary Turner   return N;
50803312863SZachary Turner }
50903312863SZachary Turner 
51003312863SZachary Turner ConversionOperatorIdentifierNode *
demangleConversionOperatorIdentifier(StringView & MangledName)51103312863SZachary Turner Demangler::demangleConversionOperatorIdentifier(StringView &MangledName) {
51203312863SZachary Turner   ConversionOperatorIdentifierNode *N =
51303312863SZachary Turner       Arena.alloc<ConversionOperatorIdentifierNode>();
51403312863SZachary Turner   return N;
51503312863SZachary Turner }
51603312863SZachary Turner 
51703312863SZachary Turner LiteralOperatorIdentifierNode *
demangleLiteralOperatorIdentifier(StringView & MangledName)51803312863SZachary Turner Demangler::demangleLiteralOperatorIdentifier(StringView &MangledName) {
51903312863SZachary Turner   LiteralOperatorIdentifierNode *N =
52003312863SZachary Turner       Arena.alloc<LiteralOperatorIdentifierNode>();
521af2ee7d0SNico Weber   N->Name = demangleSimpleString(MangledName, /*Memorize=*/false);
52203312863SZachary Turner   return N;
52303312863SZachary Turner }
52403312863SZachary Turner 
52503db625cSNico Weber IntrinsicFunctionKind
translateIntrinsicFunctionCode(char CH,FunctionIdentifierCodeGroup Group)52603db625cSNico Weber Demangler::translateIntrinsicFunctionCode(char CH,
52703db625cSNico Weber                                           FunctionIdentifierCodeGroup Group) {
52803db625cSNico Weber   using IFK = IntrinsicFunctionKind;
52903db625cSNico Weber   if (!(CH >= '0' && CH <= '9') && !(CH >= 'A' && CH <= 'Z')) {
53003db625cSNico Weber     Error = true;
53103db625cSNico Weber     return IFK::None;
53203db625cSNico Weber   }
53303db625cSNico Weber 
53403312863SZachary Turner   // Not all ? identifiers are intrinsics *functions*.  This function only maps
53503312863SZachary Turner   // operator codes for the special functions, all others are handled elsewhere,
53603312863SZachary Turner   // hence the IFK::None entries in the table.
53703312863SZachary Turner   static IFK Basic[36] = {
53803312863SZachary Turner       IFK::None,             // ?0 # Foo::Foo()
53903312863SZachary Turner       IFK::None,             // ?1 # Foo::~Foo()
54003312863SZachary Turner       IFK::New,              // ?2 # operator new
54103312863SZachary Turner       IFK::Delete,           // ?3 # operator delete
54203312863SZachary Turner       IFK::Assign,           // ?4 # operator=
54303312863SZachary Turner       IFK::RightShift,       // ?5 # operator>>
54403312863SZachary Turner       IFK::LeftShift,        // ?6 # operator<<
54503312863SZachary Turner       IFK::LogicalNot,       // ?7 # operator!
54603312863SZachary Turner       IFK::Equals,           // ?8 # operator==
54703312863SZachary Turner       IFK::NotEquals,        // ?9 # operator!=
54803312863SZachary Turner       IFK::ArraySubscript,   // ?A # operator[]
54903312863SZachary Turner       IFK::None,             // ?B # Foo::operator <type>()
55003312863SZachary Turner       IFK::Pointer,          // ?C # operator->
55103312863SZachary Turner       IFK::Dereference,      // ?D # operator*
55203312863SZachary Turner       IFK::Increment,        // ?E # operator++
55303312863SZachary Turner       IFK::Decrement,        // ?F # operator--
55403312863SZachary Turner       IFK::Minus,            // ?G # operator-
55503312863SZachary Turner       IFK::Plus,             // ?H # operator+
55603312863SZachary Turner       IFK::BitwiseAnd,       // ?I # operator&
55703312863SZachary Turner       IFK::MemberPointer,    // ?J # operator->*
55803312863SZachary Turner       IFK::Divide,           // ?K # operator/
55903312863SZachary Turner       IFK::Modulus,          // ?L # operator%
56003312863SZachary Turner       IFK::LessThan,         // ?M operator<
56103312863SZachary Turner       IFK::LessThanEqual,    // ?N operator<=
56203312863SZachary Turner       IFK::GreaterThan,      // ?O operator>
56303312863SZachary Turner       IFK::GreaterThanEqual, // ?P operator>=
56403312863SZachary Turner       IFK::Comma,            // ?Q operator,
56503312863SZachary Turner       IFK::Parens,           // ?R operator()
56603312863SZachary Turner       IFK::BitwiseNot,       // ?S operator~
56703312863SZachary Turner       IFK::BitwiseXor,       // ?T operator^
56803312863SZachary Turner       IFK::BitwiseOr,        // ?U operator|
56903312863SZachary Turner       IFK::LogicalAnd,       // ?V operator&&
57003312863SZachary Turner       IFK::LogicalOr,        // ?W operator||
57103312863SZachary Turner       IFK::TimesEqual,       // ?X operator*=
57203312863SZachary Turner       IFK::PlusEqual,        // ?Y operator+=
57303312863SZachary Turner       IFK::MinusEqual,       // ?Z operator-=
57403312863SZachary Turner   };
57503312863SZachary Turner   static IFK Under[36] = {
57603312863SZachary Turner       IFK::DivEqual,           // ?_0 operator/=
57703312863SZachary Turner       IFK::ModEqual,           // ?_1 operator%=
57803312863SZachary Turner       IFK::RshEqual,           // ?_2 operator>>=
57903312863SZachary Turner       IFK::LshEqual,           // ?_3 operator<<=
58003312863SZachary Turner       IFK::BitwiseAndEqual,    // ?_4 operator&=
58103312863SZachary Turner       IFK::BitwiseOrEqual,     // ?_5 operator|=
58203312863SZachary Turner       IFK::BitwiseXorEqual,    // ?_6 operator^=
58303312863SZachary Turner       IFK::None,               // ?_7 # vftable
58403312863SZachary Turner       IFK::None,               // ?_8 # vbtable
58503312863SZachary Turner       IFK::None,               // ?_9 # vcall
58603312863SZachary Turner       IFK::None,               // ?_A # typeof
58703312863SZachary Turner       IFK::None,               // ?_B # local static guard
58803312863SZachary Turner       IFK::None,               // ?_C # string literal
58903312863SZachary Turner       IFK::VbaseDtor,          // ?_D # vbase destructor
59003312863SZachary Turner       IFK::VecDelDtor,         // ?_E # vector deleting destructor
59103312863SZachary Turner       IFK::DefaultCtorClosure, // ?_F # default constructor closure
59203312863SZachary Turner       IFK::ScalarDelDtor,      // ?_G # scalar deleting destructor
59303312863SZachary Turner       IFK::VecCtorIter,        // ?_H # vector constructor iterator
59403312863SZachary Turner       IFK::VecDtorIter,        // ?_I # vector destructor iterator
59503312863SZachary Turner       IFK::VecVbaseCtorIter,   // ?_J # vector vbase constructor iterator
59603312863SZachary Turner       IFK::VdispMap,           // ?_K # virtual displacement map
59703312863SZachary Turner       IFK::EHVecCtorIter,      // ?_L # eh vector constructor iterator
59803312863SZachary Turner       IFK::EHVecDtorIter,      // ?_M # eh vector destructor iterator
59903312863SZachary Turner       IFK::EHVecVbaseCtorIter, // ?_N # eh vector vbase constructor iterator
60003312863SZachary Turner       IFK::CopyCtorClosure,    // ?_O # copy constructor closure
60103312863SZachary Turner       IFK::None,               // ?_P<name> # udt returning <name>
60203312863SZachary Turner       IFK::None,               // ?_Q # <unknown>
60303312863SZachary Turner       IFK::None,               // ?_R0 - ?_R4 # RTTI Codes
60403312863SZachary Turner       IFK::None,               // ?_S # local vftable
60503312863SZachary Turner       IFK::LocalVftableCtorClosure, // ?_T # local vftable constructor closure
60603312863SZachary Turner       IFK::ArrayNew,                // ?_U operator new[]
60703312863SZachary Turner       IFK::ArrayDelete,             // ?_V operator delete[]
60803312863SZachary Turner       IFK::None,                    // ?_W <unused>
60903312863SZachary Turner       IFK::None,                    // ?_X <unused>
61003312863SZachary Turner       IFK::None,                    // ?_Y <unused>
61103312863SZachary Turner       IFK::None,                    // ?_Z <unused>
61203312863SZachary Turner   };
61303312863SZachary Turner   static IFK DoubleUnder[36] = {
61403312863SZachary Turner       IFK::None,                       // ?__0 <unused>
61503312863SZachary Turner       IFK::None,                       // ?__1 <unused>
61603312863SZachary Turner       IFK::None,                       // ?__2 <unused>
61703312863SZachary Turner       IFK::None,                       // ?__3 <unused>
61803312863SZachary Turner       IFK::None,                       // ?__4 <unused>
61903312863SZachary Turner       IFK::None,                       // ?__5 <unused>
62003312863SZachary Turner       IFK::None,                       // ?__6 <unused>
62103312863SZachary Turner       IFK::None,                       // ?__7 <unused>
62203312863SZachary Turner       IFK::None,                       // ?__8 <unused>
62303312863SZachary Turner       IFK::None,                       // ?__9 <unused>
62403312863SZachary Turner       IFK::ManVectorCtorIter,          // ?__A managed vector ctor iterator
62503312863SZachary Turner       IFK::ManVectorDtorIter,          // ?__B managed vector dtor iterator
62603312863SZachary Turner       IFK::EHVectorCopyCtorIter,       // ?__C EH vector copy ctor iterator
62703312863SZachary Turner       IFK::EHVectorVbaseCopyCtorIter,  // ?__D EH vector vbase copy ctor iter
62803312863SZachary Turner       IFK::None,                       // ?__E dynamic initializer for `T'
62903312863SZachary Turner       IFK::None,                       // ?__F dynamic atexit destructor for `T'
63003312863SZachary Turner       IFK::VectorCopyCtorIter,         // ?__G vector copy constructor iter
63103312863SZachary Turner       IFK::VectorVbaseCopyCtorIter,    // ?__H vector vbase copy ctor iter
63203312863SZachary Turner       IFK::ManVectorVbaseCopyCtorIter, // ?__I managed vector vbase copy ctor
63303312863SZachary Turner                                        // iter
63403312863SZachary Turner       IFK::None,                       // ?__J local static thread guard
63503312863SZachary Turner       IFK::None,                       // ?__K operator ""_name
636e8f21b1aSNico Weber       IFK::CoAwait,                    // ?__L operator co_await
637e8f21b1aSNico Weber       IFK::Spaceship,                  // ?__M operator<=>
63803312863SZachary Turner       IFK::None,                       // ?__N <unused>
63903312863SZachary Turner       IFK::None,                       // ?__O <unused>
64003312863SZachary Turner       IFK::None,                       // ?__P <unused>
64103312863SZachary Turner       IFK::None,                       // ?__Q <unused>
64203312863SZachary Turner       IFK::None,                       // ?__R <unused>
64303312863SZachary Turner       IFK::None,                       // ?__S <unused>
64403312863SZachary Turner       IFK::None,                       // ?__T <unused>
64503312863SZachary Turner       IFK::None,                       // ?__U <unused>
64603312863SZachary Turner       IFK::None,                       // ?__V <unused>
64703312863SZachary Turner       IFK::None,                       // ?__W <unused>
64803312863SZachary Turner       IFK::None,                       // ?__X <unused>
64903312863SZachary Turner       IFK::None,                       // ?__Y <unused>
65003312863SZachary Turner       IFK::None,                       // ?__Z <unused>
65103312863SZachary Turner   };
65203312863SZachary Turner 
65303312863SZachary Turner   int Index = (CH >= '0' && CH <= '9') ? (CH - '0') : (CH - 'A' + 10);
65403312863SZachary Turner   switch (Group) {
65503312863SZachary Turner   case FunctionIdentifierCodeGroup::Basic:
65603312863SZachary Turner     return Basic[Index];
65703312863SZachary Turner   case FunctionIdentifierCodeGroup::Under:
65803312863SZachary Turner     return Under[Index];
65903312863SZachary Turner   case FunctionIdentifierCodeGroup::DoubleUnder:
66003312863SZachary Turner     return DoubleUnder[Index];
66103312863SZachary Turner   }
6625094e5efSErik Pilkington   DEMANGLE_UNREACHABLE;
66303312863SZachary Turner }
66403312863SZachary Turner 
66503312863SZachary Turner IdentifierNode *
demangleFunctionIdentifierCode(StringView & MangledName,FunctionIdentifierCodeGroup Group)66603312863SZachary Turner Demangler::demangleFunctionIdentifierCode(StringView &MangledName,
66703312863SZachary Turner                                           FunctionIdentifierCodeGroup Group) {
66863fe2593SNico Weber   if (MangledName.empty()) {
66963fe2593SNico Weber     Error = true;
67063fe2593SNico Weber     return nullptr;
67163fe2593SNico Weber   }
67203312863SZachary Turner   switch (Group) {
67303312863SZachary Turner   case FunctionIdentifierCodeGroup::Basic:
67403312863SZachary Turner     switch (char CH = MangledName.popFront()) {
67503312863SZachary Turner     case '0':
67603312863SZachary Turner     case '1':
67703312863SZachary Turner       return demangleStructorIdentifier(MangledName, CH == '1');
67803312863SZachary Turner     case 'B':
67903312863SZachary Turner       return demangleConversionOperatorIdentifier(MangledName);
68003312863SZachary Turner     default:
68103312863SZachary Turner       return Arena.alloc<IntrinsicFunctionIdentifierNode>(
68203312863SZachary Turner           translateIntrinsicFunctionCode(CH, Group));
68303312863SZachary Turner     }
68403312863SZachary Turner   case FunctionIdentifierCodeGroup::Under:
68503312863SZachary Turner     return Arena.alloc<IntrinsicFunctionIdentifierNode>(
68603312863SZachary Turner         translateIntrinsicFunctionCode(MangledName.popFront(), Group));
68703312863SZachary Turner   case FunctionIdentifierCodeGroup::DoubleUnder:
68803312863SZachary Turner     switch (char CH = MangledName.popFront()) {
68903312863SZachary Turner     case 'K':
69003312863SZachary Turner       return demangleLiteralOperatorIdentifier(MangledName);
69103312863SZachary Turner     default:
69203312863SZachary Turner       return Arena.alloc<IntrinsicFunctionIdentifierNode>(
69303312863SZachary Turner           translateIntrinsicFunctionCode(CH, Group));
69403312863SZachary Turner     }
69503312863SZachary Turner   }
69603312863SZachary Turner 
697ef035186SNico Weber   DEMANGLE_UNREACHABLE;
69803312863SZachary Turner }
69903312863SZachary Turner 
demangleEncodedSymbol(StringView & MangledName,QualifiedNameNode * Name)70003312863SZachary Turner SymbolNode *Demangler::demangleEncodedSymbol(StringView &MangledName,
70103312863SZachary Turner                                              QualifiedNameNode *Name) {
70263b97d2aSNico Weber   if (MangledName.empty()) {
70363b97d2aSNico Weber     Error = true;
70463b97d2aSNico Weber     return nullptr;
70563b97d2aSNico Weber   }
70663b97d2aSNico Weber 
707469f0763SZachary Turner   // Read a variable.
708469f0763SZachary Turner   switch (MangledName.front()) {
709469f0763SZachary Turner   case '0':
710469f0763SZachary Turner   case '1':
711469f0763SZachary Turner   case '2':
712469f0763SZachary Turner   case '3':
71303312863SZachary Turner   case '4': {
71403312863SZachary Turner     StorageClass SC = demangleVariableStorageClass(MangledName);
71503312863SZachary Turner     return demangleVariableEncoding(MangledName, SC);
716469f0763SZachary Turner   }
71703312863SZachary Turner   }
71803312863SZachary Turner   FunctionSymbolNode *FSN = demangleFunctionEncoding(MangledName);
71903312863SZachary Turner 
72003312863SZachary Turner   IdentifierNode *UQN = Name->getUnqualifiedIdentifier();
72103312863SZachary Turner   if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
72203312863SZachary Turner     ConversionOperatorIdentifierNode *COIN =
72303312863SZachary Turner         static_cast<ConversionOperatorIdentifierNode *>(UQN);
72463b97d2aSNico Weber     if (FSN)
72503312863SZachary Turner       COIN->TargetType = FSN->Signature->ReturnType;
72603312863SZachary Turner   }
72703312863SZachary Turner   return FSN;
728469f0763SZachary Turner }
729469f0763SZachary Turner 
demangleDeclarator(StringView & MangledName)73063b97d2aSNico Weber SymbolNode *Demangler::demangleDeclarator(StringView &MangledName) {
73163b97d2aSNico Weber   // What follows is a main symbol name. This may include namespaces or class
73263b97d2aSNico Weber   // back references.
73363b97d2aSNico Weber   QualifiedNameNode *QN = demangleFullyQualifiedSymbolName(MangledName);
73463b97d2aSNico Weber   if (Error)
73563b97d2aSNico Weber     return nullptr;
73663b97d2aSNico Weber 
73763b97d2aSNico Weber   SymbolNode *Symbol = demangleEncodedSymbol(MangledName, QN);
73863b97d2aSNico Weber   if (Error)
73963b97d2aSNico Weber     return nullptr;
74063b97d2aSNico Weber   Symbol->Name = QN;
74163b97d2aSNico Weber 
74263b97d2aSNico Weber   IdentifierNode *UQN = QN->getUnqualifiedIdentifier();
74363b97d2aSNico Weber   if (UQN->kind() == NodeKind::ConversionOperatorIdentifier) {
74463b97d2aSNico Weber     ConversionOperatorIdentifierNode *COIN =
74563b97d2aSNico Weber         static_cast<ConversionOperatorIdentifierNode *>(UQN);
74663b97d2aSNico Weber     if (!COIN->TargetType) {
74763b97d2aSNico Weber       Error = true;
74863b97d2aSNico Weber       return nullptr;
74963b97d2aSNico Weber     }
75063b97d2aSNico Weber   }
75163b97d2aSNico Weber   return Symbol;
75263b97d2aSNico Weber }
75363b97d2aSNico Weber 
demangleMD5Name(StringView & MangledName)75482dc06c3SNico Weber SymbolNode *Demangler::demangleMD5Name(StringView &MangledName) {
75582dc06c3SNico Weber   assert(MangledName.startsWith("??@"));
75603312863SZachary Turner   // This is an MD5 mangled name.  We can't demangle it, just return the
75703312863SZachary Turner   // mangled name.
758cfe08bc7SNico Weber   // An MD5 mangled name is ??@ followed by 32 characters and a terminating @.
759cfe08bc7SNico Weber   size_t MD5Last = MangledName.find('@', strlen("??@"));
760cfe08bc7SNico Weber   if (MD5Last == StringView::npos) {
761cfe08bc7SNico Weber     Error = true;
762cfe08bc7SNico Weber     return nullptr;
763cfe08bc7SNico Weber   }
764cfe08bc7SNico Weber   const char *Start = MangledName.begin();
765cfe08bc7SNico Weber   MangledName = MangledName.dropFront(MD5Last + 1);
766cfe08bc7SNico Weber 
767cfe08bc7SNico Weber   // There are two additional special cases for MD5 names:
768cfe08bc7SNico Weber   // 1. For complete object locators where the object name is long enough
769cfe08bc7SNico Weber   //    for the object to have an MD5 name, the complete object locator is
770cfe08bc7SNico Weber   //    called ??@...@??_R4@ (with a trailing "??_R4@" instead of the usual
771cfe08bc7SNico Weber   //    leading "??_R4". This is handled here.
772cfe08bc7SNico Weber   // 2. For catchable types, in versions of MSVC before 2015 (<1900) or after
773cfe08bc7SNico Weber   //    2017.2 (>= 1914), the catchable type mangling is _CT??@...@??@...@8
774cfe08bc7SNico Weber   //    instead of_CT??@...@8 with just one MD5 name. Since we don't yet
775cfe08bc7SNico Weber   //    demangle catchable types anywhere, this isn't handled for MD5 names
776cfe08bc7SNico Weber   //    either.
777cfe08bc7SNico Weber   MangledName.consumeFront("??_R4@");
778cfe08bc7SNico Weber 
779cfe08bc7SNico Weber   StringView MD5(Start, MangledName.begin());
78003312863SZachary Turner   SymbolNode *S = Arena.alloc<SymbolNode>(NodeKind::Md5Symbol);
781cfe08bc7SNico Weber   S->Name = synthesizeQualifiedName(Arena, MD5);
782cfe08bc7SNico Weber 
78383313f8fSZachary Turner   return S;
78483313f8fSZachary Turner }
78583313f8fSZachary Turner 
demangleTypeinfoName(StringView & MangledName)786da298aa9SNico Weber SymbolNode *Demangler::demangleTypeinfoName(StringView &MangledName) {
787da298aa9SNico Weber   assert(MangledName.startsWith('.'));
788da298aa9SNico Weber   MangledName.consumeFront('.');
789da298aa9SNico Weber 
790da298aa9SNico Weber   TypeNode *T = demangleType(MangledName, QualifierMangleMode::Result);
791da298aa9SNico Weber   if (Error || !MangledName.empty()) {
792da298aa9SNico Weber     Error = true;
793da298aa9SNico Weber     return nullptr;
794da298aa9SNico Weber   }
795da298aa9SNico Weber   return synthesizeVariable(Arena, T, "`RTTI Type Descriptor Name'");
796da298aa9SNico Weber }
797da298aa9SNico Weber 
79882dc06c3SNico Weber // Parser entry point.
parse(StringView & MangledName)79982dc06c3SNico Weber SymbolNode *Demangler::parse(StringView &MangledName) {
800da298aa9SNico Weber   // Typeinfo names are strings stored in RTTI data. They're not symbol names.
801da298aa9SNico Weber   // It's still useful to demangle them. They're the only demangled entity
802da298aa9SNico Weber   // that doesn't start with a "?" but a ".".
803da298aa9SNico Weber   if (MangledName.startsWith('.'))
804da298aa9SNico Weber     return demangleTypeinfoName(MangledName);
805da298aa9SNico Weber 
80682dc06c3SNico Weber   if (MangledName.startsWith("??@"))
80782dc06c3SNico Weber     return demangleMD5Name(MangledName);
80882dc06c3SNico Weber 
809cfe08bc7SNico Weber   // MSVC-style mangled symbols must start with '?'.
81003312863SZachary Turner   if (!MangledName.startsWith('?')) {
81103312863SZachary Turner     Error = true;
81203312863SZachary Turner     return nullptr;
81303312863SZachary Turner   }
81403312863SZachary Turner 
815469f0763SZachary Turner   MangledName.consumeFront('?');
816970fdc32SZachary Turner 
817469f0763SZachary Turner   // ?$ is a template instantiation, but all other names that start with ? are
818469f0763SZachary Turner   // operators / special names.
81903312863SZachary Turner   if (SymbolNode *SI = demangleSpecialIntrinsic(MangledName))
82003312863SZachary Turner     return SI;
821469f0763SZachary Turner 
82263b97d2aSNico Weber   return demangleDeclarator(MangledName);
823f435a7eaSZachary Turner }
824f435a7eaSZachary Turner 
parseTagUniqueName(StringView & MangledName)8257ba90563SZachary Turner TagTypeNode *Demangler::parseTagUniqueName(StringView &MangledName) {
826*bf1e96d6SZequan Wu   if (!MangledName.consumeFront(".?A")) {
827*bf1e96d6SZequan Wu     Error = true;
8287ba90563SZachary Turner     return nullptr;
829*bf1e96d6SZequan Wu   }
8307ba90563SZachary Turner   MangledName.consumeFront(".?A");
831*bf1e96d6SZequan Wu   if (MangledName.empty()) {
832*bf1e96d6SZequan Wu     Error = true;
8337ba90563SZachary Turner     return nullptr;
834*bf1e96d6SZequan Wu   }
8357ba90563SZachary Turner 
8367ba90563SZachary Turner   return demangleClassType(MangledName);
8377ba90563SZachary Turner }
8387ba90563SZachary Turner 
839f435a7eaSZachary Turner // <type-encoding> ::= <storage-class> <variable-type>
840f435a7eaSZachary Turner // <storage-class> ::= 0  # private static member
841f435a7eaSZachary Turner //                 ::= 1  # protected static member
842f435a7eaSZachary Turner //                 ::= 2  # public static member
843f435a7eaSZachary Turner //                 ::= 3  # global
844f435a7eaSZachary Turner //                 ::= 4  # static local
845f435a7eaSZachary Turner 
demangleVariableEncoding(StringView & MangledName,StorageClass SC)84603312863SZachary Turner VariableSymbolNode *Demangler::demangleVariableEncoding(StringView &MangledName,
847469f0763SZachary Turner                                                         StorageClass SC) {
84803312863SZachary Turner   VariableSymbolNode *VSN = Arena.alloc<VariableSymbolNode>();
849f435a7eaSZachary Turner 
85003312863SZachary Turner   VSN->Type = demangleType(MangledName, QualifierMangleMode::Drop);
85103312863SZachary Turner   VSN->SC = SC;
852f435a7eaSZachary Turner 
85363b97d2aSNico Weber   if (Error)
85463b97d2aSNico Weber     return nullptr;
85563b97d2aSNico Weber 
856f435a7eaSZachary Turner   // <variable-type> ::= <type> <cvr-qualifiers>
857f435a7eaSZachary Turner   //                 ::= <type> <pointee-cvr-qualifiers> # pointers, references
85803312863SZachary Turner   switch (VSN->Type->kind()) {
85903312863SZachary Turner   case NodeKind::PointerType: {
86003312863SZachary Turner     PointerTypeNode *PTN = static_cast<PointerTypeNode *>(VSN->Type);
86103312863SZachary Turner 
862f435a7eaSZachary Turner     Qualifiers ExtraChildQuals = Q_None;
86303312863SZachary Turner     PTN->Quals = Qualifiers(VSN->Type->Quals |
86403312863SZachary Turner                             demanglePointerExtQualifiers(MangledName));
865f435a7eaSZachary Turner 
866d742d645SZachary Turner     bool IsMember = false;
867316109b5SZachary Turner     std::tie(ExtraChildQuals, IsMember) = demangleQualifiers(MangledName);
868f435a7eaSZachary Turner 
86903312863SZachary Turner     if (PTN->ClassParent) {
87003312863SZachary Turner       QualifiedNameNode *BackRefName =
87103312863SZachary Turner           demangleFullyQualifiedTypeName(MangledName);
872f435a7eaSZachary Turner       (void)BackRefName;
873f435a7eaSZachary Turner     }
87403312863SZachary Turner     PTN->Pointee->Quals = Qualifiers(PTN->Pointee->Quals | ExtraChildQuals);
875f435a7eaSZachary Turner 
876f435a7eaSZachary Turner     break;
877f435a7eaSZachary Turner   }
878f435a7eaSZachary Turner   default:
87903312863SZachary Turner     VSN->Type->Quals = demangleQualifiers(MangledName).first;
880f435a7eaSZachary Turner     break;
881f435a7eaSZachary Turner   }
882f435a7eaSZachary Turner 
88303312863SZachary Turner   return VSN;
884f435a7eaSZachary Turner }
885f435a7eaSZachary Turner 
886f435a7eaSZachary Turner // Sometimes numbers are encoded in mangled symbols. For example,
887f435a7eaSZachary Turner // "int (*x)[20]" is a valid C type (x is a pointer to an array of
888f435a7eaSZachary Turner // length 20), so we need some way to embed numbers as part of symbols.
889f435a7eaSZachary Turner // This function parses it.
890f435a7eaSZachary Turner //
891f435a7eaSZachary Turner // <number>               ::= [?] <non-negative integer>
892f435a7eaSZachary Turner //
893f435a7eaSZachary Turner // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10
894502cf4bdSNico Weber //                        ::= <hex digit>+ @  # when Number == 0 or >= 10
895f435a7eaSZachary Turner //
896f435a7eaSZachary Turner // <hex-digit>            ::= [A-P]           # A = 0, B = 1, ...
demangleNumber(StringView & MangledName)897dbefc6cdSZachary Turner std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) {
898dbefc6cdSZachary Turner   bool IsNegative = MangledName.consumeFront('?');
899f435a7eaSZachary Turner 
900f435a7eaSZachary Turner   if (startsWithDigit(MangledName)) {
901dbefc6cdSZachary Turner     uint64_t Ret = MangledName[0] - '0' + 1;
902f435a7eaSZachary Turner     MangledName = MangledName.dropFront(1);
903dbefc6cdSZachary Turner     return {Ret, IsNegative};
904f435a7eaSZachary Turner   }
905f435a7eaSZachary Turner 
906dbefc6cdSZachary Turner   uint64_t Ret = 0;
907f435a7eaSZachary Turner   for (size_t i = 0; i < MangledName.size(); ++i) {
908f435a7eaSZachary Turner     char C = MangledName[i];
909f435a7eaSZachary Turner     if (C == '@') {
910f435a7eaSZachary Turner       MangledName = MangledName.dropFront(i + 1);
911dbefc6cdSZachary Turner       return {Ret, IsNegative};
912f435a7eaSZachary Turner     }
913f435a7eaSZachary Turner     if ('A' <= C && C <= 'P') {
914f435a7eaSZachary Turner       Ret = (Ret << 4) + (C - 'A');
915f435a7eaSZachary Turner       continue;
916f435a7eaSZachary Turner     }
917f435a7eaSZachary Turner     break;
918f435a7eaSZachary Turner   }
919f435a7eaSZachary Turner 
920f435a7eaSZachary Turner   Error = true;
921dbefc6cdSZachary Turner   return {0ULL, false};
922f435a7eaSZachary Turner }
923f435a7eaSZachary Turner 
demangleUnsigned(StringView & MangledName)924469f0763SZachary Turner uint64_t Demangler::demangleUnsigned(StringView &MangledName) {
925469f0763SZachary Turner   bool IsNegative = false;
926469f0763SZachary Turner   uint64_t Number = 0;
927469f0763SZachary Turner   std::tie(Number, IsNegative) = demangleNumber(MangledName);
928469f0763SZachary Turner   if (IsNegative)
929469f0763SZachary Turner     Error = true;
930469f0763SZachary Turner   return Number;
931469f0763SZachary Turner }
932469f0763SZachary Turner 
demangleSigned(StringView & MangledName)933469f0763SZachary Turner int64_t Demangler::demangleSigned(StringView &MangledName) {
934469f0763SZachary Turner   bool IsNegative = false;
935469f0763SZachary Turner   uint64_t Number = 0;
936469f0763SZachary Turner   std::tie(Number, IsNegative) = demangleNumber(MangledName);
937469f0763SZachary Turner   if (Number > INT64_MAX)
938469f0763SZachary Turner     Error = true;
939469f0763SZachary Turner   int64_t I = static_cast<int64_t>(Number);
940469f0763SZachary Turner   return IsNegative ? -I : I;
941469f0763SZachary Turner }
942469f0763SZachary Turner 
943f435a7eaSZachary Turner // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
944f435a7eaSZachary Turner // Memorize it.
memorizeString(StringView S)945f435a7eaSZachary Turner void Demangler::memorizeString(StringView S) {
946d346cba9SZachary Turner   if (Backrefs.NamesCount >= BackrefContext::Max)
947f435a7eaSZachary Turner     return;
948d346cba9SZachary Turner   for (size_t i = 0; i < Backrefs.NamesCount; ++i)
94903312863SZachary Turner     if (S == Backrefs.Names[i]->Name)
950f435a7eaSZachary Turner       return;
95103312863SZachary Turner   NamedIdentifierNode *N = Arena.alloc<NamedIdentifierNode>();
95203312863SZachary Turner   N->Name = S;
95303312863SZachary Turner   Backrefs.Names[Backrefs.NamesCount++] = N;
954f435a7eaSZachary Turner }
955f435a7eaSZachary Turner 
demangleBackRefName(StringView & MangledName)95603312863SZachary Turner NamedIdentifierNode *Demangler::demangleBackRefName(StringView &MangledName) {
957a7dffb13SZachary Turner   assert(startsWithDigit(MangledName));
958d9e925fcSZachary Turner 
959d9e925fcSZachary Turner   size_t I = MangledName[0] - '0';
960d9e925fcSZachary Turner   if (I >= Backrefs.NamesCount) {
961d9e925fcSZachary Turner     Error = true;
962d9e925fcSZachary Turner     return nullptr;
963d9e925fcSZachary Turner   }
964d9e925fcSZachary Turner 
965172aea10SZachary Turner   MangledName = MangledName.dropFront();
96603312863SZachary Turner   return Backrefs.Names[I];
967f435a7eaSZachary Turner }
968f435a7eaSZachary Turner 
memorizeIdentifier(IdentifierNode * Identifier)969b2fef1a0SZachary Turner void Demangler::memorizeIdentifier(IdentifierNode *Identifier) {
970b2fef1a0SZachary Turner   // Render this class template name into a string buffer so that we can
971b2fef1a0SZachary Turner   // memorize it for the purpose of back-referencing.
9722e97236aSLuís Ferreira   OutputBuffer OB;
973aabeb5ebSKirill Stoimenov   if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
974aabeb5ebSKirill Stoimenov     // FIXME: Propagate out-of-memory as an error?
975aabeb5ebSKirill Stoimenov     std::terminate();
9762e97236aSLuís Ferreira   Identifier->output(OB, OF_Default);
9771066e397SNathan Sidwell   StringView Owned = copyString(OB);
978b2fef1a0SZachary Turner   memorizeString(Owned);
9791066e397SNathan Sidwell   std::free(OB.getBuffer());
980b2fef1a0SZachary Turner }
981b2fef1a0SZachary Turner 
98203312863SZachary Turner IdentifierNode *
demangleTemplateInstantiationName(StringView & MangledName,NameBackrefBehavior NBB)98303312863SZachary Turner Demangler::demangleTemplateInstantiationName(StringView &MangledName,
98458d29cf5SZachary Turner                                              NameBackrefBehavior NBB) {
985a7dffb13SZachary Turner   assert(MangledName.startsWith("?$"));
986a7dffb13SZachary Turner   MangledName.consumeFront("?$");
987f435a7eaSZachary Turner 
988d346cba9SZachary Turner   BackrefContext OuterContext;
989d346cba9SZachary Turner   std::swap(OuterContext, Backrefs);
99054d4ffe5SZachary Turner 
99103312863SZachary Turner   IdentifierNode *Identifier =
99203312863SZachary Turner       demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
993d346cba9SZachary Turner   if (!Error)
99403312863SZachary Turner     Identifier->TemplateParams = demangleTemplateParameterList(MangledName);
995d346cba9SZachary Turner 
996d346cba9SZachary Turner   std::swap(OuterContext, Backrefs);
99754d4ffe5SZachary Turner   if (Error)
99854d4ffe5SZachary Turner     return nullptr;
99971c91f94SZachary Turner 
100064041d7bSNico Weber   if (NBB & NBB_Template) {
100164041d7bSNico Weber     // NBB_Template is only set for types and non-leaf names ("a::" in "a::b").
1002c035c243SNico Weber     // Structors and conversion operators only makes sense in a leaf name, so
1003c035c243SNico Weber     // reject them in NBB_Template contexts.
1004c035c243SNico Weber     if (Identifier->kind() == NodeKind::ConversionOperatorIdentifier ||
1005c035c243SNico Weber         Identifier->kind() == NodeKind::StructorIdentifier) {
100664041d7bSNico Weber       Error = true;
100764041d7bSNico Weber       return nullptr;
100864041d7bSNico Weber     }
100964041d7bSNico Weber 
1010b2fef1a0SZachary Turner     memorizeIdentifier(Identifier);
101164041d7bSNico Weber   }
101271c91f94SZachary Turner 
101303312863SZachary Turner   return Identifier;
1014f435a7eaSZachary Turner }
1015f435a7eaSZachary Turner 
demangleSimpleName(StringView & MangledName,bool Memorize)101603312863SZachary Turner NamedIdentifierNode *Demangler::demangleSimpleName(StringView &MangledName,
101703312863SZachary Turner                                                    bool Memorize) {
1018931e879cSZachary Turner   StringView S = demangleSimpleString(MangledName, Memorize);
1019931e879cSZachary Turner   if (Error)
1020931e879cSZachary Turner     return nullptr;
1021a7dffb13SZachary Turner 
102203312863SZachary Turner   NamedIdentifierNode *Name = Arena.alloc<NamedIdentifierNode>();
102303312863SZachary Turner   Name->Name = S;
102403312863SZachary Turner   return Name;
1025a7dffb13SZachary Turner }
1026f435a7eaSZachary Turner 
isRebasedHexDigit(char C)1027970fdc32SZachary Turner static bool isRebasedHexDigit(char C) { return (C >= 'A' && C <= 'P'); }
1028970fdc32SZachary Turner 
rebasedHexDigitToNumber(char C)1029970fdc32SZachary Turner static uint8_t rebasedHexDigitToNumber(char C) {
1030970fdc32SZachary Turner   assert(isRebasedHexDigit(C));
1031970fdc32SZachary Turner   return (C <= 'J') ? (C - 'A') : (10 + C - 'K');
1032970fdc32SZachary Turner }
1033970fdc32SZachary Turner 
demangleCharLiteral(StringView & MangledName)1034970fdc32SZachary Turner uint8_t Demangler::demangleCharLiteral(StringView &MangledName) {
1035a0ac65c9SNico Weber   assert(!MangledName.empty());
1036970fdc32SZachary Turner   if (!MangledName.startsWith('?'))
1037970fdc32SZachary Turner     return MangledName.popFront();
1038970fdc32SZachary Turner 
1039970fdc32SZachary Turner   MangledName = MangledName.dropFront();
1040970fdc32SZachary Turner   if (MangledName.empty())
1041970fdc32SZachary Turner     goto CharLiteralError;
1042970fdc32SZachary Turner 
1043970fdc32SZachary Turner   if (MangledName.consumeFront('$')) {
1044970fdc32SZachary Turner     // Two hex digits
1045970fdc32SZachary Turner     if (MangledName.size() < 2)
1046970fdc32SZachary Turner       goto CharLiteralError;
1047970fdc32SZachary Turner     StringView Nibbles = MangledName.substr(0, 2);
1048970fdc32SZachary Turner     if (!isRebasedHexDigit(Nibbles[0]) || !isRebasedHexDigit(Nibbles[1]))
1049970fdc32SZachary Turner       goto CharLiteralError;
1050970fdc32SZachary Turner     // Don't append the null terminator.
1051970fdc32SZachary Turner     uint8_t C1 = rebasedHexDigitToNumber(Nibbles[0]);
1052970fdc32SZachary Turner     uint8_t C2 = rebasedHexDigitToNumber(Nibbles[1]);
1053970fdc32SZachary Turner     MangledName = MangledName.dropFront(2);
1054970fdc32SZachary Turner     return (C1 << 4) | C2;
1055970fdc32SZachary Turner   }
1056970fdc32SZachary Turner 
1057970fdc32SZachary Turner   if (startsWithDigit(MangledName)) {
1058970fdc32SZachary Turner     const char *Lookup = ",/\\:. \n\t'-";
1059970fdc32SZachary Turner     char C = Lookup[MangledName[0] - '0'];
1060970fdc32SZachary Turner     MangledName = MangledName.dropFront();
1061970fdc32SZachary Turner     return C;
1062970fdc32SZachary Turner   }
1063970fdc32SZachary Turner 
1064970fdc32SZachary Turner   if (MangledName[0] >= 'a' && MangledName[0] <= 'z') {
1065970fdc32SZachary Turner     char Lookup[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7',
1066970fdc32SZachary Turner                        '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE',
1067970fdc32SZachary Turner                        '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5',
1068970fdc32SZachary Turner                        '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'};
1069970fdc32SZachary Turner     char C = Lookup[MangledName[0] - 'a'];
1070970fdc32SZachary Turner     MangledName = MangledName.dropFront();
1071970fdc32SZachary Turner     return C;
1072970fdc32SZachary Turner   }
1073970fdc32SZachary Turner 
1074970fdc32SZachary Turner   if (MangledName[0] >= 'A' && MangledName[0] <= 'Z') {
1075970fdc32SZachary Turner     char Lookup[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7',
1076970fdc32SZachary Turner                        '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE',
1077970fdc32SZachary Turner                        '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5',
1078970fdc32SZachary Turner                        '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'};
1079970fdc32SZachary Turner     char C = Lookup[MangledName[0] - 'A'];
1080970fdc32SZachary Turner     MangledName = MangledName.dropFront();
1081970fdc32SZachary Turner     return C;
1082970fdc32SZachary Turner   }
1083970fdc32SZachary Turner 
1084970fdc32SZachary Turner CharLiteralError:
1085970fdc32SZachary Turner   Error = true;
1086970fdc32SZachary Turner   return '\0';
1087970fdc32SZachary Turner }
1088970fdc32SZachary Turner 
demangleWcharLiteral(StringView & MangledName)1089970fdc32SZachary Turner wchar_t Demangler::demangleWcharLiteral(StringView &MangledName) {
1090d78fe2f4SZachary Turner   uint8_t C1, C2;
1091d78fe2f4SZachary Turner 
1092d78fe2f4SZachary Turner   C1 = demangleCharLiteral(MangledName);
1093f5c7f3adSNico Weber   if (Error || MangledName.empty())
1094970fdc32SZachary Turner     goto WCharLiteralError;
1095d78fe2f4SZachary Turner   C2 = demangleCharLiteral(MangledName);
1096970fdc32SZachary Turner   if (Error)
1097970fdc32SZachary Turner     goto WCharLiteralError;
1098970fdc32SZachary Turner 
1099970fdc32SZachary Turner   return ((wchar_t)C1 << 8) | (wchar_t)C2;
1100970fdc32SZachary Turner 
1101970fdc32SZachary Turner WCharLiteralError:
1102970fdc32SZachary Turner   Error = true;
1103970fdc32SZachary Turner   return L'\0';
1104970fdc32SZachary Turner }
1105970fdc32SZachary Turner 
writeHexDigit(char * Buffer,uint8_t Digit)1106970fdc32SZachary Turner static void writeHexDigit(char *Buffer, uint8_t Digit) {
1107970fdc32SZachary Turner   assert(Digit <= 15);
1108970fdc32SZachary Turner   *Buffer = (Digit < 10) ? ('0' + Digit) : ('A' + Digit - 10);
1109970fdc32SZachary Turner }
1110970fdc32SZachary Turner 
outputHex(OutputBuffer & OB,unsigned C)11112e97236aSLuís Ferreira static void outputHex(OutputBuffer &OB, unsigned C) {
1112b5cd6163SNico Weber   assert (C != 0);
1113b5cd6163SNico Weber 
1114970fdc32SZachary Turner   // It's easier to do the math if we can work from right to left, but we need
1115970fdc32SZachary Turner   // to print the numbers from left to right.  So render this into a temporary
1116970fdc32SZachary Turner   // buffer first, then output the temporary buffer.  Each byte is of the form
1117970fdc32SZachary Turner   // \xAB, which means that each byte needs 4 characters.  Since there are at
1118970fdc32SZachary Turner   // most 4 bytes, we need a 4*4+1 = 17 character temporary buffer.
1119970fdc32SZachary Turner   char TempBuffer[17];
1120970fdc32SZachary Turner 
1121970fdc32SZachary Turner   ::memset(TempBuffer, 0, sizeof(TempBuffer));
11228fc9902bSNico Weber   constexpr int MaxPos = sizeof(TempBuffer) - 1;
1123970fdc32SZachary Turner 
11248fc9902bSNico Weber   int Pos = MaxPos - 1; // TempBuffer[MaxPos] is the terminating \0.
1125970fdc32SZachary Turner   while (C != 0) {
1126970fdc32SZachary Turner     for (int I = 0; I < 2; ++I) {
1127970fdc32SZachary Turner       writeHexDigit(&TempBuffer[Pos--], C % 16);
1128970fdc32SZachary Turner       C /= 16;
1129970fdc32SZachary Turner     }
1130ce67a417SNico Weber   }
1131970fdc32SZachary Turner   TempBuffer[Pos--] = 'x';
1132970fdc32SZachary Turner   assert(Pos >= 0);
11338fc9902bSNico Weber   TempBuffer[Pos--] = '\\';
11342e97236aSLuís Ferreira   OB << StringView(&TempBuffer[Pos + 1]);
1135970fdc32SZachary Turner }
1136970fdc32SZachary Turner 
outputEscapedChar(OutputBuffer & OB,unsigned C)11372e97236aSLuís Ferreira static void outputEscapedChar(OutputBuffer &OB, unsigned C) {
1138970fdc32SZachary Turner   switch (C) {
11398eeaf517SNico Weber   case '\0': // nul
11402e97236aSLuís Ferreira     OB << "\\0";
11418eeaf517SNico Weber     return;
1142970fdc32SZachary Turner   case '\'': // single quote
11432e97236aSLuís Ferreira     OB << "\\\'";
1144970fdc32SZachary Turner     return;
1145970fdc32SZachary Turner   case '\"': // double quote
11462e97236aSLuís Ferreira     OB << "\\\"";
1147970fdc32SZachary Turner     return;
1148970fdc32SZachary Turner   case '\\': // backslash
11492e97236aSLuís Ferreira     OB << "\\\\";
1150970fdc32SZachary Turner     return;
1151970fdc32SZachary Turner   case '\a': // bell
11522e97236aSLuís Ferreira     OB << "\\a";
1153970fdc32SZachary Turner     return;
1154970fdc32SZachary Turner   case '\b': // backspace
11552e97236aSLuís Ferreira     OB << "\\b";
1156970fdc32SZachary Turner     return;
1157970fdc32SZachary Turner   case '\f': // form feed
11582e97236aSLuís Ferreira     OB << "\\f";
1159970fdc32SZachary Turner     return;
1160970fdc32SZachary Turner   case '\n': // new line
11612e97236aSLuís Ferreira     OB << "\\n";
1162970fdc32SZachary Turner     return;
1163970fdc32SZachary Turner   case '\r': // carriage return
11642e97236aSLuís Ferreira     OB << "\\r";
1165970fdc32SZachary Turner     return;
1166970fdc32SZachary Turner   case '\t': // tab
11672e97236aSLuís Ferreira     OB << "\\t";
1168970fdc32SZachary Turner     return;
1169970fdc32SZachary Turner   case '\v': // vertical tab
11702e97236aSLuís Ferreira     OB << "\\v";
1171970fdc32SZachary Turner     return;
1172970fdc32SZachary Turner   default:
1173970fdc32SZachary Turner     break;
1174970fdc32SZachary Turner   }
1175970fdc32SZachary Turner 
1176970fdc32SZachary Turner   if (C > 0x1F && C < 0x7F) {
1177970fdc32SZachary Turner     // Standard ascii char.
11782e97236aSLuís Ferreira     OB << (char)C;
1179970fdc32SZachary Turner     return;
1180970fdc32SZachary Turner   }
1181970fdc32SZachary Turner 
11822e97236aSLuís Ferreira   outputHex(OB, C);
1183970fdc32SZachary Turner }
1184970fdc32SZachary Turner 
countTrailingNullBytes(const uint8_t * StringBytes,int Length)1185c55e9975SBenjamin Kramer static unsigned countTrailingNullBytes(const uint8_t *StringBytes, int Length) {
1186970fdc32SZachary Turner   const uint8_t *End = StringBytes + Length - 1;
11873461bfaaSZachary Turner   unsigned Count = 0;
1188970fdc32SZachary Turner   while (Length > 0 && *End == 0) {
1189970fdc32SZachary Turner     --Length;
1190970fdc32SZachary Turner     --End;
11913461bfaaSZachary Turner     ++Count;
1192970fdc32SZachary Turner   }
11933461bfaaSZachary Turner   return Count;
1194970fdc32SZachary Turner }
1195970fdc32SZachary Turner 
countEmbeddedNulls(const uint8_t * StringBytes,unsigned Length)1196c55e9975SBenjamin Kramer static unsigned countEmbeddedNulls(const uint8_t *StringBytes,
1197c55e9975SBenjamin Kramer                                    unsigned Length) {
1198970fdc32SZachary Turner   unsigned Result = 0;
1199970fdc32SZachary Turner   for (unsigned I = 0; I < Length; ++I) {
1200970fdc32SZachary Turner     if (*StringBytes++ == 0)
1201970fdc32SZachary Turner       ++Result;
1202970fdc32SZachary Turner   }
1203970fdc32SZachary Turner   return Result;
1204970fdc32SZachary Turner }
1205970fdc32SZachary Turner 
12068d05eb85SNico Weber // A mangled (non-wide) string literal stores the total length of the string it
12078d05eb85SNico Weber // refers to (passed in NumBytes), and it contains up to 32 bytes of actual text
12088d05eb85SNico Weber // (passed in StringBytes, NumChars).
guessCharByteSize(const uint8_t * StringBytes,unsigned NumChars,uint64_t NumBytes)1209c55e9975SBenjamin Kramer static unsigned guessCharByteSize(const uint8_t *StringBytes, unsigned NumChars,
12108d05eb85SNico Weber                                   uint64_t NumBytes) {
1211970fdc32SZachary Turner   assert(NumBytes > 0);
1212970fdc32SZachary Turner 
1213970fdc32SZachary Turner   // If the number of bytes is odd, this is guaranteed to be a char string.
1214970fdc32SZachary Turner   if (NumBytes % 2 == 1)
1215970fdc32SZachary Turner     return 1;
1216970fdc32SZachary Turner 
1217970fdc32SZachary Turner   // All strings can encode at most 32 bytes of data.  If it's less than that,
1218970fdc32SZachary Turner   // then we encoded the entire string.  In this case we check for a 1-byte,
1219970fdc32SZachary Turner   // 2-byte, or 4-byte null terminator.
1220970fdc32SZachary Turner   if (NumBytes < 32) {
1221970fdc32SZachary Turner     unsigned TrailingNulls = countTrailingNullBytes(StringBytes, NumChars);
12228eeaf517SNico Weber     if (TrailingNulls >= 4 && NumBytes % 4 == 0)
1223970fdc32SZachary Turner       return 4;
1224970fdc32SZachary Turner     if (TrailingNulls >= 2)
1225970fdc32SZachary Turner       return 2;
1226970fdc32SZachary Turner     return 1;
1227970fdc32SZachary Turner   }
1228970fdc32SZachary Turner 
1229970fdc32SZachary Turner   // The whole string was not able to be encoded.  Try to look at embedded null
1230970fdc32SZachary Turner   // terminators to guess.  The heuristic is that we count all embedded null
1231970fdc32SZachary Turner   // terminators.  If more than 2/3 are null, it's a char32.  If more than 1/3
1232970fdc32SZachary Turner   // are null, it's a char16.  Otherwise it's a char8.  This obviously isn't
1233970fdc32SZachary Turner   // perfect and is biased towards languages that have ascii alphabets, but this
1234970fdc32SZachary Turner   // was always going to be best effort since the encoding is lossy.
1235970fdc32SZachary Turner   unsigned Nulls = countEmbeddedNulls(StringBytes, NumChars);
12368eeaf517SNico Weber   if (Nulls >= 2 * NumChars / 3 && NumBytes % 4 == 0)
1237970fdc32SZachary Turner     return 4;
1238970fdc32SZachary Turner   if (Nulls >= NumChars / 3)
1239970fdc32SZachary Turner     return 2;
1240970fdc32SZachary Turner   return 1;
1241970fdc32SZachary Turner }
1242970fdc32SZachary Turner 
decodeMultiByteChar(const uint8_t * StringBytes,unsigned CharIndex,unsigned CharBytes)1243970fdc32SZachary Turner static unsigned decodeMultiByteChar(const uint8_t *StringBytes,
1244970fdc32SZachary Turner                                     unsigned CharIndex, unsigned CharBytes) {
1245970fdc32SZachary Turner   assert(CharBytes == 1 || CharBytes == 2 || CharBytes == 4);
1246970fdc32SZachary Turner   unsigned Offset = CharIndex * CharBytes;
1247970fdc32SZachary Turner   unsigned Result = 0;
1248970fdc32SZachary Turner   StringBytes = StringBytes + Offset;
1249970fdc32SZachary Turner   for (unsigned I = 0; I < CharBytes; ++I) {
1250970fdc32SZachary Turner     unsigned C = static_cast<unsigned>(StringBytes[I]);
1251970fdc32SZachary Turner     Result |= C << (8 * I);
1252970fdc32SZachary Turner   }
1253970fdc32SZachary Turner   return Result;
1254970fdc32SZachary Turner }
1255970fdc32SZachary Turner 
demangleVcallThunkNode(StringView & MangledName)125603312863SZachary Turner FunctionSymbolNode *Demangler::demangleVcallThunkNode(StringView &MangledName) {
125703312863SZachary Turner   FunctionSymbolNode *FSN = Arena.alloc<FunctionSymbolNode>();
125803312863SZachary Turner   VcallThunkIdentifierNode *VTIN = Arena.alloc<VcallThunkIdentifierNode>();
125903312863SZachary Turner   FSN->Signature = Arena.alloc<ThunkSignatureNode>();
126003312863SZachary Turner   FSN->Signature->FunctionClass = FC_NoParameterList;
126103312863SZachary Turner 
126203312863SZachary Turner   FSN->Name = demangleNameScopeChain(MangledName, VTIN);
126303312863SZachary Turner   if (!Error)
126403312863SZachary Turner     Error = !MangledName.consumeFront("$B");
126503312863SZachary Turner   if (!Error)
126603312863SZachary Turner     VTIN->OffsetInVTable = demangleUnsigned(MangledName);
126703312863SZachary Turner   if (!Error)
126803312863SZachary Turner     Error = !MangledName.consumeFront('A');
126903312863SZachary Turner   if (!Error)
127003312863SZachary Turner     FSN->Signature->CallConvention = demangleCallingConvention(MangledName);
127103312863SZachary Turner   return (Error) ? nullptr : FSN;
127203312863SZachary Turner }
127303312863SZachary Turner 
127403312863SZachary Turner EncodedStringLiteralNode *
demangleStringLiteral(StringView & MangledName)127503312863SZachary Turner Demangler::demangleStringLiteral(StringView &MangledName) {
1276d78fe2f4SZachary Turner   // This function uses goto, so declare all variables up front.
12772e97236aSLuís Ferreira   OutputBuffer OB;
1278970fdc32SZachary Turner   StringView CRC;
1279d78fe2f4SZachary Turner   uint64_t StringByteSize;
1280d78fe2f4SZachary Turner   bool IsWcharT = false;
1281d78fe2f4SZachary Turner   bool IsNegative = false;
1282d78fe2f4SZachary Turner   size_t CrcEndPos = 0;
1283d78fe2f4SZachary Turner 
128403312863SZachary Turner   EncodedStringLiteralNode *Result = Arena.alloc<EncodedStringLiteralNode>();
1285970fdc32SZachary Turner 
1286aabeb5ebSKirill Stoimenov   // Must happen before the first `goto StringLiteralError`.
1287aabeb5ebSKirill Stoimenov   if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
1288aabeb5ebSKirill Stoimenov     // FIXME: Propagate out-of-memory as an error?
1289aabeb5ebSKirill Stoimenov     std::terminate();
1290aabeb5ebSKirill Stoimenov 
1291970fdc32SZachary Turner   // Prefix indicating the beginning of a string literal
12923461bfaaSZachary Turner   if (!MangledName.consumeFront("@_"))
12933461bfaaSZachary Turner     goto StringLiteralError;
1294970fdc32SZachary Turner   if (MangledName.empty())
1295970fdc32SZachary Turner     goto StringLiteralError;
1296970fdc32SZachary Turner 
1297970fdc32SZachary Turner   // Char Type (regular or wchar_t)
1298970fdc32SZachary Turner   switch (MangledName.popFront()) {
1299970fdc32SZachary Turner   case '1':
1300970fdc32SZachary Turner     IsWcharT = true;
13015094e5efSErik Pilkington     DEMANGLE_FALLTHROUGH;
1302970fdc32SZachary Turner   case '0':
1303970fdc32SZachary Turner     break;
1304970fdc32SZachary Turner   default:
1305970fdc32SZachary Turner     goto StringLiteralError;
1306970fdc32SZachary Turner   }
1307970fdc32SZachary Turner 
1308970fdc32SZachary Turner   // Encoded Length
1309970fdc32SZachary Turner   std::tie(StringByteSize, IsNegative) = demangleNumber(MangledName);
1310a0ac65c9SNico Weber   if (Error || IsNegative || StringByteSize < (IsWcharT ? 2 : 1))
1311970fdc32SZachary Turner     goto StringLiteralError;
1312970fdc32SZachary Turner 
1313970fdc32SZachary Turner   // CRC 32 (always 8 characters plus a terminator)
1314d78fe2f4SZachary Turner   CrcEndPos = MangledName.find('@');
1315970fdc32SZachary Turner   if (CrcEndPos == StringView::npos)
1316970fdc32SZachary Turner     goto StringLiteralError;
1317970fdc32SZachary Turner   CRC = MangledName.substr(0, CrcEndPos);
1318970fdc32SZachary Turner   MangledName = MangledName.dropFront(CrcEndPos + 1);
1319970fdc32SZachary Turner   if (MangledName.empty())
1320970fdc32SZachary Turner     goto StringLiteralError;
1321970fdc32SZachary Turner 
1322970fdc32SZachary Turner   if (IsWcharT) {
132303312863SZachary Turner     Result->Char = CharKind::Wchar;
1324970fdc32SZachary Turner     if (StringByteSize > 64)
13253461bfaaSZachary Turner       Result->IsTruncated = true;
1326970fdc32SZachary Turner 
1327970fdc32SZachary Turner     while (!MangledName.consumeFront('@')) {
1328a0ac65c9SNico Weber       if (MangledName.size() < 2)
1329502cf4bdSNico Weber         goto StringLiteralError;
1330970fdc32SZachary Turner       wchar_t W = demangleWcharLiteral(MangledName);
13313461bfaaSZachary Turner       if (StringByteSize != 2 || Result->IsTruncated)
13322e97236aSLuís Ferreira         outputEscapedChar(OB, W);
1333970fdc32SZachary Turner       StringByteSize -= 2;
1334970fdc32SZachary Turner       if (Error)
1335970fdc32SZachary Turner         goto StringLiteralError;
1336970fdc32SZachary Turner     }
1337970fdc32SZachary Turner   } else {
133832a8a202SZachary Turner     // The max byte length is actually 32, but some compilers mangled strings
133932a8a202SZachary Turner     // incorrectly, so we have to assume it can go higher.
134032a8a202SZachary Turner     constexpr unsigned MaxStringByteLength = 32 * 4;
1341970fdc32SZachary Turner     uint8_t StringBytes[MaxStringByteLength];
1342970fdc32SZachary Turner 
1343970fdc32SZachary Turner     unsigned BytesDecoded = 0;
1344970fdc32SZachary Turner     while (!MangledName.consumeFront('@')) {
1345aa162682SNico Weber       if (MangledName.size() < 1 || BytesDecoded >= MaxStringByteLength)
1346502cf4bdSNico Weber         goto StringLiteralError;
1347970fdc32SZachary Turner       StringBytes[BytesDecoded++] = demangleCharLiteral(MangledName);
1348970fdc32SZachary Turner     }
1349970fdc32SZachary Turner 
135032a8a202SZachary Turner     if (StringByteSize > BytesDecoded)
135132a8a202SZachary Turner       Result->IsTruncated = true;
135232a8a202SZachary Turner 
1353970fdc32SZachary Turner     unsigned CharBytes =
1354970fdc32SZachary Turner         guessCharByteSize(StringBytes, BytesDecoded, StringByteSize);
1355970fdc32SZachary Turner     assert(StringByteSize % CharBytes == 0);
1356970fdc32SZachary Turner     switch (CharBytes) {
1357970fdc32SZachary Turner     case 1:
135803312863SZachary Turner       Result->Char = CharKind::Char;
1359970fdc32SZachary Turner       break;
1360970fdc32SZachary Turner     case 2:
136103312863SZachary Turner       Result->Char = CharKind::Char16;
1362970fdc32SZachary Turner       break;
1363970fdc32SZachary Turner     case 4:
136403312863SZachary Turner       Result->Char = CharKind::Char32;
1365970fdc32SZachary Turner       break;
1366970fdc32SZachary Turner     default:
13675094e5efSErik Pilkington       DEMANGLE_UNREACHABLE;
1368970fdc32SZachary Turner     }
1369970fdc32SZachary Turner     const unsigned NumChars = BytesDecoded / CharBytes;
1370970fdc32SZachary Turner     for (unsigned CharIndex = 0; CharIndex < NumChars; ++CharIndex) {
1371970fdc32SZachary Turner       unsigned NextChar =
1372970fdc32SZachary Turner           decodeMultiByteChar(StringBytes, CharIndex, CharBytes);
13733461bfaaSZachary Turner       if (CharIndex + 1 < NumChars || Result->IsTruncated)
13742e97236aSLuís Ferreira         outputEscapedChar(OB, NextChar);
1375970fdc32SZachary Turner     }
1376970fdc32SZachary Turner   }
1377970fdc32SZachary Turner 
13781066e397SNathan Sidwell   Result->DecodedString = copyString(OB);
13791066e397SNathan Sidwell   std::free(OB.getBuffer());
1380970fdc32SZachary Turner   return Result;
1381970fdc32SZachary Turner 
1382970fdc32SZachary Turner StringLiteralError:
1383970fdc32SZachary Turner   Error = true;
13842e97236aSLuís Ferreira   std::free(OB.getBuffer());
1385970fdc32SZachary Turner   return nullptr;
1386970fdc32SZachary Turner }
1387970fdc32SZachary Turner 
1388c7444ddfSNico Weber // Returns MangledName's prefix before the first '@', or an error if
1389c7444ddfSNico Weber // MangledName contains no '@' or the prefix has length 0.
demangleSimpleString(StringView & MangledName,bool Memorize)1390931e879cSZachary Turner StringView Demangler::demangleSimpleString(StringView &MangledName,
1391931e879cSZachary Turner                                            bool Memorize) {
1392931e879cSZachary Turner   StringView S;
1393931e879cSZachary Turner   for (size_t i = 0; i < MangledName.size(); ++i) {
1394931e879cSZachary Turner     if (MangledName[i] != '@')
1395931e879cSZachary Turner       continue;
1396c7444ddfSNico Weber     if (i == 0)
1397c7444ddfSNico Weber       break;
1398931e879cSZachary Turner     S = MangledName.substr(0, i);
1399931e879cSZachary Turner     MangledName = MangledName.dropFront(i + 1);
1400931e879cSZachary Turner 
1401931e879cSZachary Turner     if (Memorize)
1402931e879cSZachary Turner       memorizeString(S);
1403931e879cSZachary Turner     return S;
1404931e879cSZachary Turner   }
1405931e879cSZachary Turner 
1406f435a7eaSZachary Turner   Error = true;
1407931e879cSZachary Turner   return {};
1408a7dffb13SZachary Turner }
1409a7dffb13SZachary Turner 
141003312863SZachary Turner NamedIdentifierNode *
demangleAnonymousNamespaceName(StringView & MangledName)141103312863SZachary Turner Demangler::demangleAnonymousNamespaceName(StringView &MangledName) {
1412a7dffb13SZachary Turner   assert(MangledName.startsWith("?A"));
1413a7dffb13SZachary Turner   MangledName.consumeFront("?A");
1414a7dffb13SZachary Turner 
141503312863SZachary Turner   NamedIdentifierNode *Node = Arena.alloc<NamedIdentifierNode>();
141603312863SZachary Turner   Node->Name = "`anonymous namespace'";
141791c98a85SZachary Turner   size_t EndPos = MangledName.find('@');
141891c98a85SZachary Turner   if (EndPos == StringView::npos) {
1419a7dffb13SZachary Turner     Error = true;
1420a7dffb13SZachary Turner     return nullptr;
1421a7dffb13SZachary Turner   }
14220002dd46SZachary Turner   StringView NamespaceKey = MangledName.substr(0, EndPos);
14230002dd46SZachary Turner   memorizeString(NamespaceKey);
142491c98a85SZachary Turner   MangledName = MangledName.substr(EndPos + 1);
142591c98a85SZachary Turner   return Node;
142691c98a85SZachary Turner }
1427a7dffb13SZachary Turner 
142803312863SZachary Turner NamedIdentifierNode *
demangleLocallyScopedNamePiece(StringView & MangledName)142903312863SZachary Turner Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) {
143071c91f94SZachary Turner   assert(startsWithLocalScopePattern(MangledName));
143171c91f94SZachary Turner 
143203312863SZachary Turner   NamedIdentifierNode *Identifier = Arena.alloc<NamedIdentifierNode>();
143371c91f94SZachary Turner   MangledName.consumeFront('?');
1434c5615c23SNico Weber   uint64_t Number = 0;
1435c5615c23SNico Weber   bool IsNegative = false;
1436c5615c23SNico Weber   std::tie(Number, IsNegative) = demangleNumber(MangledName);
1437c5615c23SNico Weber   assert(!IsNegative);
143871c91f94SZachary Turner 
143971c91f94SZachary Turner   // One ? to terminate the number
144071c91f94SZachary Turner   MangledName.consumeFront('?');
144171c91f94SZachary Turner 
144271c91f94SZachary Turner   assert(!Error);
144303312863SZachary Turner   Node *Scope = parse(MangledName);
144471c91f94SZachary Turner   if (Error)
144571c91f94SZachary Turner     return nullptr;
144671c91f94SZachary Turner 
144771c91f94SZachary Turner   // Render the parent symbol's name into a buffer.
14482e97236aSLuís Ferreira   OutputBuffer OB;
1449aabeb5ebSKirill Stoimenov   if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
1450aabeb5ebSKirill Stoimenov     // FIXME: Propagate out-of-memory as an error?
1451aabeb5ebSKirill Stoimenov     std::terminate();
14522e97236aSLuís Ferreira   OB << '`';
14532e97236aSLuís Ferreira   Scope->output(OB, OF_Default);
14542e97236aSLuís Ferreira   OB << '\'';
14552e97236aSLuís Ferreira   OB << "::`" << Number << "'";
14561066e397SNathan Sidwell 
14571066e397SNathan Sidwell   Identifier->Name = copyString(OB);
14581066e397SNathan Sidwell   std::free(OB.getBuffer());
145903312863SZachary Turner   return Identifier;
146071c91f94SZachary Turner }
146171c91f94SZachary Turner 
1462a7dffb13SZachary Turner // Parses a type name in the form of A@B@C@@ which represents C::B::A.
146303312863SZachary Turner QualifiedNameNode *
demangleFullyQualifiedTypeName(StringView & MangledName)146403312863SZachary Turner Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) {
1465af2ee7d0SNico Weber   IdentifierNode *Identifier =
1466af2ee7d0SNico Weber       demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true);
146754d4ffe5SZachary Turner   if (Error)
146854d4ffe5SZachary Turner     return nullptr;
146903312863SZachary Turner   assert(Identifier);
1470a7dffb13SZachary Turner 
147103312863SZachary Turner   QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier);
147254d4ffe5SZachary Turner   if (Error)
147354d4ffe5SZachary Turner     return nullptr;
147403312863SZachary Turner   assert(QN);
147503312863SZachary Turner   return QN;
1476a7dffb13SZachary Turner }
1477a7dffb13SZachary Turner 
1478a7dffb13SZachary Turner // Parses a symbol name in the form of A@B@C@@ which represents C::B::A.
1479a7dffb13SZachary Turner // Symbol names have slightly different rules regarding what can appear
1480a7dffb13SZachary Turner // so we separate out the implementations for flexibility.
148103312863SZachary Turner QualifiedNameNode *
demangleFullyQualifiedSymbolName(StringView & MangledName)148203312863SZachary Turner Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) {
148358d29cf5SZachary Turner   // This is the final component of a symbol name (i.e. the leftmost component
148458d29cf5SZachary Turner   // of a mangled name.  Since the only possible template instantiation that
148558d29cf5SZachary Turner   // can appear in this context is a function template, and since those are
148658d29cf5SZachary Turner   // not saved for the purposes of name backreferences, only backref simple
148758d29cf5SZachary Turner   // names.
148803312863SZachary Turner   IdentifierNode *Identifier =
148903312863SZachary Turner       demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
149054d4ffe5SZachary Turner   if (Error)
149154d4ffe5SZachary Turner     return nullptr;
14923461bfaaSZachary Turner 
149303312863SZachary Turner   QualifiedNameNode *QN = demangleNameScopeChain(MangledName, Identifier);
149454d4ffe5SZachary Turner   if (Error)
149554d4ffe5SZachary Turner     return nullptr;
149603312863SZachary Turner 
149703312863SZachary Turner   if (Identifier->kind() == NodeKind::StructorIdentifier) {
1498a9886f82SNico Weber     if (QN->Components->Count < 2) {
1499a9886f82SNico Weber       Error = true;
1500a9886f82SNico Weber       return nullptr;
1501a9886f82SNico Weber     }
150203312863SZachary Turner     StructorIdentifierNode *SIN =
150303312863SZachary Turner         static_cast<StructorIdentifierNode *>(Identifier);
150403312863SZachary Turner     Node *ClassNode = QN->Components->Nodes[QN->Components->Count - 2];
150503312863SZachary Turner     SIN->Class = static_cast<IdentifierNode *>(ClassNode);
150603312863SZachary Turner   }
150703312863SZachary Turner   assert(QN);
150803312863SZachary Turner   return QN;
1509a7dffb13SZachary Turner }
1510a7dffb13SZachary Turner 
demangleUnqualifiedTypeName(StringView & MangledName,bool Memorize)151103312863SZachary Turner IdentifierNode *Demangler::demangleUnqualifiedTypeName(StringView &MangledName,
151244ebbc21SZachary Turner                                                        bool Memorize) {
1513a7dffb13SZachary Turner   // An inner-most name can be a back-reference, because a fully-qualified name
1514a7dffb13SZachary Turner   // (e.g. Scope + Inner) can contain other fully qualified names inside of
1515a7dffb13SZachary Turner   // them (for example template parameters), and these nested parameters can
1516a7dffb13SZachary Turner   // refer to previously mangled types.
1517a7dffb13SZachary Turner   if (startsWithDigit(MangledName))
1518316109b5SZachary Turner     return demangleBackRefName(MangledName);
1519a7dffb13SZachary Turner 
1520a7dffb13SZachary Turner   if (MangledName.startsWith("?$"))
152158d29cf5SZachary Turner     return demangleTemplateInstantiationName(MangledName, NBB_Template);
1522a7dffb13SZachary Turner 
152344ebbc21SZachary Turner   return demangleSimpleName(MangledName, Memorize);
1524a7dffb13SZachary Turner }
1525a7dffb13SZachary Turner 
152603312863SZachary Turner IdentifierNode *
demangleUnqualifiedSymbolName(StringView & MangledName,NameBackrefBehavior NBB)152703312863SZachary Turner Demangler::demangleUnqualifiedSymbolName(StringView &MangledName,
152858d29cf5SZachary Turner                                          NameBackrefBehavior NBB) {
152971c91f94SZachary Turner   if (startsWithDigit(MangledName))
153071c91f94SZachary Turner     return demangleBackRefName(MangledName);
153171c91f94SZachary Turner   if (MangledName.startsWith("?$"))
153258d29cf5SZachary Turner     return demangleTemplateInstantiationName(MangledName, NBB);
1533a7dffb13SZachary Turner   if (MangledName.startsWith('?'))
153403312863SZachary Turner     return demangleFunctionIdentifierCode(MangledName);
1535af2ee7d0SNico Weber   return demangleSimpleName(MangledName, /*Memorize=*/(NBB & NBB_Simple) != 0);
1536a7dffb13SZachary Turner }
1537a7dffb13SZachary Turner 
demangleNameScopePiece(StringView & MangledName)153803312863SZachary Turner IdentifierNode *Demangler::demangleNameScopePiece(StringView &MangledName) {
1539a7dffb13SZachary Turner   if (startsWithDigit(MangledName))
1540316109b5SZachary Turner     return demangleBackRefName(MangledName);
1541a7dffb13SZachary Turner 
1542a7dffb13SZachary Turner   if (MangledName.startsWith("?$"))
154358d29cf5SZachary Turner     return demangleTemplateInstantiationName(MangledName, NBB_Template);
1544a7dffb13SZachary Turner 
1545a7dffb13SZachary Turner   if (MangledName.startsWith("?A"))
1546316109b5SZachary Turner     return demangleAnonymousNamespaceName(MangledName);
1547a7dffb13SZachary Turner 
154871c91f94SZachary Turner   if (startsWithLocalScopePattern(MangledName))
154971c91f94SZachary Turner     return demangleLocallyScopedNamePiece(MangledName);
155071c91f94SZachary Turner 
1551af2ee7d0SNico Weber   return demangleSimpleName(MangledName, /*Memorize=*/true);
1552a7dffb13SZachary Turner }
1553a7dffb13SZachary Turner 
nodeListToNodeArray(ArenaAllocator & Arena,NodeList * Head,size_t Count)155403312863SZachary Turner static NodeArrayNode *nodeListToNodeArray(ArenaAllocator &Arena, NodeList *Head,
155503312863SZachary Turner                                           size_t Count) {
155603312863SZachary Turner   NodeArrayNode *N = Arena.alloc<NodeArrayNode>();
155703312863SZachary Turner   N->Count = Count;
155803312863SZachary Turner   N->Nodes = Arena.allocArray<Node *>(Count);
155903312863SZachary Turner   for (size_t I = 0; I < Count; ++I) {
156003312863SZachary Turner     N->Nodes[I] = Head->N;
156103312863SZachary Turner     Head = Head->Next;
156203312863SZachary Turner   }
156303312863SZachary Turner   return N;
156403312863SZachary Turner }
1565a7dffb13SZachary Turner 
156603312863SZachary Turner QualifiedNameNode *
demangleNameScopeChain(StringView & MangledName,IdentifierNode * UnqualifiedName)156703312863SZachary Turner Demangler::demangleNameScopeChain(StringView &MangledName,
156803312863SZachary Turner                                   IdentifierNode *UnqualifiedName) {
156903312863SZachary Turner   NodeList *Head = Arena.alloc<NodeList>();
157003312863SZachary Turner 
157103312863SZachary Turner   Head->N = UnqualifiedName;
157203312863SZachary Turner 
157303312863SZachary Turner   size_t Count = 1;
1574a7dffb13SZachary Turner   while (!MangledName.consumeFront("@")) {
157503312863SZachary Turner     ++Count;
157603312863SZachary Turner     NodeList *NewHead = Arena.alloc<NodeList>();
157703312863SZachary Turner     NewHead->Next = Head;
157803312863SZachary Turner     Head = NewHead;
157903312863SZachary Turner 
1580a7dffb13SZachary Turner     if (MangledName.empty()) {
1581a7dffb13SZachary Turner       Error = true;
1582a7dffb13SZachary Turner       return nullptr;
1583a7dffb13SZachary Turner     }
1584a7dffb13SZachary Turner 
1585a7dffb13SZachary Turner     assert(!Error);
158603312863SZachary Turner     IdentifierNode *Elem = demangleNameScopePiece(MangledName);
1587a7dffb13SZachary Turner     if (Error)
1588a7dffb13SZachary Turner       return nullptr;
1589a7dffb13SZachary Turner 
159003312863SZachary Turner     Head->N = Elem;
1591a7dffb13SZachary Turner   }
159203312863SZachary Turner 
159303312863SZachary Turner   QualifiedNameNode *QN = Arena.alloc<QualifiedNameNode>();
159403312863SZachary Turner   QN->Components = nodeListToNodeArray(Arena, Head, Count);
159503312863SZachary Turner   return QN;
1596f435a7eaSZachary Turner }
1597f435a7eaSZachary Turner 
demangleFunctionClass(StringView & MangledName)1598316109b5SZachary Turner FuncClass Demangler::demangleFunctionClass(StringView &MangledName) {
1599f435a7eaSZachary Turner   switch (MangledName.popFront()) {
160029ec67b6SZachary Turner   case '9':
160103312863SZachary Turner     return FuncClass(FC_ExternC | FC_NoParameterList);
1602f435a7eaSZachary Turner   case 'A':
160303312863SZachary Turner     return FC_Private;
1604f435a7eaSZachary Turner   case 'B':
160503312863SZachary Turner     return FuncClass(FC_Private | FC_Far);
1606f435a7eaSZachary Turner   case 'C':
160703312863SZachary Turner     return FuncClass(FC_Private | FC_Static);
1608f435a7eaSZachary Turner   case 'D':
160954362477SNico Weber     return FuncClass(FC_Private | FC_Static | FC_Far);
1610f435a7eaSZachary Turner   case 'E':
161103312863SZachary Turner     return FuncClass(FC_Private | FC_Virtual);
1612f435a7eaSZachary Turner   case 'F':
161354362477SNico Weber     return FuncClass(FC_Private | FC_Virtual | FC_Far);
161432a8a202SZachary Turner   case 'G':
161532a8a202SZachary Turner     return FuncClass(FC_Private | FC_StaticThisAdjust);
161632a8a202SZachary Turner   case 'H':
161732a8a202SZachary Turner     return FuncClass(FC_Private | FC_StaticThisAdjust | FC_Far);
1618f435a7eaSZachary Turner   case 'I':
161903312863SZachary Turner     return FuncClass(FC_Protected);
1620f435a7eaSZachary Turner   case 'J':
162103312863SZachary Turner     return FuncClass(FC_Protected | FC_Far);
1622f435a7eaSZachary Turner   case 'K':
162303312863SZachary Turner     return FuncClass(FC_Protected | FC_Static);
1624f435a7eaSZachary Turner   case 'L':
162503312863SZachary Turner     return FuncClass(FC_Protected | FC_Static | FC_Far);
1626f435a7eaSZachary Turner   case 'M':
162703312863SZachary Turner     return FuncClass(FC_Protected | FC_Virtual);
1628f435a7eaSZachary Turner   case 'N':
162903312863SZachary Turner     return FuncClass(FC_Protected | FC_Virtual | FC_Far);
1630469f0763SZachary Turner   case 'O':
163103312863SZachary Turner     return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust);
1632469f0763SZachary Turner   case 'P':
163303312863SZachary Turner     return FuncClass(FC_Protected | FC_Virtual | FC_StaticThisAdjust | FC_Far);
1634f435a7eaSZachary Turner   case 'Q':
163503312863SZachary Turner     return FuncClass(FC_Public);
1636f435a7eaSZachary Turner   case 'R':
163703312863SZachary Turner     return FuncClass(FC_Public | FC_Far);
1638f435a7eaSZachary Turner   case 'S':
163903312863SZachary Turner     return FuncClass(FC_Public | FC_Static);
1640f435a7eaSZachary Turner   case 'T':
164103312863SZachary Turner     return FuncClass(FC_Public | FC_Static | FC_Far);
1642f435a7eaSZachary Turner   case 'U':
164303312863SZachary Turner     return FuncClass(FC_Public | FC_Virtual);
1644f435a7eaSZachary Turner   case 'V':
164503312863SZachary Turner     return FuncClass(FC_Public | FC_Virtual | FC_Far);
1646469f0763SZachary Turner   case 'W':
164703312863SZachary Turner     return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust);
1648469f0763SZachary Turner   case 'X':
164903312863SZachary Turner     return FuncClass(FC_Public | FC_Virtual | FC_StaticThisAdjust | FC_Far);
1650f435a7eaSZachary Turner   case 'Y':
165103312863SZachary Turner     return FuncClass(FC_Global);
1652f435a7eaSZachary Turner   case 'Z':
165303312863SZachary Turner     return FuncClass(FC_Global | FC_Far);
1654469f0763SZachary Turner   case '$': {
165503312863SZachary Turner     FuncClass VFlag = FC_VirtualThisAdjust;
1656469f0763SZachary Turner     if (MangledName.consumeFront('R'))
165703312863SZachary Turner       VFlag = FuncClass(VFlag | FC_VirtualThisAdjustEx);
1658b4f33bbbSNico Weber     if (MangledName.empty())
1659b4f33bbbSNico Weber       break;
1660469f0763SZachary Turner     switch (MangledName.popFront()) {
1661469f0763SZachary Turner     case '0':
166203312863SZachary Turner       return FuncClass(FC_Private | FC_Virtual | VFlag);
1663469f0763SZachary Turner     case '1':
166403312863SZachary Turner       return FuncClass(FC_Private | FC_Virtual | VFlag | FC_Far);
1665469f0763SZachary Turner     case '2':
166603312863SZachary Turner       return FuncClass(FC_Protected | FC_Virtual | VFlag);
1667469f0763SZachary Turner     case '3':
166803312863SZachary Turner       return FuncClass(FC_Protected | FC_Virtual | VFlag | FC_Far);
1669469f0763SZachary Turner     case '4':
167003312863SZachary Turner       return FuncClass(FC_Public | FC_Virtual | VFlag);
1671469f0763SZachary Turner     case '5':
167203312863SZachary Turner       return FuncClass(FC_Public | FC_Virtual | VFlag | FC_Far);
1673469f0763SZachary Turner     }
1674469f0763SZachary Turner   }
1675f435a7eaSZachary Turner   }
1676f435a7eaSZachary Turner 
1677f435a7eaSZachary Turner   Error = true;
167803312863SZachary Turner   return FC_Public;
1679f435a7eaSZachary Turner }
1680f435a7eaSZachary Turner 
demangleCallingConvention(StringView & MangledName)1681316109b5SZachary Turner CallingConv Demangler::demangleCallingConvention(StringView &MangledName) {
168263b97d2aSNico Weber   if (MangledName.empty()) {
168363b97d2aSNico Weber     Error = true;
168463b97d2aSNico Weber     return CallingConv::None;
168563b97d2aSNico Weber   }
168663b97d2aSNico Weber 
1687f435a7eaSZachary Turner   switch (MangledName.popFront()) {
1688f435a7eaSZachary Turner   case 'A':
1689f435a7eaSZachary Turner   case 'B':
1690f435a7eaSZachary Turner     return CallingConv::Cdecl;
1691f435a7eaSZachary Turner   case 'C':
1692f435a7eaSZachary Turner   case 'D':
1693f435a7eaSZachary Turner     return CallingConv::Pascal;
1694f435a7eaSZachary Turner   case 'E':
1695f435a7eaSZachary Turner   case 'F':
1696f435a7eaSZachary Turner     return CallingConv::Thiscall;
1697f435a7eaSZachary Turner   case 'G':
1698f435a7eaSZachary Turner   case 'H':
1699f435a7eaSZachary Turner     return CallingConv::Stdcall;
1700f435a7eaSZachary Turner   case 'I':
1701f435a7eaSZachary Turner   case 'J':
1702f435a7eaSZachary Turner     return CallingConv::Fastcall;
1703f435a7eaSZachary Turner   case 'M':
1704f435a7eaSZachary Turner   case 'N':
1705f435a7eaSZachary Turner     return CallingConv::Clrcall;
1706f435a7eaSZachary Turner   case 'O':
1707f435a7eaSZachary Turner   case 'P':
1708f435a7eaSZachary Turner     return CallingConv::Eabi;
1709f435a7eaSZachary Turner   case 'Q':
1710f435a7eaSZachary Turner     return CallingConv::Vectorcall;
171144f79296SVarun Gandhi   case 'S':
171244f79296SVarun Gandhi     return CallingConv::Swift;
17139c2de238SSaleem Abdulrasool   case 'W':
171492dcb1d2SVarun Gandhi     return CallingConv::SwiftAsync;
1715f435a7eaSZachary Turner   }
1716f435a7eaSZachary Turner 
1717f435a7eaSZachary Turner   return CallingConv::None;
17180f2abd80SMartin Storsjo }
1719f435a7eaSZachary Turner 
demangleVariableStorageClass(StringView & MangledName)1720316109b5SZachary Turner StorageClass Demangler::demangleVariableStorageClass(StringView &MangledName) {
1721c1a0e6feSNico Weber   assert(MangledName.front() >= '0' && MangledName.front() <= '4');
1722f435a7eaSZachary Turner 
1723f435a7eaSZachary Turner   switch (MangledName.popFront()) {
1724f435a7eaSZachary Turner   case '0':
1725f435a7eaSZachary Turner     return StorageClass::PrivateStatic;
1726f435a7eaSZachary Turner   case '1':
1727f435a7eaSZachary Turner     return StorageClass::ProtectedStatic;
1728f435a7eaSZachary Turner   case '2':
1729f435a7eaSZachary Turner     return StorageClass::PublicStatic;
1730f435a7eaSZachary Turner   case '3':
1731f435a7eaSZachary Turner     return StorageClass::Global;
1732f435a7eaSZachary Turner   case '4':
1733f435a7eaSZachary Turner     return StorageClass::FunctionLocalStatic;
1734f435a7eaSZachary Turner   }
1735c1a0e6feSNico Weber   DEMANGLE_UNREACHABLE;
1736f435a7eaSZachary Turner }
1737f435a7eaSZachary Turner 
1738316109b5SZachary Turner std::pair<Qualifiers, bool>
demangleQualifiers(StringView & MangledName)1739316109b5SZachary Turner Demangler::demangleQualifiers(StringView &MangledName) {
174063b97d2aSNico Weber   if (MangledName.empty()) {
174163b97d2aSNico Weber     Error = true;
174263b97d2aSNico Weber     return std::make_pair(Q_None, false);
174363b97d2aSNico Weber   }
1744f435a7eaSZachary Turner 
1745f435a7eaSZachary Turner   switch (MangledName.popFront()) {
1746f435a7eaSZachary Turner   // Member qualifiers
1747f435a7eaSZachary Turner   case 'Q':
1748d742d645SZachary Turner     return std::make_pair(Q_None, true);
1749f435a7eaSZachary Turner   case 'R':
1750d742d645SZachary Turner     return std::make_pair(Q_Const, true);
1751f435a7eaSZachary Turner   case 'S':
1752d742d645SZachary Turner     return std::make_pair(Q_Volatile, true);
1753f435a7eaSZachary Turner   case 'T':
1754d742d645SZachary Turner     return std::make_pair(Qualifiers(Q_Const | Q_Volatile), true);
1755f435a7eaSZachary Turner   // Non-Member qualifiers
1756f435a7eaSZachary Turner   case 'A':
1757d742d645SZachary Turner     return std::make_pair(Q_None, false);
1758f435a7eaSZachary Turner   case 'B':
1759d742d645SZachary Turner     return std::make_pair(Q_Const, false);
1760f435a7eaSZachary Turner   case 'C':
1761d742d645SZachary Turner     return std::make_pair(Q_Volatile, false);
1762f435a7eaSZachary Turner   case 'D':
1763d742d645SZachary Turner     return std::make_pair(Qualifiers(Q_Const | Q_Volatile), false);
1764f435a7eaSZachary Turner   }
1765f435a7eaSZachary Turner   Error = true;
1766d742d645SZachary Turner   return std::make_pair(Q_None, false);
1767f435a7eaSZachary Turner }
1768f435a7eaSZachary Turner 
1769f435a7eaSZachary Turner // <variable-type> ::= <type> <cvr-qualifiers>
1770f435a7eaSZachary Turner //                 ::= <type> <pointee-cvr-qualifiers> # pointers, references
demangleType(StringView & MangledName,QualifierMangleMode QMM)177103312863SZachary Turner TypeNode *Demangler::demangleType(StringView &MangledName,
1772316109b5SZachary Turner                                   QualifierMangleMode QMM) {
1773f435a7eaSZachary Turner   Qualifiers Quals = Q_None;
1774d742d645SZachary Turner   bool IsMember = false;
1775d742d645SZachary Turner   if (QMM == QualifierMangleMode::Mangle) {
1776316109b5SZachary Turner     std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
1777d742d645SZachary Turner   } else if (QMM == QualifierMangleMode::Result) {
1778df4cd7cbSZachary Turner     if (MangledName.consumeFront('?'))
1779316109b5SZachary Turner       std::tie(Quals, IsMember) = demangleQualifiers(MangledName);
1780f435a7eaSZachary Turner   }
1781f435a7eaSZachary Turner 
178263b97d2aSNico Weber   if (MangledName.empty()) {
178363b97d2aSNico Weber     Error = true;
178463b97d2aSNico Weber     return nullptr;
178563b97d2aSNico Weber   }
178663b97d2aSNico Weber 
178703312863SZachary Turner   TypeNode *Ty = nullptr;
1788931e879cSZachary Turner   if (isTagType(MangledName))
1789316109b5SZachary Turner     Ty = demangleClassType(MangledName);
1790931e879cSZachary Turner   else if (isPointerType(MangledName)) {
17918fb9a71dSZachary Turner     if (isMemberPointer(MangledName, Error))
1792316109b5SZachary Turner       Ty = demangleMemberPointerType(MangledName);
17938fb9a71dSZachary Turner     else if (!Error)
1794316109b5SZachary Turner       Ty = demanglePointerType(MangledName);
17958fb9a71dSZachary Turner     else
17968fb9a71dSZachary Turner       return nullptr;
1797931e879cSZachary Turner   } else if (isArrayType(MangledName))
1798316109b5SZachary Turner     Ty = demangleArrayType(MangledName);
1799931e879cSZachary Turner   else if (isFunctionType(MangledName)) {
1800931e879cSZachary Turner     if (MangledName.consumeFront("$$A8@@"))
180103312863SZachary Turner       Ty = demangleFunctionType(MangledName, true);
1802931e879cSZachary Turner     else {
1803931e879cSZachary Turner       assert(MangledName.startsWith("$$A6"));
1804931e879cSZachary Turner       MangledName.consumeFront("$$A6");
180503312863SZachary Turner       Ty = demangleFunctionType(MangledName, false);
1806f435a7eaSZachary Turner     }
1807b2fef1a0SZachary Turner   } else if (isCustomType(MangledName)) {
1808b2fef1a0SZachary Turner     Ty = demangleCustomType(MangledName);
1809931e879cSZachary Turner   } else {
181003312863SZachary Turner     Ty = demanglePrimitiveType(MangledName);
1811931e879cSZachary Turner   }
1812931e879cSZachary Turner 
18132cd3286eSZachary Turner   if (!Ty || Error)
18142cd3286eSZachary Turner     return Ty;
1815f435a7eaSZachary Turner   Ty->Quals = Qualifiers(Ty->Quals | Quals);
1816f435a7eaSZachary Turner   return Ty;
1817f435a7eaSZachary Turner }
1818f435a7eaSZachary Turner 
demangleThrowSpecification(StringView & MangledName)18192fe49005SZachary Turner bool Demangler::demangleThrowSpecification(StringView &MangledName) {
18202fe49005SZachary Turner   if (MangledName.consumeFront("_E"))
18212fe49005SZachary Turner     return true;
182238b78a7fSZachary Turner   if (MangledName.consumeFront('Z'))
18232fe49005SZachary Turner     return false;
1824f435a7eaSZachary Turner 
182538b78a7fSZachary Turner   Error = true;
18262fe49005SZachary Turner   return false;
182738b78a7fSZachary Turner }
182838b78a7fSZachary Turner 
demangleFunctionType(StringView & MangledName,bool HasThisQuals)182903312863SZachary Turner FunctionSignatureNode *Demangler::demangleFunctionType(StringView &MangledName,
183003312863SZachary Turner                                                        bool HasThisQuals) {
183103312863SZachary Turner   FunctionSignatureNode *FTy = Arena.alloc<FunctionSignatureNode>();
183238b78a7fSZachary Turner 
183338b78a7fSZachary Turner   if (HasThisQuals) {
1834316109b5SZachary Turner     FTy->Quals = demanglePointerExtQualifiers(MangledName);
183503312863SZachary Turner     FTy->RefQualifier = demangleFunctionRefQualifier(MangledName);
1836316109b5SZachary Turner     FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers(MangledName).first);
1837f435a7eaSZachary Turner   }
1838f435a7eaSZachary Turner 
1839f435a7eaSZachary Turner   // Fields that appear on both member and non-member functions.
1840316109b5SZachary Turner   FTy->CallConvention = demangleCallingConvention(MangledName);
1841f435a7eaSZachary Turner 
1842f435a7eaSZachary Turner   // <return-type> ::= <type>
1843f435a7eaSZachary Turner   //               ::= @ # structors (they have no declared return type)
1844f435a7eaSZachary Turner   bool IsStructor = MangledName.consumeFront('@');
1845f435a7eaSZachary Turner   if (!IsStructor)
1846316109b5SZachary Turner     FTy->ReturnType = demangleType(MangledName, QualifierMangleMode::Result);
1847f435a7eaSZachary Turner 
18481dce8263SNico Weber   FTy->Params = demangleFunctionParameterList(MangledName, FTy->IsVariadic);
1849f435a7eaSZachary Turner 
18502fe49005SZachary Turner   FTy->IsNoexcept = demangleThrowSpecification(MangledName);
185138b78a7fSZachary Turner 
185238b78a7fSZachary Turner   return FTy;
185338b78a7fSZachary Turner }
185438b78a7fSZachary Turner 
185503312863SZachary Turner FunctionSymbolNode *
demangleFunctionEncoding(StringView & MangledName)185603312863SZachary Turner Demangler::demangleFunctionEncoding(StringView &MangledName) {
185703312863SZachary Turner   FuncClass ExtraFlags = FC_None;
1858469f0763SZachary Turner   if (MangledName.consumeFront("$$J0"))
185903312863SZachary Turner     ExtraFlags = FC_ExternC;
1860469f0763SZachary Turner 
186163b97d2aSNico Weber   if (MangledName.empty()) {
186263b97d2aSNico Weber     Error = true;
186363b97d2aSNico Weber     return nullptr;
186463b97d2aSNico Weber   }
186563b97d2aSNico Weber 
1866316109b5SZachary Turner   FuncClass FC = demangleFunctionClass(MangledName);
1867469f0763SZachary Turner   FC = FuncClass(ExtraFlags | FC);
1868469f0763SZachary Turner 
186903312863SZachary Turner   FunctionSignatureNode *FSN = nullptr;
187003312863SZachary Turner   ThunkSignatureNode *TTN = nullptr;
187103312863SZachary Turner   if (FC & FC_StaticThisAdjust) {
187203312863SZachary Turner     TTN = Arena.alloc<ThunkSignatureNode>();
187303312863SZachary Turner     TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName);
187403312863SZachary Turner   } else if (FC & FC_VirtualThisAdjust) {
187503312863SZachary Turner     TTN = Arena.alloc<ThunkSignatureNode>();
187603312863SZachary Turner     if (FC & FC_VirtualThisAdjustEx) {
187703312863SZachary Turner       TTN->ThisAdjust.VBPtrOffset = demangleSigned(MangledName);
187803312863SZachary Turner       TTN->ThisAdjust.VBOffsetOffset = demangleSigned(MangledName);
1879469f0763SZachary Turner     }
188003312863SZachary Turner     TTN->ThisAdjust.VtordispOffset = demangleSigned(MangledName);
188103312863SZachary Turner     TTN->ThisAdjust.StaticOffset = demangleSigned(MangledName);
1882469f0763SZachary Turner   }
1883469f0763SZachary Turner 
188403312863SZachary Turner   if (FC & FC_NoParameterList) {
188529ec67b6SZachary Turner     // This is an extern "C" function whose full signature hasn't been mangled.
188629ec67b6SZachary Turner     // This happens when we need to mangle a local symbol inside of an extern
188729ec67b6SZachary Turner     // "C" function.
188803312863SZachary Turner     FSN = Arena.alloc<FunctionSignatureNode>();
188929ec67b6SZachary Turner   } else {
189003312863SZachary Turner     bool HasThisQuals = !(FC & (FC_Global | FC_Static));
189103312863SZachary Turner     FSN = demangleFunctionType(MangledName, HasThisQuals);
189229ec67b6SZachary Turner   }
189363b97d2aSNico Weber 
189463b97d2aSNico Weber   if (Error)
189563b97d2aSNico Weber     return nullptr;
189663b97d2aSNico Weber 
189703312863SZachary Turner   if (TTN) {
189803312863SZachary Turner     *static_cast<FunctionSignatureNode *>(TTN) = *FSN;
189903312863SZachary Turner     FSN = TTN;
190003312863SZachary Turner   }
190103312863SZachary Turner   FSN->FunctionClass = FC;
190238b78a7fSZachary Turner 
190303312863SZachary Turner   FunctionSymbolNode *Symbol = Arena.alloc<FunctionSymbolNode>();
190403312863SZachary Turner   Symbol->Signature = FSN;
190503312863SZachary Turner   return Symbol;
1906f435a7eaSZachary Turner }
1907f435a7eaSZachary Turner 
demangleCustomType(StringView & MangledName)1908b2fef1a0SZachary Turner CustomTypeNode *Demangler::demangleCustomType(StringView &MangledName) {
1909b2fef1a0SZachary Turner   assert(MangledName.startsWith('?'));
1910b2fef1a0SZachary Turner   MangledName.popFront();
1911b2fef1a0SZachary Turner 
1912b2fef1a0SZachary Turner   CustomTypeNode *CTN = Arena.alloc<CustomTypeNode>();
1913af2ee7d0SNico Weber   CTN->Identifier = demangleUnqualifiedTypeName(MangledName, /*Memorize=*/true);
1914b2fef1a0SZachary Turner   if (!MangledName.consumeFront('@'))
1915b2fef1a0SZachary Turner     Error = true;
1916b2fef1a0SZachary Turner   if (Error)
1917b2fef1a0SZachary Turner     return nullptr;
1918b2fef1a0SZachary Turner   return CTN;
1919b2fef1a0SZachary Turner }
1920b2fef1a0SZachary Turner 
1921f435a7eaSZachary Turner // Reads a primitive type.
demanglePrimitiveType(StringView & MangledName)192203312863SZachary Turner PrimitiveTypeNode *Demangler::demanglePrimitiveType(StringView &MangledName) {
192303312863SZachary Turner   if (MangledName.consumeFront("$$T"))
192403312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Nullptr);
1925931e879cSZachary Turner 
1926f435a7eaSZachary Turner   switch (MangledName.popFront()) {
1927f435a7eaSZachary Turner   case 'X':
192803312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Void);
1929f435a7eaSZachary Turner   case 'D':
193003312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char);
1931f435a7eaSZachary Turner   case 'C':
193203312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Schar);
1933f435a7eaSZachary Turner   case 'E':
193403312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uchar);
1935f435a7eaSZachary Turner   case 'F':
193603312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Short);
1937f435a7eaSZachary Turner   case 'G':
193803312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ushort);
1939f435a7eaSZachary Turner   case 'H':
194003312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int);
1941f435a7eaSZachary Turner   case 'I':
194203312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint);
1943f435a7eaSZachary Turner   case 'J':
194403312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Long);
1945f435a7eaSZachary Turner   case 'K':
194603312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ulong);
1947f435a7eaSZachary Turner   case 'M':
194803312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Float);
1949f435a7eaSZachary Turner   case 'N':
195003312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Double);
1951f435a7eaSZachary Turner   case 'O':
195203312863SZachary Turner     return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Ldouble);
1953f435a7eaSZachary Turner   case '_': {
195491ecedd2SZachary Turner     if (MangledName.empty()) {
195591ecedd2SZachary Turner       Error = true;
195691ecedd2SZachary Turner       return nullptr;
195791ecedd2SZachary Turner     }
1958f435a7eaSZachary Turner     switch (MangledName.popFront()) {
1959f435a7eaSZachary Turner     case 'N':
196003312863SZachary Turner       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Bool);
1961f435a7eaSZachary Turner     case 'J':
196203312863SZachary Turner       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Int64);
1963f435a7eaSZachary Turner     case 'K':
196403312863SZachary Turner       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Uint64);
1965f435a7eaSZachary Turner     case 'W':
196603312863SZachary Turner       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Wchar);
1967a2ca6e78SNico Weber     case 'Q':
1968a2ca6e78SNico Weber       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char8);
1969931e879cSZachary Turner     case 'S':
197003312863SZachary Turner       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char16);
1971931e879cSZachary Turner     case 'U':
197203312863SZachary Turner       return Arena.alloc<PrimitiveTypeNode>(PrimitiveKind::Char32);
1973f435a7eaSZachary Turner     }
1974f435a7eaSZachary Turner     break;
1975f435a7eaSZachary Turner   }
197603312863SZachary Turner   }
1977931e879cSZachary Turner   Error = true;
1978931e879cSZachary Turner   return nullptr;
1979f435a7eaSZachary Turner }
1980f435a7eaSZachary Turner 
demangleClassType(StringView & MangledName)198103312863SZachary Turner TagTypeNode *Demangler::demangleClassType(StringView &MangledName) {
198203312863SZachary Turner   TagTypeNode *TT = nullptr;
1983f435a7eaSZachary Turner 
1984f435a7eaSZachary Turner   switch (MangledName.popFront()) {
1985f435a7eaSZachary Turner   case 'T':
198603312863SZachary Turner     TT = Arena.alloc<TagTypeNode>(TagKind::Union);
1987f435a7eaSZachary Turner     break;
1988f435a7eaSZachary Turner   case 'U':
198903312863SZachary Turner     TT = Arena.alloc<TagTypeNode>(TagKind::Struct);
1990f435a7eaSZachary Turner     break;
1991f435a7eaSZachary Turner   case 'V':
199203312863SZachary Turner     TT = Arena.alloc<TagTypeNode>(TagKind::Class);
1993f435a7eaSZachary Turner     break;
1994f435a7eaSZachary Turner   case 'W':
1995e5b62654SNico Weber     if (!MangledName.consumeFront('4')) {
1996f435a7eaSZachary Turner       Error = true;
1997f435a7eaSZachary Turner       return nullptr;
1998f435a7eaSZachary Turner     }
199903312863SZachary Turner     TT = Arena.alloc<TagTypeNode>(TagKind::Enum);
2000f435a7eaSZachary Turner     break;
2001f435a7eaSZachary Turner   default:
2002f435a7eaSZachary Turner     assert(false);
2003f435a7eaSZachary Turner   }
2004f435a7eaSZachary Turner 
200503312863SZachary Turner   TT->QualifiedName = demangleFullyQualifiedTypeName(MangledName);
200603312863SZachary Turner   return TT;
2007d742d645SZachary Turner }
2008d742d645SZachary Turner 
2009f435a7eaSZachary Turner // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type>
2010f435a7eaSZachary Turner //                       # the E is required for 64-bit non-static pointers
demanglePointerType(StringView & MangledName)201103312863SZachary Turner PointerTypeNode *Demangler::demanglePointerType(StringView &MangledName) {
201203312863SZachary Turner   PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>();
2013f435a7eaSZachary Turner 
2014931e879cSZachary Turner   std::tie(Pointer->Quals, Pointer->Affinity) =
2015931e879cSZachary Turner       demanglePointerCVQualifiers(MangledName);
2016f435a7eaSZachary Turner 
2017f435a7eaSZachary Turner   if (MangledName.consumeFront("6")) {
201803312863SZachary Turner     Pointer->Pointee = demangleFunctionType(MangledName, false);
2019f435a7eaSZachary Turner     return Pointer;
2020f435a7eaSZachary Turner   }
2021f435a7eaSZachary Turner 
2022316109b5SZachary Turner   Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
2023f435a7eaSZachary Turner   Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
2024f435a7eaSZachary Turner 
2025316109b5SZachary Turner   Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Mangle);
2026f435a7eaSZachary Turner   return Pointer;
2027f435a7eaSZachary Turner }
2028f435a7eaSZachary Turner 
demangleMemberPointerType(StringView & MangledName)202903312863SZachary Turner PointerTypeNode *Demangler::demangleMemberPointerType(StringView &MangledName) {
203003312863SZachary Turner   PointerTypeNode *Pointer = Arena.alloc<PointerTypeNode>();
2031d742d645SZachary Turner 
203203312863SZachary Turner   std::tie(Pointer->Quals, Pointer->Affinity) =
203303312863SZachary Turner       demanglePointerCVQualifiers(MangledName);
203403312863SZachary Turner   assert(Pointer->Affinity == PointerAffinity::Pointer);
2035d742d645SZachary Turner 
2036316109b5SZachary Turner   Qualifiers ExtQuals = demanglePointerExtQualifiers(MangledName);
2037d742d645SZachary Turner   Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
2038d742d645SZachary Turner 
203963b97d2aSNico Weber   // isMemberPointer() only returns true if there is at least one character
204063b97d2aSNico Weber   // after the qualifiers.
204138b78a7fSZachary Turner   if (MangledName.consumeFront("8")) {
204232a8a202SZachary Turner     Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
204303312863SZachary Turner     Pointer->Pointee = demangleFunctionType(MangledName, true);
204438b78a7fSZachary Turner   } else {
2045d742d645SZachary Turner     Qualifiers PointeeQuals = Q_None;
2046d742d645SZachary Turner     bool IsMember = false;
2047316109b5SZachary Turner     std::tie(PointeeQuals, IsMember) = demangleQualifiers(MangledName);
204863b97d2aSNico Weber     assert(IsMember || Error);
204932a8a202SZachary Turner     Pointer->ClassParent = demangleFullyQualifiedTypeName(MangledName);
2050d742d645SZachary Turner 
2051316109b5SZachary Turner     Pointer->Pointee = demangleType(MangledName, QualifierMangleMode::Drop);
205263b97d2aSNico Weber     if (Pointer->Pointee)
2053d742d645SZachary Turner       Pointer->Pointee->Quals = PointeeQuals;
205438b78a7fSZachary Turner   }
205538b78a7fSZachary Turner 
2056d742d645SZachary Turner   return Pointer;
2057d742d645SZachary Turner }
2058d742d645SZachary Turner 
demanglePointerExtQualifiers(StringView & MangledName)2059316109b5SZachary Turner Qualifiers Demangler::demanglePointerExtQualifiers(StringView &MangledName) {
2060f435a7eaSZachary Turner   Qualifiers Quals = Q_None;
2061f435a7eaSZachary Turner   if (MangledName.consumeFront('E'))
2062f435a7eaSZachary Turner     Quals = Qualifiers(Quals | Q_Pointer64);
2063f435a7eaSZachary Turner   if (MangledName.consumeFront('I'))
2064f435a7eaSZachary Turner     Quals = Qualifiers(Quals | Q_Restrict);
2065f435a7eaSZachary Turner   if (MangledName.consumeFront('F'))
2066f435a7eaSZachary Turner     Quals = Qualifiers(Quals | Q_Unaligned);
2067f435a7eaSZachary Turner 
2068f435a7eaSZachary Turner   return Quals;
2069f435a7eaSZachary Turner }
2070f435a7eaSZachary Turner 
demangleArrayType(StringView & MangledName)207103312863SZachary Turner ArrayTypeNode *Demangler::demangleArrayType(StringView &MangledName) {
2072f435a7eaSZachary Turner   assert(MangledName.front() == 'Y');
2073f435a7eaSZachary Turner   MangledName.popFront();
2074f435a7eaSZachary Turner 
2075dbefc6cdSZachary Turner   uint64_t Rank = 0;
2076dbefc6cdSZachary Turner   bool IsNegative = false;
2077dbefc6cdSZachary Turner   std::tie(Rank, IsNegative) = demangleNumber(MangledName);
2078dbefc6cdSZachary Turner   if (IsNegative || Rank == 0) {
2079f435a7eaSZachary Turner     Error = true;
2080f435a7eaSZachary Turner     return nullptr;
2081f435a7eaSZachary Turner   }
2082f435a7eaSZachary Turner 
208303312863SZachary Turner   ArrayTypeNode *ATy = Arena.alloc<ArrayTypeNode>();
208403312863SZachary Turner   NodeList *Head = Arena.alloc<NodeList>();
208503312863SZachary Turner   NodeList *Tail = Head;
208603312863SZachary Turner 
2087dbefc6cdSZachary Turner   for (uint64_t I = 0; I < Rank; ++I) {
208803312863SZachary Turner     uint64_t D = 0;
208903312863SZachary Turner     std::tie(D, IsNegative) = demangleNumber(MangledName);
20901672581eSNico Weber     if (Error || IsNegative) {
2091dbefc6cdSZachary Turner       Error = true;
2092dbefc6cdSZachary Turner       return nullptr;
2093dbefc6cdSZachary Turner     }
209403312863SZachary Turner     Tail->N = Arena.alloc<IntegerLiteralNode>(D, IsNegative);
2095dbefc6cdSZachary Turner     if (I + 1 < Rank) {
209603312863SZachary Turner       Tail->Next = Arena.alloc<NodeList>();
209703312863SZachary Turner       Tail = Tail->Next;
2098dbefc6cdSZachary Turner     }
2099f435a7eaSZachary Turner   }
210003312863SZachary Turner   ATy->Dimensions = nodeListToNodeArray(Arena, Head, Rank);
2101f435a7eaSZachary Turner 
2102f435a7eaSZachary Turner   if (MangledName.consumeFront("$$C")) {
21032bbb23baSZachary Turner     bool IsMember = false;
21042bbb23baSZachary Turner     std::tie(ATy->Quals, IsMember) = demangleQualifiers(MangledName);
21052bbb23baSZachary Turner     if (IsMember) {
2106f435a7eaSZachary Turner       Error = true;
21072bbb23baSZachary Turner       return nullptr;
21082bbb23baSZachary Turner     }
2109f435a7eaSZachary Turner   }
2110f435a7eaSZachary Turner 
2111316109b5SZachary Turner   ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop);
2112f435a7eaSZachary Turner   return ATy;
2113f435a7eaSZachary Turner }
2114f435a7eaSZachary Turner 
211546385484SNico Weber // Reads a function's parameters.
demangleFunctionParameterList(StringView & MangledName,bool & IsVariadic)21161dce8263SNico Weber NodeArrayNode *Demangler::demangleFunctionParameterList(StringView &MangledName,
21171dce8263SNico Weber                                                         bool &IsVariadic) {
211838b78a7fSZachary Turner   // Empty parameter list.
211938b78a7fSZachary Turner   if (MangledName.consumeFront('X'))
2120930994ceSNico Weber     return nullptr;
212138b78a7fSZachary Turner 
212203312863SZachary Turner   NodeList *Head = Arena.alloc<NodeList>();
212303312863SZachary Turner   NodeList **Current = &Head;
212403312863SZachary Turner   size_t Count = 0;
2125f435a7eaSZachary Turner   while (!Error && !MangledName.startsWith('@') &&
2126f435a7eaSZachary Turner          !MangledName.startsWith('Z')) {
212703312863SZachary Turner     ++Count;
212823df1319SZachary Turner 
2129f435a7eaSZachary Turner     if (startsWithDigit(MangledName)) {
213030375de9SZachary Turner       size_t N = MangledName[0] - '0';
2131d346cba9SZachary Turner       if (N >= Backrefs.FunctionParamCount) {
2132f435a7eaSZachary Turner         Error = true;
2133930994ceSNico Weber         return nullptr;
2134f435a7eaSZachary Turner       }
2135f435a7eaSZachary Turner       MangledName = MangledName.dropFront();
2136f435a7eaSZachary Turner 
213703312863SZachary Turner       *Current = Arena.alloc<NodeList>();
213803312863SZachary Turner       (*Current)->N = Backrefs.FunctionParams[N];
2139f435a7eaSZachary Turner       Current = &(*Current)->Next;
2140f435a7eaSZachary Turner       continue;
2141f435a7eaSZachary Turner     }
2142f435a7eaSZachary Turner 
214323df1319SZachary Turner     size_t OldSize = MangledName.size();
2144f435a7eaSZachary Turner 
214503312863SZachary Turner     *Current = Arena.alloc<NodeList>();
214603312863SZachary Turner     TypeNode *TN = demangleType(MangledName, QualifierMangleMode::Drop);
21478fb9a71dSZachary Turner     if (!TN || Error)
21488fb9a71dSZachary Turner       return nullptr;
214903312863SZachary Turner 
215003312863SZachary Turner     (*Current)->N = TN;
2151f435a7eaSZachary Turner 
215223df1319SZachary Turner     size_t CharsConsumed = OldSize - MangledName.size();
215323df1319SZachary Turner     assert(CharsConsumed != 0);
215423df1319SZachary Turner 
215523df1319SZachary Turner     // Single-letter types are ignored for backreferences because memorizing
215623df1319SZachary Turner     // them doesn't save anything.
2157d346cba9SZachary Turner     if (Backrefs.FunctionParamCount <= 9 && CharsConsumed > 1)
215803312863SZachary Turner       Backrefs.FunctionParams[Backrefs.FunctionParamCount++] = TN;
215923df1319SZachary Turner 
2160f435a7eaSZachary Turner     Current = &(*Current)->Next;
2161f435a7eaSZachary Turner   }
2162f435a7eaSZachary Turner 
216338b78a7fSZachary Turner   if (Error)
2164930994ceSNico Weber     return nullptr;
216538b78a7fSZachary Turner 
216603312863SZachary Turner   NodeArrayNode *NA = nodeListToNodeArray(Arena, Head, Count);
216738b78a7fSZachary Turner   // A non-empty parameter list is terminated by either 'Z' (variadic) parameter
216838b78a7fSZachary Turner   // list or '@' (non variadic).  Careful not to consume "@Z", as in that case
216938b78a7fSZachary Turner   // the following Z could be a throw specifier.
217038b78a7fSZachary Turner   if (MangledName.consumeFront('@'))
217103312863SZachary Turner     return NA;
217238b78a7fSZachary Turner 
217338b78a7fSZachary Turner   if (MangledName.consumeFront('Z')) {
21741dce8263SNico Weber     IsVariadic = true;
217503312863SZachary Turner     return NA;
217638b78a7fSZachary Turner   }
217738b78a7fSZachary Turner 
217846385484SNico Weber   DEMANGLE_UNREACHABLE;
2179f435a7eaSZachary Turner }
2180f435a7eaSZachary Turner 
218103312863SZachary Turner NodeArrayNode *
demangleTemplateParameterList(StringView & MangledName)2182d30700f8SZachary Turner Demangler::demangleTemplateParameterList(StringView &MangledName) {
2183d2a3e898SSimon Pilgrim   NodeList *Head = nullptr;
218403312863SZachary Turner   NodeList **Current = &Head;
218503312863SZachary Turner   size_t Count = 0;
218603312863SZachary Turner 
218746385484SNico Weber   while (!MangledName.startsWith('@')) {
218832a8a202SZachary Turner     if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
218978ab3cb2SZachary Turner         MangledName.consumeFront("$$$V") || MangledName.consumeFront("$$Z")) {
219078ab3cb2SZachary Turner       // parameter pack separator
219132a8a202SZachary Turner       continue;
219232a8a202SZachary Turner     }
219332a8a202SZachary Turner 
219403312863SZachary Turner     ++Count;
219532a8a202SZachary Turner 
219623df1319SZachary Turner     // Template parameter lists don't participate in back-referencing.
219703312863SZachary Turner     *Current = Arena.alloc<NodeList>();
2198931e879cSZachary Turner 
219903312863SZachary Turner     NodeList &TP = **Current;
220066555a7bSZachary Turner 
220103312863SZachary Turner     TemplateParameterReferenceNode *TPRN = nullptr;
220232a8a202SZachary Turner     if (MangledName.consumeFront("$$Y")) {
2203dbefc6cdSZachary Turner       // Template alias
220403312863SZachary Turner       TP.N = demangleFullyQualifiedTypeName(MangledName);
2205dbefc6cdSZachary Turner     } else if (MangledName.consumeFront("$$B")) {
2206dbefc6cdSZachary Turner       // Array
220703312863SZachary Turner       TP.N = demangleType(MangledName, QualifierMangleMode::Drop);
2208073620bcSZachary Turner     } else if (MangledName.consumeFront("$$C")) {
2209073620bcSZachary Turner       // Type has qualifiers.
221003312863SZachary Turner       TP.N = demangleType(MangledName, QualifierMangleMode::Mangle);
221166555a7bSZachary Turner     } else if (MangledName.startsWith("$1") || MangledName.startsWith("$H") ||
221266555a7bSZachary Turner                MangledName.startsWith("$I") || MangledName.startsWith("$J")) {
221303312863SZachary Turner       // Pointer to member
221403312863SZachary Turner       TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
221503312863SZachary Turner       TPRN->IsMemberPointer = true;
221603312863SZachary Turner 
221766555a7bSZachary Turner       MangledName = MangledName.dropFront();
221866555a7bSZachary Turner       // 1 - single inheritance       <name>
221966555a7bSZachary Turner       // H - multiple inheritance     <name> <number>
2220880d21d3SNico Weber       // I - virtual inheritance      <name> <number> <number>
222166555a7bSZachary Turner       // J - unspecified inheritance  <name> <number> <number> <number>
222266555a7bSZachary Turner       char InheritanceSpecifier = MangledName.popFront();
2223b2fef1a0SZachary Turner       SymbolNode *S = nullptr;
2224b2fef1a0SZachary Turner       if (MangledName.startsWith('?')) {
2225b2fef1a0SZachary Turner         S = parse(MangledName);
222609fb2029SNico Weber         if (Error || !S->Name) {
222709fb2029SNico Weber           Error = true;
2228f2d8f09dSNico Weber           return nullptr;
222909fb2029SNico Weber         }
2230b2fef1a0SZachary Turner         memorizeIdentifier(S->Name->getUnqualifiedIdentifier());
2231b2fef1a0SZachary Turner       }
2232b2fef1a0SZachary Turner 
223366555a7bSZachary Turner       switch (InheritanceSpecifier) {
223466555a7bSZachary Turner       case 'J':
223503312863SZachary Turner         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
223603312863SZachary Turner             demangleSigned(MangledName);
22375094e5efSErik Pilkington         DEMANGLE_FALLTHROUGH;
223866555a7bSZachary Turner       case 'I':
223903312863SZachary Turner         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
224003312863SZachary Turner             demangleSigned(MangledName);
22415094e5efSErik Pilkington         DEMANGLE_FALLTHROUGH;
224266555a7bSZachary Turner       case 'H':
224303312863SZachary Turner         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
224403312863SZachary Turner             demangleSigned(MangledName);
22455094e5efSErik Pilkington         DEMANGLE_FALLTHROUGH;
224666555a7bSZachary Turner       case '1':
224766555a7bSZachary Turner         break;
224866555a7bSZachary Turner       default:
2249880d21d3SNico Weber         DEMANGLE_UNREACHABLE;
225066555a7bSZachary Turner       }
225103312863SZachary Turner       TPRN->Affinity = PointerAffinity::Pointer;
225203312863SZachary Turner       TPRN->Symbol = S;
2253dbefc6cdSZachary Turner     } else if (MangledName.startsWith("$E?")) {
2254dbefc6cdSZachary Turner       MangledName.consumeFront("$E");
2255dbefc6cdSZachary Turner       // Reference to symbol
225603312863SZachary Turner       TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
225703312863SZachary Turner       TPRN->Symbol = parse(MangledName);
225803312863SZachary Turner       TPRN->Affinity = PointerAffinity::Reference;
225966555a7bSZachary Turner     } else if (MangledName.startsWith("$F") || MangledName.startsWith("$G")) {
226003312863SZachary Turner       TP.N = TPRN = Arena.alloc<TemplateParameterReferenceNode>();
226103312863SZachary Turner 
226266555a7bSZachary Turner       // Data member pointer.
226366555a7bSZachary Turner       MangledName = MangledName.dropFront();
226466555a7bSZachary Turner       char InheritanceSpecifier = MangledName.popFront();
226566555a7bSZachary Turner 
226666555a7bSZachary Turner       switch (InheritanceSpecifier) {
226766555a7bSZachary Turner       case 'G':
226803312863SZachary Turner         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
226903312863SZachary Turner             demangleSigned(MangledName);
22705094e5efSErik Pilkington         DEMANGLE_FALLTHROUGH;
227166555a7bSZachary Turner       case 'F':
227203312863SZachary Turner         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
227303312863SZachary Turner             demangleSigned(MangledName);
227403312863SZachary Turner         TPRN->ThunkOffsets[TPRN->ThunkOffsetCount++] =
227503312863SZachary Turner             demangleSigned(MangledName);
227666555a7bSZachary Turner         break;
227766555a7bSZachary Turner       default:
2278880d21d3SNico Weber         DEMANGLE_UNREACHABLE;
227966555a7bSZachary Turner       }
228003312863SZachary Turner       TPRN->IsMemberPointer = true;
228166555a7bSZachary Turner 
2282dbefc6cdSZachary Turner     } else if (MangledName.consumeFront("$0")) {
2283dbefc6cdSZachary Turner       // Integral non-type template parameter
2284dbefc6cdSZachary Turner       bool IsNegative = false;
2285dbefc6cdSZachary Turner       uint64_t Value = 0;
2286dbefc6cdSZachary Turner       std::tie(Value, IsNegative) = demangleNumber(MangledName);
2287dbefc6cdSZachary Turner 
228803312863SZachary Turner       TP.N = Arena.alloc<IntegerLiteralNode>(Value, IsNegative);
2289d30700f8SZachary Turner     } else {
229003312863SZachary Turner       TP.N = demangleType(MangledName, QualifierMangleMode::Drop);
2291d30700f8SZachary Turner     }
229254d4ffe5SZachary Turner     if (Error)
229354d4ffe5SZachary Turner       return nullptr;
229423df1319SZachary Turner 
229566555a7bSZachary Turner     Current = &TP.Next;
229623df1319SZachary Turner   }
229723df1319SZachary Turner 
229846385484SNico Weber   // The loop above returns nullptr on Error.
229946385484SNico Weber   assert(!Error);
230023df1319SZachary Turner 
230123df1319SZachary Turner   // Template parameter lists cannot be variadic, so it can only be terminated
230246385484SNico Weber   // by @ (as opposed to 'Z' in the function parameter case).
230346385484SNico Weber   assert(MangledName.startsWith('@')); // The above loop exits only on '@'.
230446385484SNico Weber   MangledName.consumeFront('@');
230503312863SZachary Turner   return nodeListToNodeArray(Arena, Head, Count);
230623df1319SZachary Turner }
230723df1319SZachary Turner 
dumpBackReferences()23083a758e22SZachary Turner void Demangler::dumpBackReferences() {
23095ae08b85SZachary Turner   std::printf("%d function parameter backreferences\n",
2310d346cba9SZachary Turner               (int)Backrefs.FunctionParamCount);
23113a758e22SZachary Turner 
23123a758e22SZachary Turner   // Create an output stream so we can render each type.
23132e97236aSLuís Ferreira   OutputBuffer OB;
2314aabeb5ebSKirill Stoimenov   if (!initializeOutputBuffer(nullptr, nullptr, OB, 1024))
2315aabeb5ebSKirill Stoimenov     std::terminate();
2316d346cba9SZachary Turner   for (size_t I = 0; I < Backrefs.FunctionParamCount; ++I) {
23172e97236aSLuís Ferreira     OB.setCurrentPosition(0);
23183a758e22SZachary Turner 
231903312863SZachary Turner     TypeNode *T = Backrefs.FunctionParams[I];
23202e97236aSLuís Ferreira     T->output(OB, OF_Default);
23213a758e22SZachary Turner 
23221066e397SNathan Sidwell     StringView B = OB;
23231066e397SNathan Sidwell     std::printf("  [%d] - %.*s\n", (int)I, (int)B.size(), B.begin());
23243a758e22SZachary Turner   }
23252e97236aSLuís Ferreira   std::free(OB.getBuffer());
23263a758e22SZachary Turner 
2327d346cba9SZachary Turner   if (Backrefs.FunctionParamCount > 0)
23285ae08b85SZachary Turner     std::printf("\n");
2329d346cba9SZachary Turner   std::printf("%d name backreferences\n", (int)Backrefs.NamesCount);
2330d346cba9SZachary Turner   for (size_t I = 0; I < Backrefs.NamesCount; ++I) {
233103312863SZachary Turner     std::printf("  [%d] - %.*s\n", (int)I, (int)Backrefs.Names[I]->Name.size(),
233203312863SZachary Turner                 Backrefs.Names[I]->Name.begin());
23333a758e22SZachary Turner   }
2334d346cba9SZachary Turner   if (Backrefs.NamesCount > 0)
23355ae08b85SZachary Turner     std::printf("\n");
23363a758e22SZachary Turner }
23373a758e22SZachary Turner 
microsoftDemangle(const char * MangledName,size_t * NMangled,char * Buf,size_t * N,int * Status,MSDemangleFlags Flags)2338bc1c3655SNico Weber char *llvm::microsoftDemangle(const char *MangledName, size_t *NMangled,
2339bc1c3655SNico Weber                               char *Buf, size_t *N,
23403a758e22SZachary Turner                               int *Status, MSDemangleFlags Flags) {
2341316109b5SZachary Turner   Demangler D;
2342aabeb5ebSKirill Stoimenov   OutputBuffer OB;
23431359d654SNico Weber 
2344316109b5SZachary Turner   StringView Name{MangledName};
23451359d654SNico Weber   SymbolNode *AST = D.parse(Name);
2346bc1c3655SNico Weber   if (!D.Error && NMangled)
2347bc1c3655SNico Weber     *NMangled = Name.begin() - MangledName;
2348f435a7eaSZachary Turner 
23493a758e22SZachary Turner   if (Flags & MSDF_DumpBackrefs)
23503a758e22SZachary Turner     D.dumpBackReferences();
23511359d654SNico Weber 
2352da92ed83SMartin Storsjo   OutputFlags OF = OF_Default;
2353da92ed83SMartin Storsjo   if (Flags & MSDF_NoCallingConvention)
2354da92ed83SMartin Storsjo     OF = OutputFlags(OF | OF_NoCallingConvention);
2355da92ed83SMartin Storsjo   if (Flags & MSDF_NoAccessSpecifier)
2356da92ed83SMartin Storsjo     OF = OutputFlags(OF | OF_NoAccessSpecifier);
2357da92ed83SMartin Storsjo   if (Flags & MSDF_NoReturnType)
2358da92ed83SMartin Storsjo     OF = OutputFlags(OF | OF_NoReturnType);
2359da92ed83SMartin Storsjo   if (Flags & MSDF_NoMemberType)
2360da92ed83SMartin Storsjo     OF = OutputFlags(OF | OF_NoMemberType);
2361134e1817SLasse Folger   if (Flags & MSDF_NoVariableType)
2362134e1817SLasse Folger     OF = OutputFlags(OF | OF_NoVariableType);
2363da92ed83SMartin Storsjo 
2364bc1c3655SNico Weber   int InternalStatus = demangle_success;
23651359d654SNico Weber   if (D.Error)
23661359d654SNico Weber     InternalStatus = demangle_invalid_mangled_name;
2367aabeb5ebSKirill Stoimenov   else if (!initializeOutputBuffer(Buf, N, OB, 1024))
2368aabeb5ebSKirill Stoimenov     InternalStatus = demangle_memory_alloc_failure;
23691359d654SNico Weber   else {
23702e97236aSLuís Ferreira     AST->output(OB, OF);
23712e97236aSLuís Ferreira     OB += '\0';
23721359d654SNico Weber     if (N != nullptr)
23732e97236aSLuís Ferreira       *N = OB.getCurrentPosition();
23742e97236aSLuís Ferreira     Buf = OB.getBuffer();
237554d4ffe5SZachary Turner   }
237654d4ffe5SZachary Turner 
23771359d654SNico Weber   if (Status)
23781359d654SNico Weber     *Status = InternalStatus;
23791359d654SNico Weber   return InternalStatus == demangle_success ? Buf : nullptr;
2380f435a7eaSZachary Turner }
2381