1 //===- MicrosoftDemangle.cpp ----------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines a demangler for MSVC-style mangled symbols.
11 // This file has no dependencies on the rest of LLVM so that it can be
12 // easily reused in other programs such as libcxxabi.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/Demangle/MicrosoftDemangle.h"
17 #include "llvm/Demangle/Demangle.h"
18 #include "llvm/Demangle/MicrosoftDemangleNodes.h"
20 #include "llvm/Demangle/DemangleConfig.h"
21 #include "llvm/Demangle/StringView.h"
22 #include "llvm/Demangle/Utility.h"
30 using namespace ms_demangle
;
32 static bool startsWithDigit(StringView S
) {
33 return !S
.empty() && std::isdigit(S
.front());
39 NodeList
*Next
= nullptr;
42 static bool isMemberPointer(StringView MangledName
, bool &Error
) {
44 switch (MangledName
.popFront()) {
46 // This is probably an rvalue reference (e.g. $$Q), and you cannot have an
47 // rvalue reference to a member.
50 // 'A' indicates a reference, and you cannot have a reference to a member
51 // function or member.
57 // These 4 values indicate some kind of pointer, but we still don't know
61 // isMemberPointer() is called only if isPointerType() returns true,
62 // and it rejects other prefixes.
66 // If it starts with a number, then 6 indicates a non-member function
67 // pointer, and 8 indicates a member function pointer.
68 if (startsWithDigit(MangledName
)) {
69 if (MangledName
[0] != '6' && MangledName
[0] != '8') {
73 return (MangledName
[0] == '8');
76 // Remove ext qualifiers since those can appear on either type and are
77 // therefore not indicative.
78 MangledName
.consumeFront('E'); // 64-bit
79 MangledName
.consumeFront('I'); // restrict
80 MangledName
.consumeFront('F'); // unaligned
82 if (MangledName
.empty()) {
87 // The next value should be either ABCD (non-member) or QRST (member).
88 switch (MangledName
.front()) {
105 static SpecialIntrinsicKind
106 consumeSpecialIntrinsicKind(StringView
&MangledName
) {
107 if (MangledName
.consumeFront("?_7"))
108 return SpecialIntrinsicKind::Vftable
;
109 if (MangledName
.consumeFront("?_8"))
110 return SpecialIntrinsicKind::Vbtable
;
111 if (MangledName
.consumeFront("?_9"))
112 return SpecialIntrinsicKind::VcallThunk
;
113 if (MangledName
.consumeFront("?_A"))
114 return SpecialIntrinsicKind::Typeof
;
115 if (MangledName
.consumeFront("?_B"))
116 return SpecialIntrinsicKind::LocalStaticGuard
;
117 if (MangledName
.consumeFront("?_C"))
118 return SpecialIntrinsicKind::StringLiteralSymbol
;
119 if (MangledName
.consumeFront("?_P"))
120 return SpecialIntrinsicKind::UdtReturning
;
121 if (MangledName
.consumeFront("?_R0"))
122 return SpecialIntrinsicKind::RttiTypeDescriptor
;
123 if (MangledName
.consumeFront("?_R1"))
124 return SpecialIntrinsicKind::RttiBaseClassDescriptor
;
125 if (MangledName
.consumeFront("?_R2"))
126 return SpecialIntrinsicKind::RttiBaseClassArray
;
127 if (MangledName
.consumeFront("?_R3"))
128 return SpecialIntrinsicKind::RttiClassHierarchyDescriptor
;
129 if (MangledName
.consumeFront("?_R4"))
130 return SpecialIntrinsicKind::RttiCompleteObjLocator
;
131 if (MangledName
.consumeFront("?_S"))
132 return SpecialIntrinsicKind::LocalVftable
;
133 if (MangledName
.consumeFront("?__E"))
134 return SpecialIntrinsicKind::DynamicInitializer
;
135 if (MangledName
.consumeFront("?__F"))
136 return SpecialIntrinsicKind::DynamicAtexitDestructor
;
137 if (MangledName
.consumeFront("?__J"))
138 return SpecialIntrinsicKind::LocalStaticThreadGuard
;
139 return SpecialIntrinsicKind::None
;
142 static bool startsWithLocalScopePattern(StringView S
) {
143 if (!S
.consumeFront('?'))
146 size_t End
= S
.find('?');
147 if (End
== StringView::npos
)
149 StringView Candidate
= S
.substr(0, End
);
150 if (Candidate
.empty())
154 // ?@? is the discriminator 0.
155 if (Candidate
.size() == 1)
156 return Candidate
[0] == '@' || (Candidate
[0] >= '0' && Candidate
[0] <= '9');
158 // If it's not 0-9, then it's an encoded number terminated with an @
159 if (Candidate
.back() != '@')
161 Candidate
= Candidate
.dropBack();
163 // An encoded number starts with B-P and all subsequent digits are in A-P.
164 // Note that the reason the first digit cannot be A is two fold. First, it
165 // would create an ambiguity with ?A which delimits the beginning of an
166 // anonymous namespace. Second, A represents 0, and you don't start a multi
167 // digit number with a leading 0. Presumably the anonymous namespace
168 // ambiguity is also why single digit encoded numbers use 0-9 rather than A-J.
169 if (Candidate
[0] < 'B' || Candidate
[0] > 'P')
171 Candidate
= Candidate
.dropFront();
172 while (!Candidate
.empty()) {
173 if (Candidate
[0] < 'A' || Candidate
[0] > 'P')
175 Candidate
= Candidate
.dropFront();
181 static bool isTagType(StringView S
) {
192 static bool isCustomType(StringView S
) { return S
[0] == '?'; }
194 static bool isPointerType(StringView S
) {
195 if (S
.startsWith("$$Q")) // foo &&
201 case 'Q': // foo *const
202 case 'R': // foo *volatile
203 case 'S': // foo *const volatile
209 static bool isArrayType(StringView S
) { return S
[0] == 'Y'; }
211 static bool isFunctionType(StringView S
) {
212 return S
.startsWith("$$A8@@") || S
.startsWith("$$A6");
215 static FunctionRefQualifier
216 demangleFunctionRefQualifier(StringView
&MangledName
) {
217 if (MangledName
.consumeFront('G'))
218 return FunctionRefQualifier::Reference
;
219 else if (MangledName
.consumeFront('H'))
220 return FunctionRefQualifier::RValueReference
;
221 return FunctionRefQualifier::None
;
224 static std::pair
<Qualifiers
, PointerAffinity
>
225 demanglePointerCVQualifiers(StringView
&MangledName
) {
226 if (MangledName
.consumeFront("$$Q"))
227 return std::make_pair(Q_None
, PointerAffinity::RValueReference
);
229 switch (MangledName
.popFront()) {
231 return std::make_pair(Q_None
, PointerAffinity::Reference
);
233 return std::make_pair(Q_None
, PointerAffinity::Pointer
);
235 return std::make_pair(Q_Const
, PointerAffinity::Pointer
);
237 return std::make_pair(Q_Volatile
, PointerAffinity::Pointer
);
239 return std::make_pair(Qualifiers(Q_Const
| Q_Volatile
),
240 PointerAffinity::Pointer
);
242 // This function is only called if isPointerType() returns true,
243 // and it only returns true for the six cases listed above.
244 DEMANGLE_UNREACHABLE
;
247 StringView
Demangler::copyString(StringView Borrowed
) {
248 char *Stable
= Arena
.allocUnalignedBuffer(Borrowed
.size() + 1);
249 std::strcpy(Stable
, Borrowed
.begin());
251 return {Stable
, Borrowed
.size()};
254 SpecialTableSymbolNode
*
255 Demangler::demangleSpecialTableSymbolNode(StringView
&MangledName
,
256 SpecialIntrinsicKind K
) {
257 NamedIdentifierNode
*NI
= Arena
.alloc
<NamedIdentifierNode
>();
259 case SpecialIntrinsicKind::Vftable
:
260 NI
->Name
= "`vftable'";
262 case SpecialIntrinsicKind::Vbtable
:
263 NI
->Name
= "`vbtable'";
265 case SpecialIntrinsicKind::LocalVftable
:
266 NI
->Name
= "`local vftable'";
268 case SpecialIntrinsicKind::RttiCompleteObjLocator
:
269 NI
->Name
= "`RTTI Complete Object Locator'";
272 DEMANGLE_UNREACHABLE
;
274 QualifiedNameNode
*QN
= demangleNameScopeChain(MangledName
, NI
);
275 SpecialTableSymbolNode
*STSN
= Arena
.alloc
<SpecialTableSymbolNode
>();
277 bool IsMember
= false;
278 if (MangledName
.empty()) {
282 char Front
= MangledName
.popFront();
283 if (Front
!= '6' && Front
!= '7') {
288 std::tie(STSN
->Quals
, IsMember
) = demangleQualifiers(MangledName
);
289 if (!MangledName
.consumeFront('@'))
290 STSN
->TargetName
= demangleFullyQualifiedTypeName(MangledName
);
294 LocalStaticGuardVariableNode
*
295 Demangler::demangleLocalStaticGuard(StringView
&MangledName
, bool IsThread
) {
296 LocalStaticGuardIdentifierNode
*LSGI
=
297 Arena
.alloc
<LocalStaticGuardIdentifierNode
>();
298 LSGI
->IsThread
= IsThread
;
299 QualifiedNameNode
*QN
= demangleNameScopeChain(MangledName
, LSGI
);
300 LocalStaticGuardVariableNode
*LSGVN
=
301 Arena
.alloc
<LocalStaticGuardVariableNode
>();
304 if (MangledName
.consumeFront("4IA"))
305 LSGVN
->IsVisible
= false;
306 else if (MangledName
.consumeFront("5"))
307 LSGVN
->IsVisible
= true;
313 if (!MangledName
.empty())
314 LSGI
->ScopeIndex
= demangleUnsigned(MangledName
);
318 static NamedIdentifierNode
*synthesizeNamedIdentifier(ArenaAllocator
&Arena
,
320 NamedIdentifierNode
*Id
= Arena
.alloc
<NamedIdentifierNode
>();
325 static QualifiedNameNode
*synthesizeQualifiedName(ArenaAllocator
&Arena
,
326 IdentifierNode
*Identifier
) {
327 QualifiedNameNode
*QN
= Arena
.alloc
<QualifiedNameNode
>();
328 QN
->Components
= Arena
.alloc
<NodeArrayNode
>();
329 QN
->Components
->Count
= 1;
330 QN
->Components
->Nodes
= Arena
.allocArray
<Node
*>(1);
331 QN
->Components
->Nodes
[0] = Identifier
;
335 static QualifiedNameNode
*synthesizeQualifiedName(ArenaAllocator
&Arena
,
337 NamedIdentifierNode
*Id
= synthesizeNamedIdentifier(Arena
, Name
);
338 return synthesizeQualifiedName(Arena
, Id
);
341 static VariableSymbolNode
*synthesizeVariable(ArenaAllocator
&Arena
,
343 StringView VariableName
) {
344 VariableSymbolNode
*VSN
= Arena
.alloc
<VariableSymbolNode
>();
346 VSN
->Name
= synthesizeQualifiedName(Arena
, VariableName
);
350 VariableSymbolNode
*Demangler::demangleUntypedVariable(
351 ArenaAllocator
&Arena
, StringView
&MangledName
, StringView VariableName
) {
352 NamedIdentifierNode
*NI
= synthesizeNamedIdentifier(Arena
, VariableName
);
353 QualifiedNameNode
*QN
= demangleNameScopeChain(MangledName
, NI
);
354 VariableSymbolNode
*VSN
= Arena
.alloc
<VariableSymbolNode
>();
356 if (MangledName
.consumeFront("8"))
364 Demangler::demangleRttiBaseClassDescriptorNode(ArenaAllocator
&Arena
,
365 StringView
&MangledName
) {
366 RttiBaseClassDescriptorNode
*RBCDN
=
367 Arena
.alloc
<RttiBaseClassDescriptorNode
>();
368 RBCDN
->NVOffset
= demangleUnsigned(MangledName
);
369 RBCDN
->VBPtrOffset
= demangleSigned(MangledName
);
370 RBCDN
->VBTableOffset
= demangleUnsigned(MangledName
);
371 RBCDN
->Flags
= demangleUnsigned(MangledName
);
375 VariableSymbolNode
*VSN
= Arena
.alloc
<VariableSymbolNode
>();
376 VSN
->Name
= demangleNameScopeChain(MangledName
, RBCDN
);
377 MangledName
.consumeFront('8');
381 FunctionSymbolNode
*Demangler::demangleInitFiniStub(StringView
&MangledName
,
383 DynamicStructorIdentifierNode
*DSIN
=
384 Arena
.alloc
<DynamicStructorIdentifierNode
>();
385 DSIN
->IsDestructor
= IsDestructor
;
387 bool IsKnownStaticDataMember
= false;
388 if (MangledName
.consumeFront('?'))
389 IsKnownStaticDataMember
= true;
391 SymbolNode
*Symbol
= demangleDeclarator(MangledName
);
395 FunctionSymbolNode
*FSN
= nullptr;
397 if (Symbol
->kind() == NodeKind::VariableSymbol
) {
398 DSIN
->Variable
= static_cast<VariableSymbolNode
*>(Symbol
);
400 // Older versions of clang mangled this type of symbol incorrectly. They
401 // would omit the leading ? and they would only emit a single @ at the end.
402 // The correct mangling is a leading ? and 2 trailing @ signs. Handle
404 int AtCount
= IsKnownStaticDataMember
? 2 : 1;
405 for (int I
= 0; I
< AtCount
; ++I
) {
406 if (MangledName
.consumeFront('@'))
412 FSN
= demangleFunctionEncoding(MangledName
);
414 FSN
->Name
= synthesizeQualifiedName(Arena
, DSIN
);
416 if (IsKnownStaticDataMember
) {
417 // This was supposed to be a static data member, but we got a function.
422 FSN
= static_cast<FunctionSymbolNode
*>(Symbol
);
423 DSIN
->Name
= Symbol
->Name
;
424 FSN
->Name
= synthesizeQualifiedName(Arena
, DSIN
);
430 SymbolNode
*Demangler::demangleSpecialIntrinsic(StringView
&MangledName
) {
431 SpecialIntrinsicKind SIK
= consumeSpecialIntrinsicKind(MangledName
);
434 case SpecialIntrinsicKind::None
:
436 case SpecialIntrinsicKind::StringLiteralSymbol
:
437 return demangleStringLiteral(MangledName
);
438 case SpecialIntrinsicKind::Vftable
:
439 case SpecialIntrinsicKind::Vbtable
:
440 case SpecialIntrinsicKind::LocalVftable
:
441 case SpecialIntrinsicKind::RttiCompleteObjLocator
:
442 return demangleSpecialTableSymbolNode(MangledName
, SIK
);
443 case SpecialIntrinsicKind::VcallThunk
:
444 return demangleVcallThunkNode(MangledName
);
445 case SpecialIntrinsicKind::LocalStaticGuard
:
446 return demangleLocalStaticGuard(MangledName
, /*IsThread=*/false);
447 case SpecialIntrinsicKind::LocalStaticThreadGuard
:
448 return demangleLocalStaticGuard(MangledName
, /*IsThread=*/true);
449 case SpecialIntrinsicKind::RttiTypeDescriptor
: {
450 TypeNode
*T
= demangleType(MangledName
, QualifierMangleMode::Result
);
453 if (!MangledName
.consumeFront("@8"))
455 if (!MangledName
.empty())
457 return synthesizeVariable(Arena
, T
, "`RTTI Type Descriptor'");
459 case SpecialIntrinsicKind::RttiBaseClassArray
:
460 return demangleUntypedVariable(Arena
, MangledName
,
461 "`RTTI Base Class Array'");
462 case SpecialIntrinsicKind::RttiClassHierarchyDescriptor
:
463 return demangleUntypedVariable(Arena
, MangledName
,
464 "`RTTI Class Hierarchy Descriptor'");
465 case SpecialIntrinsicKind::RttiBaseClassDescriptor
:
466 return demangleRttiBaseClassDescriptorNode(Arena
, MangledName
);
467 case SpecialIntrinsicKind::DynamicInitializer
:
468 return demangleInitFiniStub(MangledName
, /*IsDestructor=*/false);
469 case SpecialIntrinsicKind::DynamicAtexitDestructor
:
470 return demangleInitFiniStub(MangledName
, /*IsDestructor=*/true);
471 case SpecialIntrinsicKind::Typeof
:
472 case SpecialIntrinsicKind::UdtReturning
:
473 // It's unclear which tools produces these manglings, so demangling
474 // support is not (yet?) implemented.
476 case SpecialIntrinsicKind::Unknown
:
477 DEMANGLE_UNREACHABLE
; // Never returned by consumeSpecialIntrinsicKind.
484 Demangler::demangleFunctionIdentifierCode(StringView
&MangledName
) {
485 assert(MangledName
.startsWith('?'));
486 MangledName
= MangledName
.dropFront();
487 if (MangledName
.empty()) {
492 if (MangledName
.consumeFront("__"))
493 return demangleFunctionIdentifierCode(
494 MangledName
, FunctionIdentifierCodeGroup::DoubleUnder
);
495 if (MangledName
.consumeFront("_"))
496 return demangleFunctionIdentifierCode(MangledName
,
497 FunctionIdentifierCodeGroup::Under
);
498 return demangleFunctionIdentifierCode(MangledName
,
499 FunctionIdentifierCodeGroup::Basic
);
502 StructorIdentifierNode
*
503 Demangler::demangleStructorIdentifier(StringView
&MangledName
,
505 StructorIdentifierNode
*N
= Arena
.alloc
<StructorIdentifierNode
>();
506 N
->IsDestructor
= IsDestructor
;
510 ConversionOperatorIdentifierNode
*
511 Demangler::demangleConversionOperatorIdentifier(StringView
&MangledName
) {
512 ConversionOperatorIdentifierNode
*N
=
513 Arena
.alloc
<ConversionOperatorIdentifierNode
>();
517 LiteralOperatorIdentifierNode
*
518 Demangler::demangleLiteralOperatorIdentifier(StringView
&MangledName
) {
519 LiteralOperatorIdentifierNode
*N
=
520 Arena
.alloc
<LiteralOperatorIdentifierNode
>();
521 N
->Name
= demangleSimpleString(MangledName
, /*Memorize=*/false);
525 IntrinsicFunctionKind
526 Demangler::translateIntrinsicFunctionCode(char CH
,
527 FunctionIdentifierCodeGroup Group
) {
528 using IFK
= IntrinsicFunctionKind
;
529 if (!(CH
>= '0' && CH
<= '9') && !(CH
>= 'A' && CH
<= 'Z')) {
534 // Not all ? identifiers are intrinsics *functions*. This function only maps
535 // operator codes for the special functions, all others are handled elsewhere,
536 // hence the IFK::None entries in the table.
537 static IFK Basic
[36] = {
538 IFK::None
, // ?0 # Foo::Foo()
539 IFK::None
, // ?1 # Foo::~Foo()
540 IFK::New
, // ?2 # operator new
541 IFK::Delete
, // ?3 # operator delete
542 IFK::Assign
, // ?4 # operator=
543 IFK::RightShift
, // ?5 # operator>>
544 IFK::LeftShift
, // ?6 # operator<<
545 IFK::LogicalNot
, // ?7 # operator!
546 IFK::Equals
, // ?8 # operator==
547 IFK::NotEquals
, // ?9 # operator!=
548 IFK::ArraySubscript
, // ?A # operator[]
549 IFK::None
, // ?B # Foo::operator <type>()
550 IFK::Pointer
, // ?C # operator->
551 IFK::Dereference
, // ?D # operator*
552 IFK::Increment
, // ?E # operator++
553 IFK::Decrement
, // ?F # operator--
554 IFK::Minus
, // ?G # operator-
555 IFK::Plus
, // ?H # operator+
556 IFK::BitwiseAnd
, // ?I # operator&
557 IFK::MemberPointer
, // ?J # operator->*
558 IFK::Divide
, // ?K # operator/
559 IFK::Modulus
, // ?L # operator%
560 IFK::LessThan
, // ?M operator<
561 IFK::LessThanEqual
, // ?N operator<=
562 IFK::GreaterThan
, // ?O operator>
563 IFK::GreaterThanEqual
, // ?P operator>=
564 IFK::Comma
, // ?Q operator,
565 IFK::Parens
, // ?R operator()
566 IFK::BitwiseNot
, // ?S operator~
567 IFK::BitwiseXor
, // ?T operator^
568 IFK::BitwiseOr
, // ?U operator|
569 IFK::LogicalAnd
, // ?V operator&&
570 IFK::LogicalOr
, // ?W operator||
571 IFK::TimesEqual
, // ?X operator*=
572 IFK::PlusEqual
, // ?Y operator+=
573 IFK::MinusEqual
, // ?Z operator-=
575 static IFK Under
[36] = {
576 IFK::DivEqual
, // ?_0 operator/=
577 IFK::ModEqual
, // ?_1 operator%=
578 IFK::RshEqual
, // ?_2 operator>>=
579 IFK::LshEqual
, // ?_3 operator<<=
580 IFK::BitwiseAndEqual
, // ?_4 operator&=
581 IFK::BitwiseOrEqual
, // ?_5 operator|=
582 IFK::BitwiseXorEqual
, // ?_6 operator^=
583 IFK::None
, // ?_7 # vftable
584 IFK::None
, // ?_8 # vbtable
585 IFK::None
, // ?_9 # vcall
586 IFK::None
, // ?_A # typeof
587 IFK::None
, // ?_B # local static guard
588 IFK::None
, // ?_C # string literal
589 IFK::VbaseDtor
, // ?_D # vbase destructor
590 IFK::VecDelDtor
, // ?_E # vector deleting destructor
591 IFK::DefaultCtorClosure
, // ?_F # default constructor closure
592 IFK::ScalarDelDtor
, // ?_G # scalar deleting destructor
593 IFK::VecCtorIter
, // ?_H # vector constructor iterator
594 IFK::VecDtorIter
, // ?_I # vector destructor iterator
595 IFK::VecVbaseCtorIter
, // ?_J # vector vbase constructor iterator
596 IFK::VdispMap
, // ?_K # virtual displacement map
597 IFK::EHVecCtorIter
, // ?_L # eh vector constructor iterator
598 IFK::EHVecDtorIter
, // ?_M # eh vector destructor iterator
599 IFK::EHVecVbaseCtorIter
, // ?_N # eh vector vbase constructor iterator
600 IFK::CopyCtorClosure
, // ?_O # copy constructor closure
601 IFK::None
, // ?_P<name> # udt returning <name>
602 IFK::None
, // ?_Q # <unknown>
603 IFK::None
, // ?_R0 - ?_R4 # RTTI Codes
604 IFK::None
, // ?_S # local vftable
605 IFK::LocalVftableCtorClosure
, // ?_T # local vftable constructor closure
606 IFK::ArrayNew
, // ?_U operator new[]
607 IFK::ArrayDelete
, // ?_V operator delete[]
608 IFK::None
, // ?_W <unused>
609 IFK::None
, // ?_X <unused>
610 IFK::None
, // ?_Y <unused>
611 IFK::None
, // ?_Z <unused>
613 static IFK DoubleUnder
[36] = {
614 IFK::None
, // ?__0 <unused>
615 IFK::None
, // ?__1 <unused>
616 IFK::None
, // ?__2 <unused>
617 IFK::None
, // ?__3 <unused>
618 IFK::None
, // ?__4 <unused>
619 IFK::None
, // ?__5 <unused>
620 IFK::None
, // ?__6 <unused>
621 IFK::None
, // ?__7 <unused>
622 IFK::None
, // ?__8 <unused>
623 IFK::None
, // ?__9 <unused>
624 IFK::ManVectorCtorIter
, // ?__A managed vector ctor iterator
625 IFK::ManVectorDtorIter
, // ?__B managed vector dtor iterator
626 IFK::EHVectorCopyCtorIter
, // ?__C EH vector copy ctor iterator
627 IFK::EHVectorVbaseCopyCtorIter
, // ?__D EH vector vbase copy ctor iter
628 IFK::None
, // ?__E dynamic initializer for `T'
629 IFK::None
, // ?__F dynamic atexit destructor for `T'
630 IFK::VectorCopyCtorIter
, // ?__G vector copy constructor iter
631 IFK::VectorVbaseCopyCtorIter
, // ?__H vector vbase copy ctor iter
632 IFK::ManVectorVbaseCopyCtorIter
, // ?__I managed vector vbase copy ctor
634 IFK::None
, // ?__J local static thread guard
635 IFK::None
, // ?__K operator ""_name
636 IFK::CoAwait
, // ?__L operator co_await
637 IFK::Spaceship
, // ?__M operator<=>
638 IFK::None
, // ?__N <unused>
639 IFK::None
, // ?__O <unused>
640 IFK::None
, // ?__P <unused>
641 IFK::None
, // ?__Q <unused>
642 IFK::None
, // ?__R <unused>
643 IFK::None
, // ?__S <unused>
644 IFK::None
, // ?__T <unused>
645 IFK::None
, // ?__U <unused>
646 IFK::None
, // ?__V <unused>
647 IFK::None
, // ?__W <unused>
648 IFK::None
, // ?__X <unused>
649 IFK::None
, // ?__Y <unused>
650 IFK::None
, // ?__Z <unused>
653 int Index
= (CH
>= '0' && CH
<= '9') ? (CH
- '0') : (CH
- 'A' + 10);
655 case FunctionIdentifierCodeGroup::Basic
:
657 case FunctionIdentifierCodeGroup::Under
:
659 case FunctionIdentifierCodeGroup::DoubleUnder
:
660 return DoubleUnder
[Index
];
662 DEMANGLE_UNREACHABLE
;
666 Demangler::demangleFunctionIdentifierCode(StringView
&MangledName
,
667 FunctionIdentifierCodeGroup Group
) {
668 if (MangledName
.empty()) {
673 case FunctionIdentifierCodeGroup::Basic
:
674 switch (char CH
= MangledName
.popFront()) {
677 return demangleStructorIdentifier(MangledName
, CH
== '1');
679 return demangleConversionOperatorIdentifier(MangledName
);
681 return Arena
.alloc
<IntrinsicFunctionIdentifierNode
>(
682 translateIntrinsicFunctionCode(CH
, Group
));
684 case FunctionIdentifierCodeGroup::Under
:
685 return Arena
.alloc
<IntrinsicFunctionIdentifierNode
>(
686 translateIntrinsicFunctionCode(MangledName
.popFront(), Group
));
687 case FunctionIdentifierCodeGroup::DoubleUnder
:
688 switch (char CH
= MangledName
.popFront()) {
690 return demangleLiteralOperatorIdentifier(MangledName
);
692 return Arena
.alloc
<IntrinsicFunctionIdentifierNode
>(
693 translateIntrinsicFunctionCode(CH
, Group
));
697 DEMANGLE_UNREACHABLE
;
700 SymbolNode
*Demangler::demangleEncodedSymbol(StringView
&MangledName
,
701 QualifiedNameNode
*Name
) {
702 if (MangledName
.empty()) {
708 switch (MangledName
.front()) {
714 StorageClass SC
= demangleVariableStorageClass(MangledName
);
715 return demangleVariableEncoding(MangledName
, SC
);
718 FunctionSymbolNode
*FSN
= demangleFunctionEncoding(MangledName
);
720 IdentifierNode
*UQN
= Name
->getUnqualifiedIdentifier();
721 if (UQN
->kind() == NodeKind::ConversionOperatorIdentifier
) {
722 ConversionOperatorIdentifierNode
*COIN
=
723 static_cast<ConversionOperatorIdentifierNode
*>(UQN
);
725 COIN
->TargetType
= FSN
->Signature
->ReturnType
;
730 SymbolNode
*Demangler::demangleDeclarator(StringView
&MangledName
) {
731 // What follows is a main symbol name. This may include namespaces or class
733 QualifiedNameNode
*QN
= demangleFullyQualifiedSymbolName(MangledName
);
737 SymbolNode
*Symbol
= demangleEncodedSymbol(MangledName
, QN
);
742 IdentifierNode
*UQN
= QN
->getUnqualifiedIdentifier();
743 if (UQN
->kind() == NodeKind::ConversionOperatorIdentifier
) {
744 ConversionOperatorIdentifierNode
*COIN
=
745 static_cast<ConversionOperatorIdentifierNode
*>(UQN
);
746 if (!COIN
->TargetType
) {
754 SymbolNode
*Demangler::demangleMD5Name(StringView
&MangledName
) {
755 assert(MangledName
.startsWith("??@"));
756 // This is an MD5 mangled name. We can't demangle it, just return the
758 // An MD5 mangled name is ??@ followed by 32 characters and a terminating @.
759 size_t MD5Last
= MangledName
.find('@', strlen("??@"));
760 if (MD5Last
== StringView::npos
) {
764 const char *Start
= MangledName
.begin();
765 MangledName
= MangledName
.dropFront(MD5Last
+ 1);
767 // There are two additional special cases for MD5 names:
768 // 1. For complete object locators where the object name is long enough
769 // for the object to have an MD5 name, the complete object locator is
770 // called ??@...@??_R4@ (with a trailing "??_R4@" instead of the usual
771 // leading "??_R4". This is handled here.
772 // 2. For catchable types, in versions of MSVC before 2015 (<1900) or after
773 // 2017.2 (>= 1914), the catchable type mangling is _CT??@...@??@...@8
774 // instead of_CT??@...@8 with just one MD5 name. Since we don't yet
775 // demangle catchable types anywhere, this isn't handled for MD5 names
777 MangledName
.consumeFront("??_R4@");
779 StringView
MD5(Start
, MangledName
.begin());
780 SymbolNode
*S
= Arena
.alloc
<SymbolNode
>(NodeKind::Md5Symbol
);
781 S
->Name
= synthesizeQualifiedName(Arena
, MD5
);
786 // Parser entry point.
787 SymbolNode
*Demangler::parse(StringView
&MangledName
) {
788 if (MangledName
.startsWith("??@"))
789 return demangleMD5Name(MangledName
);
791 // MSVC-style mangled symbols must start with '?'.
792 if (!MangledName
.startsWith('?')) {
797 MangledName
.consumeFront('?');
799 // ?$ is a template instantiation, but all other names that start with ? are
800 // operators / special names.
801 if (SymbolNode
*SI
= demangleSpecialIntrinsic(MangledName
))
804 return demangleDeclarator(MangledName
);
807 TagTypeNode
*Demangler::parseTagUniqueName(StringView
&MangledName
) {
808 if (!MangledName
.consumeFront(".?A"))
810 MangledName
.consumeFront(".?A");
811 if (MangledName
.empty())
814 return demangleClassType(MangledName
);
817 // <type-encoding> ::= <storage-class> <variable-type>
818 // <storage-class> ::= 0 # private static member
819 // ::= 1 # protected static member
820 // ::= 2 # public static member
822 // ::= 4 # static local
824 VariableSymbolNode
*Demangler::demangleVariableEncoding(StringView
&MangledName
,
826 VariableSymbolNode
*VSN
= Arena
.alloc
<VariableSymbolNode
>();
828 VSN
->Type
= demangleType(MangledName
, QualifierMangleMode::Drop
);
834 // <variable-type> ::= <type> <cvr-qualifiers>
835 // ::= <type> <pointee-cvr-qualifiers> # pointers, references
836 switch (VSN
->Type
->kind()) {
837 case NodeKind::PointerType
: {
838 PointerTypeNode
*PTN
= static_cast<PointerTypeNode
*>(VSN
->Type
);
840 Qualifiers ExtraChildQuals
= Q_None
;
841 PTN
->Quals
= Qualifiers(VSN
->Type
->Quals
|
842 demanglePointerExtQualifiers(MangledName
));
844 bool IsMember
= false;
845 std::tie(ExtraChildQuals
, IsMember
) = demangleQualifiers(MangledName
);
847 if (PTN
->ClassParent
) {
848 QualifiedNameNode
*BackRefName
=
849 demangleFullyQualifiedTypeName(MangledName
);
852 PTN
->Pointee
->Quals
= Qualifiers(PTN
->Pointee
->Quals
| ExtraChildQuals
);
857 VSN
->Type
->Quals
= demangleQualifiers(MangledName
).first
;
864 // Sometimes numbers are encoded in mangled symbols. For example,
865 // "int (*x)[20]" is a valid C type (x is a pointer to an array of
866 // length 20), so we need some way to embed numbers as part of symbols.
867 // This function parses it.
869 // <number> ::= [?] <non-negative integer>
871 // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10
872 // ::= <hex digit>+ @ # when Number == 0 or >= 10
874 // <hex-digit> ::= [A-P] # A = 0, B = 1, ...
875 std::pair
<uint64_t, bool> Demangler::demangleNumber(StringView
&MangledName
) {
876 bool IsNegative
= MangledName
.consumeFront('?');
878 if (startsWithDigit(MangledName
)) {
879 uint64_t Ret
= MangledName
[0] - '0' + 1;
880 MangledName
= MangledName
.dropFront(1);
881 return {Ret
, IsNegative
};
885 for (size_t i
= 0; i
< MangledName
.size(); ++i
) {
886 char C
= MangledName
[i
];
888 MangledName
= MangledName
.dropFront(i
+ 1);
889 return {Ret
, IsNegative
};
891 if ('A' <= C
&& C
<= 'P') {
892 Ret
= (Ret
<< 4) + (C
- 'A');
899 return {0ULL, false};
902 uint64_t Demangler::demangleUnsigned(StringView
&MangledName
) {
903 bool IsNegative
= false;
905 std::tie(Number
, IsNegative
) = demangleNumber(MangledName
);
911 int64_t Demangler::demangleSigned(StringView
&MangledName
) {
912 bool IsNegative
= false;
914 std::tie(Number
, IsNegative
) = demangleNumber(MangledName
);
915 if (Number
> INT64_MAX
)
917 int64_t I
= static_cast<int64_t>(Number
);
918 return IsNegative
? -I
: I
;
921 // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
923 void Demangler::memorizeString(StringView S
) {
924 if (Backrefs
.NamesCount
>= BackrefContext::Max
)
926 for (size_t i
= 0; i
< Backrefs
.NamesCount
; ++i
)
927 if (S
== Backrefs
.Names
[i
]->Name
)
929 NamedIdentifierNode
*N
= Arena
.alloc
<NamedIdentifierNode
>();
931 Backrefs
.Names
[Backrefs
.NamesCount
++] = N
;
934 NamedIdentifierNode
*Demangler::demangleBackRefName(StringView
&MangledName
) {
935 assert(startsWithDigit(MangledName
));
937 size_t I
= MangledName
[0] - '0';
938 if (I
>= Backrefs
.NamesCount
) {
943 MangledName
= MangledName
.dropFront();
944 return Backrefs
.Names
[I
];
947 void Demangler::memorizeIdentifier(IdentifierNode
*Identifier
) {
948 // Render this class template name into a string buffer so that we can
949 // memorize it for the purpose of back-referencing.
951 if (!initializeOutputStream(nullptr, nullptr, OS
, 1024))
952 // FIXME: Propagate out-of-memory as an error?
954 Identifier
->output(OS
, OF_Default
);
956 char *Name
= OS
.getBuffer();
958 StringView Owned
= copyString(Name
);
959 memorizeString(Owned
);
964 Demangler::demangleTemplateInstantiationName(StringView
&MangledName
,
965 NameBackrefBehavior NBB
) {
966 assert(MangledName
.startsWith("?$"));
967 MangledName
.consumeFront("?$");
969 BackrefContext OuterContext
;
970 std::swap(OuterContext
, Backrefs
);
972 IdentifierNode
*Identifier
=
973 demangleUnqualifiedSymbolName(MangledName
, NBB_Simple
);
975 Identifier
->TemplateParams
= demangleTemplateParameterList(MangledName
);
977 std::swap(OuterContext
, Backrefs
);
981 if (NBB
& NBB_Template
) {
982 // NBB_Template is only set for types and non-leaf names ("a::" in "a::b").
983 // Structors and conversion operators only makes sense in a leaf name, so
984 // reject them in NBB_Template contexts.
985 if (Identifier
->kind() == NodeKind::ConversionOperatorIdentifier
||
986 Identifier
->kind() == NodeKind::StructorIdentifier
) {
991 memorizeIdentifier(Identifier
);
997 NamedIdentifierNode
*Demangler::demangleSimpleName(StringView
&MangledName
,
999 StringView S
= demangleSimpleString(MangledName
, Memorize
);
1003 NamedIdentifierNode
*Name
= Arena
.alloc
<NamedIdentifierNode
>();
1008 static bool isRebasedHexDigit(char C
) { return (C
>= 'A' && C
<= 'P'); }
1010 static uint8_t rebasedHexDigitToNumber(char C
) {
1011 assert(isRebasedHexDigit(C
));
1012 return (C
<= 'J') ? (C
- 'A') : (10 + C
- 'K');
1015 uint8_t Demangler::demangleCharLiteral(StringView
&MangledName
) {
1016 assert(!MangledName
.empty());
1017 if (!MangledName
.startsWith('?'))
1018 return MangledName
.popFront();
1020 MangledName
= MangledName
.dropFront();
1021 if (MangledName
.empty())
1022 goto CharLiteralError
;
1024 if (MangledName
.consumeFront('$')) {
1026 if (MangledName
.size() < 2)
1027 goto CharLiteralError
;
1028 StringView Nibbles
= MangledName
.substr(0, 2);
1029 if (!isRebasedHexDigit(Nibbles
[0]) || !isRebasedHexDigit(Nibbles
[1]))
1030 goto CharLiteralError
;
1031 // Don't append the null terminator.
1032 uint8_t C1
= rebasedHexDigitToNumber(Nibbles
[0]);
1033 uint8_t C2
= rebasedHexDigitToNumber(Nibbles
[1]);
1034 MangledName
= MangledName
.dropFront(2);
1035 return (C1
<< 4) | C2
;
1038 if (startsWithDigit(MangledName
)) {
1039 const char *Lookup
= ",/\\:. \n\t'-";
1040 char C
= Lookup
[MangledName
[0] - '0'];
1041 MangledName
= MangledName
.dropFront();
1045 if (MangledName
[0] >= 'a' && MangledName
[0] <= 'z') {
1046 char Lookup
[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7',
1047 '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE',
1048 '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5',
1049 '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'};
1050 char C
= Lookup
[MangledName
[0] - 'a'];
1051 MangledName
= MangledName
.dropFront();
1055 if (MangledName
[0] >= 'A' && MangledName
[0] <= 'Z') {
1056 char Lookup
[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7',
1057 '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE',
1058 '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5',
1059 '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'};
1060 char C
= Lookup
[MangledName
[0] - 'A'];
1061 MangledName
= MangledName
.dropFront();
1070 wchar_t Demangler::demangleWcharLiteral(StringView
&MangledName
) {
1073 C1
= demangleCharLiteral(MangledName
);
1074 if (Error
|| MangledName
.empty())
1075 goto WCharLiteralError
;
1076 C2
= demangleCharLiteral(MangledName
);
1078 goto WCharLiteralError
;
1080 return ((wchar_t)C1
<< 8) | (wchar_t)C2
;
1087 static void writeHexDigit(char *Buffer
, uint8_t Digit
) {
1088 assert(Digit
<= 15);
1089 *Buffer
= (Digit
< 10) ? ('0' + Digit
) : ('A' + Digit
- 10);
1092 static void outputHex(OutputStream
&OS
, unsigned C
) {
1095 // It's easier to do the math if we can work from right to left, but we need
1096 // to print the numbers from left to right. So render this into a temporary
1097 // buffer first, then output the temporary buffer. Each byte is of the form
1098 // \xAB, which means that each byte needs 4 characters. Since there are at
1099 // most 4 bytes, we need a 4*4+1 = 17 character temporary buffer.
1100 char TempBuffer
[17];
1102 ::memset(TempBuffer
, 0, sizeof(TempBuffer
));
1103 constexpr int MaxPos
= sizeof(TempBuffer
) - 1;
1105 int Pos
= MaxPos
- 1; // TempBuffer[MaxPos] is the terminating \0.
1107 for (int I
= 0; I
< 2; ++I
) {
1108 writeHexDigit(&TempBuffer
[Pos
--], C
% 16);
1112 TempBuffer
[Pos
--] = 'x';
1114 TempBuffer
[Pos
--] = '\\';
1115 OS
<< StringView(&TempBuffer
[Pos
+ 1]);
1118 static void outputEscapedChar(OutputStream
&OS
, unsigned C
) {
1123 case '\'': // single quote
1126 case '\"': // double quote
1129 case '\\': // backslash
1135 case '\b': // backspace
1138 case '\f': // form feed
1141 case '\n': // new line
1144 case '\r': // carriage return
1150 case '\v': // vertical tab
1157 if (C
> 0x1F && C
< 0x7F) {
1158 // Standard ascii char.
1166 static unsigned countTrailingNullBytes(const uint8_t *StringBytes
, int Length
) {
1167 const uint8_t *End
= StringBytes
+ Length
- 1;
1169 while (Length
> 0 && *End
== 0) {
1177 static unsigned countEmbeddedNulls(const uint8_t *StringBytes
,
1179 unsigned Result
= 0;
1180 for (unsigned I
= 0; I
< Length
; ++I
) {
1181 if (*StringBytes
++ == 0)
1187 // A mangled (non-wide) string literal stores the total length of the string it
1188 // refers to (passed in NumBytes), and it contains up to 32 bytes of actual text
1189 // (passed in StringBytes, NumChars).
1190 static unsigned guessCharByteSize(const uint8_t *StringBytes
, unsigned NumChars
,
1191 uint64_t NumBytes
) {
1192 assert(NumBytes
> 0);
1194 // If the number of bytes is odd, this is guaranteed to be a char string.
1195 if (NumBytes
% 2 == 1)
1198 // All strings can encode at most 32 bytes of data. If it's less than that,
1199 // then we encoded the entire string. In this case we check for a 1-byte,
1200 // 2-byte, or 4-byte null terminator.
1201 if (NumBytes
< 32) {
1202 unsigned TrailingNulls
= countTrailingNullBytes(StringBytes
, NumChars
);
1203 if (TrailingNulls
>= 4 && NumBytes
% 4 == 0)
1205 if (TrailingNulls
>= 2)
1210 // The whole string was not able to be encoded. Try to look at embedded null
1211 // terminators to guess. The heuristic is that we count all embedded null
1212 // terminators. If more than 2/3 are null, it's a char32. If more than 1/3
1213 // are null, it's a char16. Otherwise it's a char8. This obviously isn't
1214 // perfect and is biased towards languages that have ascii alphabets, but this
1215 // was always going to be best effort since the encoding is lossy.
1216 unsigned Nulls
= countEmbeddedNulls(StringBytes
, NumChars
);
1217 if (Nulls
>= 2 * NumChars
/ 3 && NumBytes
% 4 == 0)
1219 if (Nulls
>= NumChars
/ 3)
1224 static unsigned decodeMultiByteChar(const uint8_t *StringBytes
,
1225 unsigned CharIndex
, unsigned CharBytes
) {
1226 assert(CharBytes
== 1 || CharBytes
== 2 || CharBytes
== 4);
1227 unsigned Offset
= CharIndex
* CharBytes
;
1228 unsigned Result
= 0;
1229 StringBytes
= StringBytes
+ Offset
;
1230 for (unsigned I
= 0; I
< CharBytes
; ++I
) {
1231 unsigned C
= static_cast<unsigned>(StringBytes
[I
]);
1232 Result
|= C
<< (8 * I
);
1237 FunctionSymbolNode
*Demangler::demangleVcallThunkNode(StringView
&MangledName
) {
1238 FunctionSymbolNode
*FSN
= Arena
.alloc
<FunctionSymbolNode
>();
1239 VcallThunkIdentifierNode
*VTIN
= Arena
.alloc
<VcallThunkIdentifierNode
>();
1240 FSN
->Signature
= Arena
.alloc
<ThunkSignatureNode
>();
1241 FSN
->Signature
->FunctionClass
= FC_NoParameterList
;
1243 FSN
->Name
= demangleNameScopeChain(MangledName
, VTIN
);
1245 Error
= !MangledName
.consumeFront("$B");
1247 VTIN
->OffsetInVTable
= demangleUnsigned(MangledName
);
1249 Error
= !MangledName
.consumeFront('A');
1251 FSN
->Signature
->CallConvention
= demangleCallingConvention(MangledName
);
1252 return (Error
) ? nullptr : FSN
;
1255 EncodedStringLiteralNode
*
1256 Demangler::demangleStringLiteral(StringView
&MangledName
) {
1257 // This function uses goto, so declare all variables up front.
1260 uint64_t StringByteSize
;
1261 bool IsWcharT
= false;
1262 bool IsNegative
= false;
1263 size_t CrcEndPos
= 0;
1264 char *ResultBuffer
= nullptr;
1266 EncodedStringLiteralNode
*Result
= Arena
.alloc
<EncodedStringLiteralNode
>();
1268 // Must happen before the first `goto StringLiteralError`.
1269 if (!initializeOutputStream(nullptr, nullptr, OS
, 1024))
1270 // FIXME: Propagate out-of-memory as an error?
1273 // Prefix indicating the beginning of a string literal
1274 if (!MangledName
.consumeFront("@_"))
1275 goto StringLiteralError
;
1276 if (MangledName
.empty())
1277 goto StringLiteralError
;
1279 // Char Type (regular or wchar_t)
1280 switch (MangledName
.popFront()) {
1283 DEMANGLE_FALLTHROUGH
;
1287 goto StringLiteralError
;
1291 std::tie(StringByteSize
, IsNegative
) = demangleNumber(MangledName
);
1292 if (Error
|| IsNegative
|| StringByteSize
< (IsWcharT
? 2 : 1))
1293 goto StringLiteralError
;
1295 // CRC 32 (always 8 characters plus a terminator)
1296 CrcEndPos
= MangledName
.find('@');
1297 if (CrcEndPos
== StringView::npos
)
1298 goto StringLiteralError
;
1299 CRC
= MangledName
.substr(0, CrcEndPos
);
1300 MangledName
= MangledName
.dropFront(CrcEndPos
+ 1);
1301 if (MangledName
.empty())
1302 goto StringLiteralError
;
1305 Result
->Char
= CharKind::Wchar
;
1306 if (StringByteSize
> 64)
1307 Result
->IsTruncated
= true;
1309 while (!MangledName
.consumeFront('@')) {
1310 if (MangledName
.size() < 2)
1311 goto StringLiteralError
;
1312 wchar_t W
= demangleWcharLiteral(MangledName
);
1313 if (StringByteSize
!= 2 || Result
->IsTruncated
)
1314 outputEscapedChar(OS
, W
);
1315 StringByteSize
-= 2;
1317 goto StringLiteralError
;
1320 // The max byte length is actually 32, but some compilers mangled strings
1321 // incorrectly, so we have to assume it can go higher.
1322 constexpr unsigned MaxStringByteLength
= 32 * 4;
1323 uint8_t StringBytes
[MaxStringByteLength
];
1325 unsigned BytesDecoded
= 0;
1326 while (!MangledName
.consumeFront('@')) {
1327 if (MangledName
.size() < 1 || BytesDecoded
>= MaxStringByteLength
)
1328 goto StringLiteralError
;
1329 StringBytes
[BytesDecoded
++] = demangleCharLiteral(MangledName
);
1332 if (StringByteSize
> BytesDecoded
)
1333 Result
->IsTruncated
= true;
1335 unsigned CharBytes
=
1336 guessCharByteSize(StringBytes
, BytesDecoded
, StringByteSize
);
1337 assert(StringByteSize
% CharBytes
== 0);
1338 switch (CharBytes
) {
1340 Result
->Char
= CharKind::Char
;
1343 Result
->Char
= CharKind::Char16
;
1346 Result
->Char
= CharKind::Char32
;
1349 DEMANGLE_UNREACHABLE
;
1351 const unsigned NumChars
= BytesDecoded
/ CharBytes
;
1352 for (unsigned CharIndex
= 0; CharIndex
< NumChars
; ++CharIndex
) {
1354 decodeMultiByteChar(StringBytes
, CharIndex
, CharBytes
);
1355 if (CharIndex
+ 1 < NumChars
|| Result
->IsTruncated
)
1356 outputEscapedChar(OS
, NextChar
);
1361 ResultBuffer
= OS
.getBuffer();
1362 Result
->DecodedString
= copyString(ResultBuffer
);
1363 std::free(ResultBuffer
);
1368 std::free(OS
.getBuffer());
1372 // Returns MangledName's prefix before the first '@', or an error if
1373 // MangledName contains no '@' or the prefix has length 0.
1374 StringView
Demangler::demangleSimpleString(StringView
&MangledName
,
1377 for (size_t i
= 0; i
< MangledName
.size(); ++i
) {
1378 if (MangledName
[i
] != '@')
1382 S
= MangledName
.substr(0, i
);
1383 MangledName
= MangledName
.dropFront(i
+ 1);
1394 NamedIdentifierNode
*
1395 Demangler::demangleAnonymousNamespaceName(StringView
&MangledName
) {
1396 assert(MangledName
.startsWith("?A"));
1397 MangledName
.consumeFront("?A");
1399 NamedIdentifierNode
*Node
= Arena
.alloc
<NamedIdentifierNode
>();
1400 Node
->Name
= "`anonymous namespace'";
1401 size_t EndPos
= MangledName
.find('@');
1402 if (EndPos
== StringView::npos
) {
1406 StringView NamespaceKey
= MangledName
.substr(0, EndPos
);
1407 memorizeString(NamespaceKey
);
1408 MangledName
= MangledName
.substr(EndPos
+ 1);
1412 NamedIdentifierNode
*
1413 Demangler::demangleLocallyScopedNamePiece(StringView
&MangledName
) {
1414 assert(startsWithLocalScopePattern(MangledName
));
1416 NamedIdentifierNode
*Identifier
= Arena
.alloc
<NamedIdentifierNode
>();
1417 MangledName
.consumeFront('?');
1418 uint64_t Number
= 0;
1419 bool IsNegative
= false;
1420 std::tie(Number
, IsNegative
) = demangleNumber(MangledName
);
1421 assert(!IsNegative
);
1423 // One ? to terminate the number
1424 MangledName
.consumeFront('?');
1427 Node
*Scope
= parse(MangledName
);
1431 // Render the parent symbol's name into a buffer.
1433 if (!initializeOutputStream(nullptr, nullptr, OS
, 1024))
1434 // FIXME: Propagate out-of-memory as an error?
1437 Scope
->output(OS
, OF_Default
);
1439 OS
<< "::`" << Number
<< "'";
1441 char *Result
= OS
.getBuffer();
1442 Identifier
->Name
= copyString(Result
);
1447 // Parses a type name in the form of A@B@C@@ which represents C::B::A.
1449 Demangler::demangleFullyQualifiedTypeName(StringView
&MangledName
) {
1450 IdentifierNode
*Identifier
=
1451 demangleUnqualifiedTypeName(MangledName
, /*Memorize=*/true);
1456 QualifiedNameNode
*QN
= demangleNameScopeChain(MangledName
, Identifier
);
1463 // Parses a symbol name in the form of A@B@C@@ which represents C::B::A.
1464 // Symbol names have slightly different rules regarding what can appear
1465 // so we separate out the implementations for flexibility.
1467 Demangler::demangleFullyQualifiedSymbolName(StringView
&MangledName
) {
1468 // This is the final component of a symbol name (i.e. the leftmost component
1469 // of a mangled name. Since the only possible template instantiation that
1470 // can appear in this context is a function template, and since those are
1471 // not saved for the purposes of name backreferences, only backref simple
1473 IdentifierNode
*Identifier
=
1474 demangleUnqualifiedSymbolName(MangledName
, NBB_Simple
);
1478 QualifiedNameNode
*QN
= demangleNameScopeChain(MangledName
, Identifier
);
1482 if (Identifier
->kind() == NodeKind::StructorIdentifier
) {
1483 if (QN
->Components
->Count
< 2) {
1487 StructorIdentifierNode
*SIN
=
1488 static_cast<StructorIdentifierNode
*>(Identifier
);
1489 Node
*ClassNode
= QN
->Components
->Nodes
[QN
->Components
->Count
- 2];
1490 SIN
->Class
= static_cast<IdentifierNode
*>(ClassNode
);
1496 IdentifierNode
*Demangler::demangleUnqualifiedTypeName(StringView
&MangledName
,
1498 // An inner-most name can be a back-reference, because a fully-qualified name
1499 // (e.g. Scope + Inner) can contain other fully qualified names inside of
1500 // them (for example template parameters), and these nested parameters can
1501 // refer to previously mangled types.
1502 if (startsWithDigit(MangledName
))
1503 return demangleBackRefName(MangledName
);
1505 if (MangledName
.startsWith("?$"))
1506 return demangleTemplateInstantiationName(MangledName
, NBB_Template
);
1508 return demangleSimpleName(MangledName
, Memorize
);
1512 Demangler::demangleUnqualifiedSymbolName(StringView
&MangledName
,
1513 NameBackrefBehavior NBB
) {
1514 if (startsWithDigit(MangledName
))
1515 return demangleBackRefName(MangledName
);
1516 if (MangledName
.startsWith("?$"))
1517 return demangleTemplateInstantiationName(MangledName
, NBB
);
1518 if (MangledName
.startsWith('?'))
1519 return demangleFunctionIdentifierCode(MangledName
);
1520 return demangleSimpleName(MangledName
, /*Memorize=*/(NBB
& NBB_Simple
) != 0);
1523 IdentifierNode
*Demangler::demangleNameScopePiece(StringView
&MangledName
) {
1524 if (startsWithDigit(MangledName
))
1525 return demangleBackRefName(MangledName
);
1527 if (MangledName
.startsWith("?$"))
1528 return demangleTemplateInstantiationName(MangledName
, NBB_Template
);
1530 if (MangledName
.startsWith("?A"))
1531 return demangleAnonymousNamespaceName(MangledName
);
1533 if (startsWithLocalScopePattern(MangledName
))
1534 return demangleLocallyScopedNamePiece(MangledName
);
1536 return demangleSimpleName(MangledName
, /*Memorize=*/true);
1539 static NodeArrayNode
*nodeListToNodeArray(ArenaAllocator
&Arena
, NodeList
*Head
,
1541 NodeArrayNode
*N
= Arena
.alloc
<NodeArrayNode
>();
1543 N
->Nodes
= Arena
.allocArray
<Node
*>(Count
);
1544 for (size_t I
= 0; I
< Count
; ++I
) {
1545 N
->Nodes
[I
] = Head
->N
;
1552 Demangler::demangleNameScopeChain(StringView
&MangledName
,
1553 IdentifierNode
*UnqualifiedName
) {
1554 NodeList
*Head
= Arena
.alloc
<NodeList
>();
1556 Head
->N
= UnqualifiedName
;
1559 while (!MangledName
.consumeFront("@")) {
1561 NodeList
*NewHead
= Arena
.alloc
<NodeList
>();
1562 NewHead
->Next
= Head
;
1565 if (MangledName
.empty()) {
1571 IdentifierNode
*Elem
= demangleNameScopePiece(MangledName
);
1578 QualifiedNameNode
*QN
= Arena
.alloc
<QualifiedNameNode
>();
1579 QN
->Components
= nodeListToNodeArray(Arena
, Head
, Count
);
1583 FuncClass
Demangler::demangleFunctionClass(StringView
&MangledName
) {
1584 switch (MangledName
.popFront()) {
1586 return FuncClass(FC_ExternC
| FC_NoParameterList
);
1590 return FuncClass(FC_Private
| FC_Far
);
1592 return FuncClass(FC_Private
| FC_Static
);
1594 return FuncClass(FC_Private
| FC_Static
| FC_Far
);
1596 return FuncClass(FC_Private
| FC_Virtual
);
1598 return FuncClass(FC_Private
| FC_Virtual
| FC_Far
);
1600 return FuncClass(FC_Private
| FC_StaticThisAdjust
);
1602 return FuncClass(FC_Private
| FC_StaticThisAdjust
| FC_Far
);
1604 return FuncClass(FC_Protected
);
1606 return FuncClass(FC_Protected
| FC_Far
);
1608 return FuncClass(FC_Protected
| FC_Static
);
1610 return FuncClass(FC_Protected
| FC_Static
| FC_Far
);
1612 return FuncClass(FC_Protected
| FC_Virtual
);
1614 return FuncClass(FC_Protected
| FC_Virtual
| FC_Far
);
1616 return FuncClass(FC_Protected
| FC_Virtual
| FC_StaticThisAdjust
);
1618 return FuncClass(FC_Protected
| FC_Virtual
| FC_StaticThisAdjust
| FC_Far
);
1620 return FuncClass(FC_Public
);
1622 return FuncClass(FC_Public
| FC_Far
);
1624 return FuncClass(FC_Public
| FC_Static
);
1626 return FuncClass(FC_Public
| FC_Static
| FC_Far
);
1628 return FuncClass(FC_Public
| FC_Virtual
);
1630 return FuncClass(FC_Public
| FC_Virtual
| FC_Far
);
1632 return FuncClass(FC_Public
| FC_Virtual
| FC_StaticThisAdjust
);
1634 return FuncClass(FC_Public
| FC_Virtual
| FC_StaticThisAdjust
| FC_Far
);
1636 return FuncClass(FC_Global
);
1638 return FuncClass(FC_Global
| FC_Far
);
1640 FuncClass VFlag
= FC_VirtualThisAdjust
;
1641 if (MangledName
.consumeFront('R'))
1642 VFlag
= FuncClass(VFlag
| FC_VirtualThisAdjustEx
);
1643 if (MangledName
.empty())
1645 switch (MangledName
.popFront()) {
1647 return FuncClass(FC_Private
| FC_Virtual
| VFlag
);
1649 return FuncClass(FC_Private
| FC_Virtual
| VFlag
| FC_Far
);
1651 return FuncClass(FC_Protected
| FC_Virtual
| VFlag
);
1653 return FuncClass(FC_Protected
| FC_Virtual
| VFlag
| FC_Far
);
1655 return FuncClass(FC_Public
| FC_Virtual
| VFlag
);
1657 return FuncClass(FC_Public
| FC_Virtual
| VFlag
| FC_Far
);
1666 CallingConv
Demangler::demangleCallingConvention(StringView
&MangledName
) {
1667 if (MangledName
.empty()) {
1669 return CallingConv::None
;
1672 switch (MangledName
.popFront()) {
1675 return CallingConv::Cdecl
;
1678 return CallingConv::Pascal
;
1681 return CallingConv::Thiscall
;
1684 return CallingConv::Stdcall
;
1687 return CallingConv::Fastcall
;
1690 return CallingConv::Clrcall
;
1693 return CallingConv::Eabi
;
1695 return CallingConv::Vectorcall
;
1698 return CallingConv::None
;
1701 StorageClass
Demangler::demangleVariableStorageClass(StringView
&MangledName
) {
1702 assert(MangledName
.front() >= '0' && MangledName
.front() <= '4');
1704 switch (MangledName
.popFront()) {
1706 return StorageClass::PrivateStatic
;
1708 return StorageClass::ProtectedStatic
;
1710 return StorageClass::PublicStatic
;
1712 return StorageClass::Global
;
1714 return StorageClass::FunctionLocalStatic
;
1716 DEMANGLE_UNREACHABLE
;
1719 std::pair
<Qualifiers
, bool>
1720 Demangler::demangleQualifiers(StringView
&MangledName
) {
1721 if (MangledName
.empty()) {
1723 return std::make_pair(Q_None
, false);
1726 switch (MangledName
.popFront()) {
1727 // Member qualifiers
1729 return std::make_pair(Q_None
, true);
1731 return std::make_pair(Q_Const
, true);
1733 return std::make_pair(Q_Volatile
, true);
1735 return std::make_pair(Qualifiers(Q_Const
| Q_Volatile
), true);
1736 // Non-Member qualifiers
1738 return std::make_pair(Q_None
, false);
1740 return std::make_pair(Q_Const
, false);
1742 return std::make_pair(Q_Volatile
, false);
1744 return std::make_pair(Qualifiers(Q_Const
| Q_Volatile
), false);
1747 return std::make_pair(Q_None
, false);
1750 // <variable-type> ::= <type> <cvr-qualifiers>
1751 // ::= <type> <pointee-cvr-qualifiers> # pointers, references
1752 TypeNode
*Demangler::demangleType(StringView
&MangledName
,
1753 QualifierMangleMode QMM
) {
1754 Qualifiers Quals
= Q_None
;
1755 bool IsMember
= false;
1756 if (QMM
== QualifierMangleMode::Mangle
) {
1757 std::tie(Quals
, IsMember
) = demangleQualifiers(MangledName
);
1758 } else if (QMM
== QualifierMangleMode::Result
) {
1759 if (MangledName
.consumeFront('?'))
1760 std::tie(Quals
, IsMember
) = demangleQualifiers(MangledName
);
1763 if (MangledName
.empty()) {
1768 TypeNode
*Ty
= nullptr;
1769 if (isTagType(MangledName
))
1770 Ty
= demangleClassType(MangledName
);
1771 else if (isPointerType(MangledName
)) {
1772 if (isMemberPointer(MangledName
, Error
))
1773 Ty
= demangleMemberPointerType(MangledName
);
1775 Ty
= demanglePointerType(MangledName
);
1778 } else if (isArrayType(MangledName
))
1779 Ty
= demangleArrayType(MangledName
);
1780 else if (isFunctionType(MangledName
)) {
1781 if (MangledName
.consumeFront("$$A8@@"))
1782 Ty
= demangleFunctionType(MangledName
, true);
1784 assert(MangledName
.startsWith("$$A6"));
1785 MangledName
.consumeFront("$$A6");
1786 Ty
= demangleFunctionType(MangledName
, false);
1788 } else if (isCustomType(MangledName
)) {
1789 Ty
= demangleCustomType(MangledName
);
1791 Ty
= demanglePrimitiveType(MangledName
);
1796 Ty
->Quals
= Qualifiers(Ty
->Quals
| Quals
);
1800 bool Demangler::demangleThrowSpecification(StringView
&MangledName
) {
1801 if (MangledName
.consumeFront("_E"))
1803 if (MangledName
.consumeFront('Z'))
1810 FunctionSignatureNode
*Demangler::demangleFunctionType(StringView
&MangledName
,
1811 bool HasThisQuals
) {
1812 FunctionSignatureNode
*FTy
= Arena
.alloc
<FunctionSignatureNode
>();
1815 FTy
->Quals
= demanglePointerExtQualifiers(MangledName
);
1816 FTy
->RefQualifier
= demangleFunctionRefQualifier(MangledName
);
1817 FTy
->Quals
= Qualifiers(FTy
->Quals
| demangleQualifiers(MangledName
).first
);
1820 // Fields that appear on both member and non-member functions.
1821 FTy
->CallConvention
= demangleCallingConvention(MangledName
);
1823 // <return-type> ::= <type>
1824 // ::= @ # structors (they have no declared return type)
1825 bool IsStructor
= MangledName
.consumeFront('@');
1827 FTy
->ReturnType
= demangleType(MangledName
, QualifierMangleMode::Result
);
1829 FTy
->Params
= demangleFunctionParameterList(MangledName
, FTy
->IsVariadic
);
1831 FTy
->IsNoexcept
= demangleThrowSpecification(MangledName
);
1836 FunctionSymbolNode
*
1837 Demangler::demangleFunctionEncoding(StringView
&MangledName
) {
1838 FuncClass ExtraFlags
= FC_None
;
1839 if (MangledName
.consumeFront("$$J0"))
1840 ExtraFlags
= FC_ExternC
;
1842 if (MangledName
.empty()) {
1847 FuncClass FC
= demangleFunctionClass(MangledName
);
1848 FC
= FuncClass(ExtraFlags
| FC
);
1850 FunctionSignatureNode
*FSN
= nullptr;
1851 ThunkSignatureNode
*TTN
= nullptr;
1852 if (FC
& FC_StaticThisAdjust
) {
1853 TTN
= Arena
.alloc
<ThunkSignatureNode
>();
1854 TTN
->ThisAdjust
.StaticOffset
= demangleSigned(MangledName
);
1855 } else if (FC
& FC_VirtualThisAdjust
) {
1856 TTN
= Arena
.alloc
<ThunkSignatureNode
>();
1857 if (FC
& FC_VirtualThisAdjustEx
) {
1858 TTN
->ThisAdjust
.VBPtrOffset
= demangleSigned(MangledName
);
1859 TTN
->ThisAdjust
.VBOffsetOffset
= demangleSigned(MangledName
);
1861 TTN
->ThisAdjust
.VtordispOffset
= demangleSigned(MangledName
);
1862 TTN
->ThisAdjust
.StaticOffset
= demangleSigned(MangledName
);
1865 if (FC
& FC_NoParameterList
) {
1866 // This is an extern "C" function whose full signature hasn't been mangled.
1867 // This happens when we need to mangle a local symbol inside of an extern
1869 FSN
= Arena
.alloc
<FunctionSignatureNode
>();
1871 bool HasThisQuals
= !(FC
& (FC_Global
| FC_Static
));
1872 FSN
= demangleFunctionType(MangledName
, HasThisQuals
);
1879 *static_cast<FunctionSignatureNode
*>(TTN
) = *FSN
;
1882 FSN
->FunctionClass
= FC
;
1884 FunctionSymbolNode
*Symbol
= Arena
.alloc
<FunctionSymbolNode
>();
1885 Symbol
->Signature
= FSN
;
1889 CustomTypeNode
*Demangler::demangleCustomType(StringView
&MangledName
) {
1890 assert(MangledName
.startsWith('?'));
1891 MangledName
.popFront();
1893 CustomTypeNode
*CTN
= Arena
.alloc
<CustomTypeNode
>();
1894 CTN
->Identifier
= demangleUnqualifiedTypeName(MangledName
, /*Memorize=*/true);
1895 if (!MangledName
.consumeFront('@'))
1902 // Reads a primitive type.
1903 PrimitiveTypeNode
*Demangler::demanglePrimitiveType(StringView
&MangledName
) {
1904 if (MangledName
.consumeFront("$$T"))
1905 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Nullptr
);
1907 switch (MangledName
.popFront()) {
1909 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Void
);
1911 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char
);
1913 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Schar
);
1915 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Uchar
);
1917 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Short
);
1919 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Ushort
);
1921 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Int
);
1923 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Uint
);
1925 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Long
);
1927 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Ulong
);
1929 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Float
);
1931 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Double
);
1933 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Ldouble
);
1935 if (MangledName
.empty()) {
1939 switch (MangledName
.popFront()) {
1941 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Bool
);
1943 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Int64
);
1945 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Uint64
);
1947 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Wchar
);
1949 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char8
);
1951 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char16
);
1953 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char32
);
1962 TagTypeNode
*Demangler::demangleClassType(StringView
&MangledName
) {
1963 TagTypeNode
*TT
= nullptr;
1965 switch (MangledName
.popFront()) {
1967 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Union
);
1970 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Struct
);
1973 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Class
);
1976 if (!MangledName
.consumeFront('4')) {
1980 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Enum
);
1986 TT
->QualifiedName
= demangleFullyQualifiedTypeName(MangledName
);
1990 // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type>
1991 // # the E is required for 64-bit non-static pointers
1992 PointerTypeNode
*Demangler::demanglePointerType(StringView
&MangledName
) {
1993 PointerTypeNode
*Pointer
= Arena
.alloc
<PointerTypeNode
>();
1995 std::tie(Pointer
->Quals
, Pointer
->Affinity
) =
1996 demanglePointerCVQualifiers(MangledName
);
1998 if (MangledName
.consumeFront("6")) {
1999 Pointer
->Pointee
= demangleFunctionType(MangledName
, false);
2003 Qualifiers ExtQuals
= demanglePointerExtQualifiers(MangledName
);
2004 Pointer
->Quals
= Qualifiers(Pointer
->Quals
| ExtQuals
);
2006 Pointer
->Pointee
= demangleType(MangledName
, QualifierMangleMode::Mangle
);
2010 PointerTypeNode
*Demangler::demangleMemberPointerType(StringView
&MangledName
) {
2011 PointerTypeNode
*Pointer
= Arena
.alloc
<PointerTypeNode
>();
2013 std::tie(Pointer
->Quals
, Pointer
->Affinity
) =
2014 demanglePointerCVQualifiers(MangledName
);
2015 assert(Pointer
->Affinity
== PointerAffinity::Pointer
);
2017 Qualifiers ExtQuals
= demanglePointerExtQualifiers(MangledName
);
2018 Pointer
->Quals
= Qualifiers(Pointer
->Quals
| ExtQuals
);
2020 // isMemberPointer() only returns true if there is at least one character
2021 // after the qualifiers.
2022 if (MangledName
.consumeFront("8")) {
2023 Pointer
->ClassParent
= demangleFullyQualifiedTypeName(MangledName
);
2024 Pointer
->Pointee
= demangleFunctionType(MangledName
, true);
2026 Qualifiers PointeeQuals
= Q_None
;
2027 bool IsMember
= false;
2028 std::tie(PointeeQuals
, IsMember
) = demangleQualifiers(MangledName
);
2029 assert(IsMember
|| Error
);
2030 Pointer
->ClassParent
= demangleFullyQualifiedTypeName(MangledName
);
2032 Pointer
->Pointee
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2033 if (Pointer
->Pointee
)
2034 Pointer
->Pointee
->Quals
= PointeeQuals
;
2040 Qualifiers
Demangler::demanglePointerExtQualifiers(StringView
&MangledName
) {
2041 Qualifiers Quals
= Q_None
;
2042 if (MangledName
.consumeFront('E'))
2043 Quals
= Qualifiers(Quals
| Q_Pointer64
);
2044 if (MangledName
.consumeFront('I'))
2045 Quals
= Qualifiers(Quals
| Q_Restrict
);
2046 if (MangledName
.consumeFront('F'))
2047 Quals
= Qualifiers(Quals
| Q_Unaligned
);
2052 ArrayTypeNode
*Demangler::demangleArrayType(StringView
&MangledName
) {
2053 assert(MangledName
.front() == 'Y');
2054 MangledName
.popFront();
2057 bool IsNegative
= false;
2058 std::tie(Rank
, IsNegative
) = demangleNumber(MangledName
);
2059 if (IsNegative
|| Rank
== 0) {
2064 ArrayTypeNode
*ATy
= Arena
.alloc
<ArrayTypeNode
>();
2065 NodeList
*Head
= Arena
.alloc
<NodeList
>();
2066 NodeList
*Tail
= Head
;
2068 for (uint64_t I
= 0; I
< Rank
; ++I
) {
2070 std::tie(D
, IsNegative
) = demangleNumber(MangledName
);
2071 if (Error
|| IsNegative
) {
2075 Tail
->N
= Arena
.alloc
<IntegerLiteralNode
>(D
, IsNegative
);
2077 Tail
->Next
= Arena
.alloc
<NodeList
>();
2081 ATy
->Dimensions
= nodeListToNodeArray(Arena
, Head
, Rank
);
2083 if (MangledName
.consumeFront("$$C")) {
2084 bool IsMember
= false;
2085 std::tie(ATy
->Quals
, IsMember
) = demangleQualifiers(MangledName
);
2092 ATy
->ElementType
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2096 // Reads a function's parameters.
2097 NodeArrayNode
*Demangler::demangleFunctionParameterList(StringView
&MangledName
,
2099 // Empty parameter list.
2100 if (MangledName
.consumeFront('X'))
2103 NodeList
*Head
= Arena
.alloc
<NodeList
>();
2104 NodeList
**Current
= &Head
;
2106 while (!Error
&& !MangledName
.startsWith('@') &&
2107 !MangledName
.startsWith('Z')) {
2110 if (startsWithDigit(MangledName
)) {
2111 size_t N
= MangledName
[0] - '0';
2112 if (N
>= Backrefs
.FunctionParamCount
) {
2116 MangledName
= MangledName
.dropFront();
2118 *Current
= Arena
.alloc
<NodeList
>();
2119 (*Current
)->N
= Backrefs
.FunctionParams
[N
];
2120 Current
= &(*Current
)->Next
;
2124 size_t OldSize
= MangledName
.size();
2126 *Current
= Arena
.alloc
<NodeList
>();
2127 TypeNode
*TN
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2133 size_t CharsConsumed
= OldSize
- MangledName
.size();
2134 assert(CharsConsumed
!= 0);
2136 // Single-letter types are ignored for backreferences because memorizing
2137 // them doesn't save anything.
2138 if (Backrefs
.FunctionParamCount
<= 9 && CharsConsumed
> 1)
2139 Backrefs
.FunctionParams
[Backrefs
.FunctionParamCount
++] = TN
;
2141 Current
= &(*Current
)->Next
;
2147 NodeArrayNode
*NA
= nodeListToNodeArray(Arena
, Head
, Count
);
2148 // A non-empty parameter list is terminated by either 'Z' (variadic) parameter
2149 // list or '@' (non variadic). Careful not to consume "@Z", as in that case
2150 // the following Z could be a throw specifier.
2151 if (MangledName
.consumeFront('@'))
2154 if (MangledName
.consumeFront('Z')) {
2159 DEMANGLE_UNREACHABLE
;
2163 Demangler::demangleTemplateParameterList(StringView
&MangledName
) {
2165 NodeList
**Current
= &Head
;
2168 while (!MangledName
.startsWith('@')) {
2169 if (MangledName
.consumeFront("$S") || MangledName
.consumeFront("$$V") ||
2170 MangledName
.consumeFront("$$$V") || MangledName
.consumeFront("$$Z")) {
2171 // parameter pack separator
2177 // Template parameter lists don't participate in back-referencing.
2178 *Current
= Arena
.alloc
<NodeList
>();
2180 NodeList
&TP
= **Current
;
2182 TemplateParameterReferenceNode
*TPRN
= nullptr;
2183 if (MangledName
.consumeFront("$$Y")) {
2185 TP
.N
= demangleFullyQualifiedTypeName(MangledName
);
2186 } else if (MangledName
.consumeFront("$$B")) {
2188 TP
.N
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2189 } else if (MangledName
.consumeFront("$$C")) {
2190 // Type has qualifiers.
2191 TP
.N
= demangleType(MangledName
, QualifierMangleMode::Mangle
);
2192 } else if (MangledName
.startsWith("$1") || MangledName
.startsWith("$H") ||
2193 MangledName
.startsWith("$I") || MangledName
.startsWith("$J")) {
2194 // Pointer to member
2195 TP
.N
= TPRN
= Arena
.alloc
<TemplateParameterReferenceNode
>();
2196 TPRN
->IsMemberPointer
= true;
2198 MangledName
= MangledName
.dropFront();
2199 // 1 - single inheritance <name>
2200 // H - multiple inheritance <name> <number>
2201 // I - virtual inheritance <name> <number> <number>
2202 // J - unspecified inheritance <name> <number> <number> <number>
2203 char InheritanceSpecifier
= MangledName
.popFront();
2204 SymbolNode
*S
= nullptr;
2205 if (MangledName
.startsWith('?')) {
2206 S
= parse(MangledName
);
2207 if (Error
|| !S
->Name
) {
2211 memorizeIdentifier(S
->Name
->getUnqualifiedIdentifier());
2214 switch (InheritanceSpecifier
) {
2216 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2217 demangleSigned(MangledName
);
2218 DEMANGLE_FALLTHROUGH
;
2220 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2221 demangleSigned(MangledName
);
2222 DEMANGLE_FALLTHROUGH
;
2224 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2225 demangleSigned(MangledName
);
2226 DEMANGLE_FALLTHROUGH
;
2230 DEMANGLE_UNREACHABLE
;
2232 TPRN
->Affinity
= PointerAffinity::Pointer
;
2234 } else if (MangledName
.startsWith("$E?")) {
2235 MangledName
.consumeFront("$E");
2236 // Reference to symbol
2237 TP
.N
= TPRN
= Arena
.alloc
<TemplateParameterReferenceNode
>();
2238 TPRN
->Symbol
= parse(MangledName
);
2239 TPRN
->Affinity
= PointerAffinity::Reference
;
2240 } else if (MangledName
.startsWith("$F") || MangledName
.startsWith("$G")) {
2241 TP
.N
= TPRN
= Arena
.alloc
<TemplateParameterReferenceNode
>();
2243 // Data member pointer.
2244 MangledName
= MangledName
.dropFront();
2245 char InheritanceSpecifier
= MangledName
.popFront();
2247 switch (InheritanceSpecifier
) {
2249 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2250 demangleSigned(MangledName
);
2251 DEMANGLE_FALLTHROUGH
;
2253 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2254 demangleSigned(MangledName
);
2255 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2256 demangleSigned(MangledName
);
2259 DEMANGLE_UNREACHABLE
;
2261 TPRN
->IsMemberPointer
= true;
2263 } else if (MangledName
.consumeFront("$0")) {
2264 // Integral non-type template parameter
2265 bool IsNegative
= false;
2267 std::tie(Value
, IsNegative
) = demangleNumber(MangledName
);
2269 TP
.N
= Arena
.alloc
<IntegerLiteralNode
>(Value
, IsNegative
);
2271 TP
.N
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2279 // The loop above returns nullptr on Error.
2282 // Template parameter lists cannot be variadic, so it can only be terminated
2283 // by @ (as opposed to 'Z' in the function parameter case).
2284 assert(MangledName
.startsWith('@')); // The above loop exits only on '@'.
2285 MangledName
.consumeFront('@');
2286 return nodeListToNodeArray(Arena
, Head
, Count
);
2289 void Demangler::dumpBackReferences() {
2290 std::printf("%d function parameter backreferences\n",
2291 (int)Backrefs
.FunctionParamCount
);
2293 // Create an output stream so we can render each type.
2295 if (!initializeOutputStream(nullptr, nullptr, OS
, 1024))
2297 for (size_t I
= 0; I
< Backrefs
.FunctionParamCount
; ++I
) {
2298 OS
.setCurrentPosition(0);
2300 TypeNode
*T
= Backrefs
.FunctionParams
[I
];
2301 T
->output(OS
, OF_Default
);
2303 std::printf(" [%d] - %.*s\n", (int)I
, (int)OS
.getCurrentPosition(),
2306 std::free(OS
.getBuffer());
2308 if (Backrefs
.FunctionParamCount
> 0)
2310 std::printf("%d name backreferences\n", (int)Backrefs
.NamesCount
);
2311 for (size_t I
= 0; I
< Backrefs
.NamesCount
; ++I
) {
2312 std::printf(" [%d] - %.*s\n", (int)I
, (int)Backrefs
.Names
[I
]->Name
.size(),
2313 Backrefs
.Names
[I
]->Name
.begin());
2315 if (Backrefs
.NamesCount
> 0)
2319 char *llvm::microsoftDemangle(const char *MangledName
, char *Buf
, size_t *N
,
2320 int *Status
, MSDemangleFlags Flags
) {
2321 int InternalStatus
= demangle_success
;
2325 StringView Name
{MangledName
};
2326 SymbolNode
*AST
= D
.parse(Name
);
2328 if (Flags
& MSDF_DumpBackrefs
)
2329 D
.dumpBackReferences();
2332 InternalStatus
= demangle_invalid_mangled_name
;
2333 else if (!initializeOutputStream(Buf
, N
, S
, 1024))
2334 InternalStatus
= demangle_memory_alloc_failure
;
2336 AST
->output(S
, OF_Default
);
2339 *N
= S
.getCurrentPosition();
2340 Buf
= S
.getBuffer();
2344 *Status
= InternalStatus
;
2345 return InternalStatus
== demangle_success
? Buf
: nullptr;