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 SymbolNode
*Demangler::demangleTypeinfoName(StringView
&MangledName
) {
787 assert(MangledName
.startsWith('.'));
788 MangledName
.consumeFront('.');
790 TypeNode
*T
= demangleType(MangledName
, QualifierMangleMode::Result
);
791 if (Error
|| !MangledName
.empty()) {
795 return synthesizeVariable(Arena
, T
, "`RTTI Type Descriptor Name'");
798 // Parser entry point.
799 SymbolNode
*Demangler::parse(StringView
&MangledName
) {
800 // Typeinfo names are strings stored in RTTI data. They're not symbol names.
801 // It's still useful to demangle them. They're the only demangled entity
802 // that doesn't start with a "?" but a ".".
803 if (MangledName
.startsWith('.'))
804 return demangleTypeinfoName(MangledName
);
806 if (MangledName
.startsWith("??@"))
807 return demangleMD5Name(MangledName
);
809 // MSVC-style mangled symbols must start with '?'.
810 if (!MangledName
.startsWith('?')) {
815 MangledName
.consumeFront('?');
817 // ?$ is a template instantiation, but all other names that start with ? are
818 // operators / special names.
819 if (SymbolNode
*SI
= demangleSpecialIntrinsic(MangledName
))
822 return demangleDeclarator(MangledName
);
825 TagTypeNode
*Demangler::parseTagUniqueName(StringView
&MangledName
) {
826 if (!MangledName
.consumeFront(".?A"))
828 MangledName
.consumeFront(".?A");
829 if (MangledName
.empty())
832 return demangleClassType(MangledName
);
835 // <type-encoding> ::= <storage-class> <variable-type>
836 // <storage-class> ::= 0 # private static member
837 // ::= 1 # protected static member
838 // ::= 2 # public static member
840 // ::= 4 # static local
842 VariableSymbolNode
*Demangler::demangleVariableEncoding(StringView
&MangledName
,
844 VariableSymbolNode
*VSN
= Arena
.alloc
<VariableSymbolNode
>();
846 VSN
->Type
= demangleType(MangledName
, QualifierMangleMode::Drop
);
852 // <variable-type> ::= <type> <cvr-qualifiers>
853 // ::= <type> <pointee-cvr-qualifiers> # pointers, references
854 switch (VSN
->Type
->kind()) {
855 case NodeKind::PointerType
: {
856 PointerTypeNode
*PTN
= static_cast<PointerTypeNode
*>(VSN
->Type
);
858 Qualifiers ExtraChildQuals
= Q_None
;
859 PTN
->Quals
= Qualifiers(VSN
->Type
->Quals
|
860 demanglePointerExtQualifiers(MangledName
));
862 bool IsMember
= false;
863 std::tie(ExtraChildQuals
, IsMember
) = demangleQualifiers(MangledName
);
865 if (PTN
->ClassParent
) {
866 QualifiedNameNode
*BackRefName
=
867 demangleFullyQualifiedTypeName(MangledName
);
870 PTN
->Pointee
->Quals
= Qualifiers(PTN
->Pointee
->Quals
| ExtraChildQuals
);
875 VSN
->Type
->Quals
= demangleQualifiers(MangledName
).first
;
882 // Sometimes numbers are encoded in mangled symbols. For example,
883 // "int (*x)[20]" is a valid C type (x is a pointer to an array of
884 // length 20), so we need some way to embed numbers as part of symbols.
885 // This function parses it.
887 // <number> ::= [?] <non-negative integer>
889 // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10
890 // ::= <hex digit>+ @ # when Number == 0 or >= 10
892 // <hex-digit> ::= [A-P] # A = 0, B = 1, ...
893 std::pair
<uint64_t, bool> Demangler::demangleNumber(StringView
&MangledName
) {
894 bool IsNegative
= MangledName
.consumeFront('?');
896 if (startsWithDigit(MangledName
)) {
897 uint64_t Ret
= MangledName
[0] - '0' + 1;
898 MangledName
= MangledName
.dropFront(1);
899 return {Ret
, IsNegative
};
903 for (size_t i
= 0; i
< MangledName
.size(); ++i
) {
904 char C
= MangledName
[i
];
906 MangledName
= MangledName
.dropFront(i
+ 1);
907 return {Ret
, IsNegative
};
909 if ('A' <= C
&& C
<= 'P') {
910 Ret
= (Ret
<< 4) + (C
- 'A');
917 return {0ULL, false};
920 uint64_t Demangler::demangleUnsigned(StringView
&MangledName
) {
921 bool IsNegative
= false;
923 std::tie(Number
, IsNegative
) = demangleNumber(MangledName
);
929 int64_t Demangler::demangleSigned(StringView
&MangledName
) {
930 bool IsNegative
= false;
932 std::tie(Number
, IsNegative
) = demangleNumber(MangledName
);
933 if (Number
> INT64_MAX
)
935 int64_t I
= static_cast<int64_t>(Number
);
936 return IsNegative
? -I
: I
;
939 // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
941 void Demangler::memorizeString(StringView S
) {
942 if (Backrefs
.NamesCount
>= BackrefContext::Max
)
944 for (size_t i
= 0; i
< Backrefs
.NamesCount
; ++i
)
945 if (S
== Backrefs
.Names
[i
]->Name
)
947 NamedIdentifierNode
*N
= Arena
.alloc
<NamedIdentifierNode
>();
949 Backrefs
.Names
[Backrefs
.NamesCount
++] = N
;
952 NamedIdentifierNode
*Demangler::demangleBackRefName(StringView
&MangledName
) {
953 assert(startsWithDigit(MangledName
));
955 size_t I
= MangledName
[0] - '0';
956 if (I
>= Backrefs
.NamesCount
) {
961 MangledName
= MangledName
.dropFront();
962 return Backrefs
.Names
[I
];
965 void Demangler::memorizeIdentifier(IdentifierNode
*Identifier
) {
966 // Render this class template name into a string buffer so that we can
967 // memorize it for the purpose of back-referencing.
969 if (!initializeOutputStream(nullptr, nullptr, OS
, 1024))
970 // FIXME: Propagate out-of-memory as an error?
972 Identifier
->output(OS
, OF_Default
);
974 char *Name
= OS
.getBuffer();
976 StringView Owned
= copyString(Name
);
977 memorizeString(Owned
);
982 Demangler::demangleTemplateInstantiationName(StringView
&MangledName
,
983 NameBackrefBehavior NBB
) {
984 assert(MangledName
.startsWith("?$"));
985 MangledName
.consumeFront("?$");
987 BackrefContext OuterContext
;
988 std::swap(OuterContext
, Backrefs
);
990 IdentifierNode
*Identifier
=
991 demangleUnqualifiedSymbolName(MangledName
, NBB_Simple
);
993 Identifier
->TemplateParams
= demangleTemplateParameterList(MangledName
);
995 std::swap(OuterContext
, Backrefs
);
999 if (NBB
& NBB_Template
) {
1000 // NBB_Template is only set for types and non-leaf names ("a::" in "a::b").
1001 // Structors and conversion operators only makes sense in a leaf name, so
1002 // reject them in NBB_Template contexts.
1003 if (Identifier
->kind() == NodeKind::ConversionOperatorIdentifier
||
1004 Identifier
->kind() == NodeKind::StructorIdentifier
) {
1009 memorizeIdentifier(Identifier
);
1015 NamedIdentifierNode
*Demangler::demangleSimpleName(StringView
&MangledName
,
1017 StringView S
= demangleSimpleString(MangledName
, Memorize
);
1021 NamedIdentifierNode
*Name
= Arena
.alloc
<NamedIdentifierNode
>();
1026 static bool isRebasedHexDigit(char C
) { return (C
>= 'A' && C
<= 'P'); }
1028 static uint8_t rebasedHexDigitToNumber(char C
) {
1029 assert(isRebasedHexDigit(C
));
1030 return (C
<= 'J') ? (C
- 'A') : (10 + C
- 'K');
1033 uint8_t Demangler::demangleCharLiteral(StringView
&MangledName
) {
1034 assert(!MangledName
.empty());
1035 if (!MangledName
.startsWith('?'))
1036 return MangledName
.popFront();
1038 MangledName
= MangledName
.dropFront();
1039 if (MangledName
.empty())
1040 goto CharLiteralError
;
1042 if (MangledName
.consumeFront('$')) {
1044 if (MangledName
.size() < 2)
1045 goto CharLiteralError
;
1046 StringView Nibbles
= MangledName
.substr(0, 2);
1047 if (!isRebasedHexDigit(Nibbles
[0]) || !isRebasedHexDigit(Nibbles
[1]))
1048 goto CharLiteralError
;
1049 // Don't append the null terminator.
1050 uint8_t C1
= rebasedHexDigitToNumber(Nibbles
[0]);
1051 uint8_t C2
= rebasedHexDigitToNumber(Nibbles
[1]);
1052 MangledName
= MangledName
.dropFront(2);
1053 return (C1
<< 4) | C2
;
1056 if (startsWithDigit(MangledName
)) {
1057 const char *Lookup
= ",/\\:. \n\t'-";
1058 char C
= Lookup
[MangledName
[0] - '0'];
1059 MangledName
= MangledName
.dropFront();
1063 if (MangledName
[0] >= 'a' && MangledName
[0] <= 'z') {
1064 char Lookup
[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7',
1065 '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE',
1066 '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5',
1067 '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'};
1068 char C
= Lookup
[MangledName
[0] - 'a'];
1069 MangledName
= MangledName
.dropFront();
1073 if (MangledName
[0] >= 'A' && MangledName
[0] <= 'Z') {
1074 char Lookup
[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7',
1075 '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE',
1076 '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5',
1077 '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'};
1078 char C
= Lookup
[MangledName
[0] - 'A'];
1079 MangledName
= MangledName
.dropFront();
1088 wchar_t Demangler::demangleWcharLiteral(StringView
&MangledName
) {
1091 C1
= demangleCharLiteral(MangledName
);
1092 if (Error
|| MangledName
.empty())
1093 goto WCharLiteralError
;
1094 C2
= demangleCharLiteral(MangledName
);
1096 goto WCharLiteralError
;
1098 return ((wchar_t)C1
<< 8) | (wchar_t)C2
;
1105 static void writeHexDigit(char *Buffer
, uint8_t Digit
) {
1106 assert(Digit
<= 15);
1107 *Buffer
= (Digit
< 10) ? ('0' + Digit
) : ('A' + Digit
- 10);
1110 static void outputHex(OutputStream
&OS
, unsigned C
) {
1113 // It's easier to do the math if we can work from right to left, but we need
1114 // to print the numbers from left to right. So render this into a temporary
1115 // buffer first, then output the temporary buffer. Each byte is of the form
1116 // \xAB, which means that each byte needs 4 characters. Since there are at
1117 // most 4 bytes, we need a 4*4+1 = 17 character temporary buffer.
1118 char TempBuffer
[17];
1120 ::memset(TempBuffer
, 0, sizeof(TempBuffer
));
1121 constexpr int MaxPos
= sizeof(TempBuffer
) - 1;
1123 int Pos
= MaxPos
- 1; // TempBuffer[MaxPos] is the terminating \0.
1125 for (int I
= 0; I
< 2; ++I
) {
1126 writeHexDigit(&TempBuffer
[Pos
--], C
% 16);
1130 TempBuffer
[Pos
--] = 'x';
1132 TempBuffer
[Pos
--] = '\\';
1133 OS
<< StringView(&TempBuffer
[Pos
+ 1]);
1136 static void outputEscapedChar(OutputStream
&OS
, unsigned C
) {
1141 case '\'': // single quote
1144 case '\"': // double quote
1147 case '\\': // backslash
1153 case '\b': // backspace
1156 case '\f': // form feed
1159 case '\n': // new line
1162 case '\r': // carriage return
1168 case '\v': // vertical tab
1175 if (C
> 0x1F && C
< 0x7F) {
1176 // Standard ascii char.
1184 static unsigned countTrailingNullBytes(const uint8_t *StringBytes
, int Length
) {
1185 const uint8_t *End
= StringBytes
+ Length
- 1;
1187 while (Length
> 0 && *End
== 0) {
1195 static unsigned countEmbeddedNulls(const uint8_t *StringBytes
,
1197 unsigned Result
= 0;
1198 for (unsigned I
= 0; I
< Length
; ++I
) {
1199 if (*StringBytes
++ == 0)
1205 // A mangled (non-wide) string literal stores the total length of the string it
1206 // refers to (passed in NumBytes), and it contains up to 32 bytes of actual text
1207 // (passed in StringBytes, NumChars).
1208 static unsigned guessCharByteSize(const uint8_t *StringBytes
, unsigned NumChars
,
1209 uint64_t NumBytes
) {
1210 assert(NumBytes
> 0);
1212 // If the number of bytes is odd, this is guaranteed to be a char string.
1213 if (NumBytes
% 2 == 1)
1216 // All strings can encode at most 32 bytes of data. If it's less than that,
1217 // then we encoded the entire string. In this case we check for a 1-byte,
1218 // 2-byte, or 4-byte null terminator.
1219 if (NumBytes
< 32) {
1220 unsigned TrailingNulls
= countTrailingNullBytes(StringBytes
, NumChars
);
1221 if (TrailingNulls
>= 4 && NumBytes
% 4 == 0)
1223 if (TrailingNulls
>= 2)
1228 // The whole string was not able to be encoded. Try to look at embedded null
1229 // terminators to guess. The heuristic is that we count all embedded null
1230 // terminators. If more than 2/3 are null, it's a char32. If more than 1/3
1231 // are null, it's a char16. Otherwise it's a char8. This obviously isn't
1232 // perfect and is biased towards languages that have ascii alphabets, but this
1233 // was always going to be best effort since the encoding is lossy.
1234 unsigned Nulls
= countEmbeddedNulls(StringBytes
, NumChars
);
1235 if (Nulls
>= 2 * NumChars
/ 3 && NumBytes
% 4 == 0)
1237 if (Nulls
>= NumChars
/ 3)
1242 static unsigned decodeMultiByteChar(const uint8_t *StringBytes
,
1243 unsigned CharIndex
, unsigned CharBytes
) {
1244 assert(CharBytes
== 1 || CharBytes
== 2 || CharBytes
== 4);
1245 unsigned Offset
= CharIndex
* CharBytes
;
1246 unsigned Result
= 0;
1247 StringBytes
= StringBytes
+ Offset
;
1248 for (unsigned I
= 0; I
< CharBytes
; ++I
) {
1249 unsigned C
= static_cast<unsigned>(StringBytes
[I
]);
1250 Result
|= C
<< (8 * I
);
1255 FunctionSymbolNode
*Demangler::demangleVcallThunkNode(StringView
&MangledName
) {
1256 FunctionSymbolNode
*FSN
= Arena
.alloc
<FunctionSymbolNode
>();
1257 VcallThunkIdentifierNode
*VTIN
= Arena
.alloc
<VcallThunkIdentifierNode
>();
1258 FSN
->Signature
= Arena
.alloc
<ThunkSignatureNode
>();
1259 FSN
->Signature
->FunctionClass
= FC_NoParameterList
;
1261 FSN
->Name
= demangleNameScopeChain(MangledName
, VTIN
);
1263 Error
= !MangledName
.consumeFront("$B");
1265 VTIN
->OffsetInVTable
= demangleUnsigned(MangledName
);
1267 Error
= !MangledName
.consumeFront('A');
1269 FSN
->Signature
->CallConvention
= demangleCallingConvention(MangledName
);
1270 return (Error
) ? nullptr : FSN
;
1273 EncodedStringLiteralNode
*
1274 Demangler::demangleStringLiteral(StringView
&MangledName
) {
1275 // This function uses goto, so declare all variables up front.
1278 uint64_t StringByteSize
;
1279 bool IsWcharT
= false;
1280 bool IsNegative
= false;
1281 size_t CrcEndPos
= 0;
1282 char *ResultBuffer
= nullptr;
1284 EncodedStringLiteralNode
*Result
= Arena
.alloc
<EncodedStringLiteralNode
>();
1286 // Must happen before the first `goto StringLiteralError`.
1287 if (!initializeOutputStream(nullptr, nullptr, OS
, 1024))
1288 // FIXME: Propagate out-of-memory as an error?
1291 // Prefix indicating the beginning of a string literal
1292 if (!MangledName
.consumeFront("@_"))
1293 goto StringLiteralError
;
1294 if (MangledName
.empty())
1295 goto StringLiteralError
;
1297 // Char Type (regular or wchar_t)
1298 switch (MangledName
.popFront()) {
1301 DEMANGLE_FALLTHROUGH
;
1305 goto StringLiteralError
;
1309 std::tie(StringByteSize
, IsNegative
) = demangleNumber(MangledName
);
1310 if (Error
|| IsNegative
|| StringByteSize
< (IsWcharT
? 2 : 1))
1311 goto StringLiteralError
;
1313 // CRC 32 (always 8 characters plus a terminator)
1314 CrcEndPos
= MangledName
.find('@');
1315 if (CrcEndPos
== StringView::npos
)
1316 goto StringLiteralError
;
1317 CRC
= MangledName
.substr(0, CrcEndPos
);
1318 MangledName
= MangledName
.dropFront(CrcEndPos
+ 1);
1319 if (MangledName
.empty())
1320 goto StringLiteralError
;
1323 Result
->Char
= CharKind::Wchar
;
1324 if (StringByteSize
> 64)
1325 Result
->IsTruncated
= true;
1327 while (!MangledName
.consumeFront('@')) {
1328 if (MangledName
.size() < 2)
1329 goto StringLiteralError
;
1330 wchar_t W
= demangleWcharLiteral(MangledName
);
1331 if (StringByteSize
!= 2 || Result
->IsTruncated
)
1332 outputEscapedChar(OS
, W
);
1333 StringByteSize
-= 2;
1335 goto StringLiteralError
;
1338 // The max byte length is actually 32, but some compilers mangled strings
1339 // incorrectly, so we have to assume it can go higher.
1340 constexpr unsigned MaxStringByteLength
= 32 * 4;
1341 uint8_t StringBytes
[MaxStringByteLength
];
1343 unsigned BytesDecoded
= 0;
1344 while (!MangledName
.consumeFront('@')) {
1345 if (MangledName
.size() < 1 || BytesDecoded
>= MaxStringByteLength
)
1346 goto StringLiteralError
;
1347 StringBytes
[BytesDecoded
++] = demangleCharLiteral(MangledName
);
1350 if (StringByteSize
> BytesDecoded
)
1351 Result
->IsTruncated
= true;
1353 unsigned CharBytes
=
1354 guessCharByteSize(StringBytes
, BytesDecoded
, StringByteSize
);
1355 assert(StringByteSize
% CharBytes
== 0);
1356 switch (CharBytes
) {
1358 Result
->Char
= CharKind::Char
;
1361 Result
->Char
= CharKind::Char16
;
1364 Result
->Char
= CharKind::Char32
;
1367 DEMANGLE_UNREACHABLE
;
1369 const unsigned NumChars
= BytesDecoded
/ CharBytes
;
1370 for (unsigned CharIndex
= 0; CharIndex
< NumChars
; ++CharIndex
) {
1372 decodeMultiByteChar(StringBytes
, CharIndex
, CharBytes
);
1373 if (CharIndex
+ 1 < NumChars
|| Result
->IsTruncated
)
1374 outputEscapedChar(OS
, NextChar
);
1379 ResultBuffer
= OS
.getBuffer();
1380 Result
->DecodedString
= copyString(ResultBuffer
);
1381 std::free(ResultBuffer
);
1386 std::free(OS
.getBuffer());
1390 // Returns MangledName's prefix before the first '@', or an error if
1391 // MangledName contains no '@' or the prefix has length 0.
1392 StringView
Demangler::demangleSimpleString(StringView
&MangledName
,
1395 for (size_t i
= 0; i
< MangledName
.size(); ++i
) {
1396 if (MangledName
[i
] != '@')
1400 S
= MangledName
.substr(0, i
);
1401 MangledName
= MangledName
.dropFront(i
+ 1);
1412 NamedIdentifierNode
*
1413 Demangler::demangleAnonymousNamespaceName(StringView
&MangledName
) {
1414 assert(MangledName
.startsWith("?A"));
1415 MangledName
.consumeFront("?A");
1417 NamedIdentifierNode
*Node
= Arena
.alloc
<NamedIdentifierNode
>();
1418 Node
->Name
= "`anonymous namespace'";
1419 size_t EndPos
= MangledName
.find('@');
1420 if (EndPos
== StringView::npos
) {
1424 StringView NamespaceKey
= MangledName
.substr(0, EndPos
);
1425 memorizeString(NamespaceKey
);
1426 MangledName
= MangledName
.substr(EndPos
+ 1);
1430 NamedIdentifierNode
*
1431 Demangler::demangleLocallyScopedNamePiece(StringView
&MangledName
) {
1432 assert(startsWithLocalScopePattern(MangledName
));
1434 NamedIdentifierNode
*Identifier
= Arena
.alloc
<NamedIdentifierNode
>();
1435 MangledName
.consumeFront('?');
1436 uint64_t Number
= 0;
1437 bool IsNegative
= false;
1438 std::tie(Number
, IsNegative
) = demangleNumber(MangledName
);
1439 assert(!IsNegative
);
1441 // One ? to terminate the number
1442 MangledName
.consumeFront('?');
1445 Node
*Scope
= parse(MangledName
);
1449 // Render the parent symbol's name into a buffer.
1451 if (!initializeOutputStream(nullptr, nullptr, OS
, 1024))
1452 // FIXME: Propagate out-of-memory as an error?
1455 Scope
->output(OS
, OF_Default
);
1457 OS
<< "::`" << Number
<< "'";
1459 char *Result
= OS
.getBuffer();
1460 Identifier
->Name
= copyString(Result
);
1465 // Parses a type name in the form of A@B@C@@ which represents C::B::A.
1467 Demangler::demangleFullyQualifiedTypeName(StringView
&MangledName
) {
1468 IdentifierNode
*Identifier
=
1469 demangleUnqualifiedTypeName(MangledName
, /*Memorize=*/true);
1474 QualifiedNameNode
*QN
= demangleNameScopeChain(MangledName
, Identifier
);
1481 // Parses a symbol name in the form of A@B@C@@ which represents C::B::A.
1482 // Symbol names have slightly different rules regarding what can appear
1483 // so we separate out the implementations for flexibility.
1485 Demangler::demangleFullyQualifiedSymbolName(StringView
&MangledName
) {
1486 // This is the final component of a symbol name (i.e. the leftmost component
1487 // of a mangled name. Since the only possible template instantiation that
1488 // can appear in this context is a function template, and since those are
1489 // not saved for the purposes of name backreferences, only backref simple
1491 IdentifierNode
*Identifier
=
1492 demangleUnqualifiedSymbolName(MangledName
, NBB_Simple
);
1496 QualifiedNameNode
*QN
= demangleNameScopeChain(MangledName
, Identifier
);
1500 if (Identifier
->kind() == NodeKind::StructorIdentifier
) {
1501 if (QN
->Components
->Count
< 2) {
1505 StructorIdentifierNode
*SIN
=
1506 static_cast<StructorIdentifierNode
*>(Identifier
);
1507 Node
*ClassNode
= QN
->Components
->Nodes
[QN
->Components
->Count
- 2];
1508 SIN
->Class
= static_cast<IdentifierNode
*>(ClassNode
);
1514 IdentifierNode
*Demangler::demangleUnqualifiedTypeName(StringView
&MangledName
,
1516 // An inner-most name can be a back-reference, because a fully-qualified name
1517 // (e.g. Scope + Inner) can contain other fully qualified names inside of
1518 // them (for example template parameters), and these nested parameters can
1519 // refer to previously mangled types.
1520 if (startsWithDigit(MangledName
))
1521 return demangleBackRefName(MangledName
);
1523 if (MangledName
.startsWith("?$"))
1524 return demangleTemplateInstantiationName(MangledName
, NBB_Template
);
1526 return demangleSimpleName(MangledName
, Memorize
);
1530 Demangler::demangleUnqualifiedSymbolName(StringView
&MangledName
,
1531 NameBackrefBehavior NBB
) {
1532 if (startsWithDigit(MangledName
))
1533 return demangleBackRefName(MangledName
);
1534 if (MangledName
.startsWith("?$"))
1535 return demangleTemplateInstantiationName(MangledName
, NBB
);
1536 if (MangledName
.startsWith('?'))
1537 return demangleFunctionIdentifierCode(MangledName
);
1538 return demangleSimpleName(MangledName
, /*Memorize=*/(NBB
& NBB_Simple
) != 0);
1541 IdentifierNode
*Demangler::demangleNameScopePiece(StringView
&MangledName
) {
1542 if (startsWithDigit(MangledName
))
1543 return demangleBackRefName(MangledName
);
1545 if (MangledName
.startsWith("?$"))
1546 return demangleTemplateInstantiationName(MangledName
, NBB_Template
);
1548 if (MangledName
.startsWith("?A"))
1549 return demangleAnonymousNamespaceName(MangledName
);
1551 if (startsWithLocalScopePattern(MangledName
))
1552 return demangleLocallyScopedNamePiece(MangledName
);
1554 return demangleSimpleName(MangledName
, /*Memorize=*/true);
1557 static NodeArrayNode
*nodeListToNodeArray(ArenaAllocator
&Arena
, NodeList
*Head
,
1559 NodeArrayNode
*N
= Arena
.alloc
<NodeArrayNode
>();
1561 N
->Nodes
= Arena
.allocArray
<Node
*>(Count
);
1562 for (size_t I
= 0; I
< Count
; ++I
) {
1563 N
->Nodes
[I
] = Head
->N
;
1570 Demangler::demangleNameScopeChain(StringView
&MangledName
,
1571 IdentifierNode
*UnqualifiedName
) {
1572 NodeList
*Head
= Arena
.alloc
<NodeList
>();
1574 Head
->N
= UnqualifiedName
;
1577 while (!MangledName
.consumeFront("@")) {
1579 NodeList
*NewHead
= Arena
.alloc
<NodeList
>();
1580 NewHead
->Next
= Head
;
1583 if (MangledName
.empty()) {
1589 IdentifierNode
*Elem
= demangleNameScopePiece(MangledName
);
1596 QualifiedNameNode
*QN
= Arena
.alloc
<QualifiedNameNode
>();
1597 QN
->Components
= nodeListToNodeArray(Arena
, Head
, Count
);
1601 FuncClass
Demangler::demangleFunctionClass(StringView
&MangledName
) {
1602 switch (MangledName
.popFront()) {
1604 return FuncClass(FC_ExternC
| FC_NoParameterList
);
1608 return FuncClass(FC_Private
| FC_Far
);
1610 return FuncClass(FC_Private
| FC_Static
);
1612 return FuncClass(FC_Private
| FC_Static
| FC_Far
);
1614 return FuncClass(FC_Private
| FC_Virtual
);
1616 return FuncClass(FC_Private
| FC_Virtual
| FC_Far
);
1618 return FuncClass(FC_Private
| FC_StaticThisAdjust
);
1620 return FuncClass(FC_Private
| FC_StaticThisAdjust
| FC_Far
);
1622 return FuncClass(FC_Protected
);
1624 return FuncClass(FC_Protected
| FC_Far
);
1626 return FuncClass(FC_Protected
| FC_Static
);
1628 return FuncClass(FC_Protected
| FC_Static
| FC_Far
);
1630 return FuncClass(FC_Protected
| FC_Virtual
);
1632 return FuncClass(FC_Protected
| FC_Virtual
| FC_Far
);
1634 return FuncClass(FC_Protected
| FC_Virtual
| FC_StaticThisAdjust
);
1636 return FuncClass(FC_Protected
| FC_Virtual
| FC_StaticThisAdjust
| FC_Far
);
1638 return FuncClass(FC_Public
);
1640 return FuncClass(FC_Public
| FC_Far
);
1642 return FuncClass(FC_Public
| FC_Static
);
1644 return FuncClass(FC_Public
| FC_Static
| FC_Far
);
1646 return FuncClass(FC_Public
| FC_Virtual
);
1648 return FuncClass(FC_Public
| FC_Virtual
| FC_Far
);
1650 return FuncClass(FC_Public
| FC_Virtual
| FC_StaticThisAdjust
);
1652 return FuncClass(FC_Public
| FC_Virtual
| FC_StaticThisAdjust
| FC_Far
);
1654 return FuncClass(FC_Global
);
1656 return FuncClass(FC_Global
| FC_Far
);
1658 FuncClass VFlag
= FC_VirtualThisAdjust
;
1659 if (MangledName
.consumeFront('R'))
1660 VFlag
= FuncClass(VFlag
| FC_VirtualThisAdjustEx
);
1661 if (MangledName
.empty())
1663 switch (MangledName
.popFront()) {
1665 return FuncClass(FC_Private
| FC_Virtual
| VFlag
);
1667 return FuncClass(FC_Private
| FC_Virtual
| VFlag
| FC_Far
);
1669 return FuncClass(FC_Protected
| FC_Virtual
| VFlag
);
1671 return FuncClass(FC_Protected
| FC_Virtual
| VFlag
| FC_Far
);
1673 return FuncClass(FC_Public
| FC_Virtual
| VFlag
);
1675 return FuncClass(FC_Public
| FC_Virtual
| VFlag
| FC_Far
);
1684 CallingConv
Demangler::demangleCallingConvention(StringView
&MangledName
) {
1685 if (MangledName
.empty()) {
1687 return CallingConv::None
;
1690 switch (MangledName
.popFront()) {
1693 return CallingConv::Cdecl
;
1696 return CallingConv::Pascal
;
1699 return CallingConv::Thiscall
;
1702 return CallingConv::Stdcall
;
1705 return CallingConv::Fastcall
;
1708 return CallingConv::Clrcall
;
1711 return CallingConv::Eabi
;
1713 return CallingConv::Vectorcall
;
1716 return CallingConv::None
;
1719 StorageClass
Demangler::demangleVariableStorageClass(StringView
&MangledName
) {
1720 assert(MangledName
.front() >= '0' && MangledName
.front() <= '4');
1722 switch (MangledName
.popFront()) {
1724 return StorageClass::PrivateStatic
;
1726 return StorageClass::ProtectedStatic
;
1728 return StorageClass::PublicStatic
;
1730 return StorageClass::Global
;
1732 return StorageClass::FunctionLocalStatic
;
1734 DEMANGLE_UNREACHABLE
;
1737 std::pair
<Qualifiers
, bool>
1738 Demangler::demangleQualifiers(StringView
&MangledName
) {
1739 if (MangledName
.empty()) {
1741 return std::make_pair(Q_None
, false);
1744 switch (MangledName
.popFront()) {
1745 // Member qualifiers
1747 return std::make_pair(Q_None
, true);
1749 return std::make_pair(Q_Const
, true);
1751 return std::make_pair(Q_Volatile
, true);
1753 return std::make_pair(Qualifiers(Q_Const
| Q_Volatile
), true);
1754 // Non-Member qualifiers
1756 return std::make_pair(Q_None
, false);
1758 return std::make_pair(Q_Const
, false);
1760 return std::make_pair(Q_Volatile
, false);
1762 return std::make_pair(Qualifiers(Q_Const
| Q_Volatile
), false);
1765 return std::make_pair(Q_None
, false);
1768 // <variable-type> ::= <type> <cvr-qualifiers>
1769 // ::= <type> <pointee-cvr-qualifiers> # pointers, references
1770 TypeNode
*Demangler::demangleType(StringView
&MangledName
,
1771 QualifierMangleMode QMM
) {
1772 Qualifiers Quals
= Q_None
;
1773 bool IsMember
= false;
1774 if (QMM
== QualifierMangleMode::Mangle
) {
1775 std::tie(Quals
, IsMember
) = demangleQualifiers(MangledName
);
1776 } else if (QMM
== QualifierMangleMode::Result
) {
1777 if (MangledName
.consumeFront('?'))
1778 std::tie(Quals
, IsMember
) = demangleQualifiers(MangledName
);
1781 if (MangledName
.empty()) {
1786 TypeNode
*Ty
= nullptr;
1787 if (isTagType(MangledName
))
1788 Ty
= demangleClassType(MangledName
);
1789 else if (isPointerType(MangledName
)) {
1790 if (isMemberPointer(MangledName
, Error
))
1791 Ty
= demangleMemberPointerType(MangledName
);
1793 Ty
= demanglePointerType(MangledName
);
1796 } else if (isArrayType(MangledName
))
1797 Ty
= demangleArrayType(MangledName
);
1798 else if (isFunctionType(MangledName
)) {
1799 if (MangledName
.consumeFront("$$A8@@"))
1800 Ty
= demangleFunctionType(MangledName
, true);
1802 assert(MangledName
.startsWith("$$A6"));
1803 MangledName
.consumeFront("$$A6");
1804 Ty
= demangleFunctionType(MangledName
, false);
1806 } else if (isCustomType(MangledName
)) {
1807 Ty
= demangleCustomType(MangledName
);
1809 Ty
= demanglePrimitiveType(MangledName
);
1814 Ty
->Quals
= Qualifiers(Ty
->Quals
| Quals
);
1818 bool Demangler::demangleThrowSpecification(StringView
&MangledName
) {
1819 if (MangledName
.consumeFront("_E"))
1821 if (MangledName
.consumeFront('Z'))
1828 FunctionSignatureNode
*Demangler::demangleFunctionType(StringView
&MangledName
,
1829 bool HasThisQuals
) {
1830 FunctionSignatureNode
*FTy
= Arena
.alloc
<FunctionSignatureNode
>();
1833 FTy
->Quals
= demanglePointerExtQualifiers(MangledName
);
1834 FTy
->RefQualifier
= demangleFunctionRefQualifier(MangledName
);
1835 FTy
->Quals
= Qualifiers(FTy
->Quals
| demangleQualifiers(MangledName
).first
);
1838 // Fields that appear on both member and non-member functions.
1839 FTy
->CallConvention
= demangleCallingConvention(MangledName
);
1841 // <return-type> ::= <type>
1842 // ::= @ # structors (they have no declared return type)
1843 bool IsStructor
= MangledName
.consumeFront('@');
1845 FTy
->ReturnType
= demangleType(MangledName
, QualifierMangleMode::Result
);
1847 FTy
->Params
= demangleFunctionParameterList(MangledName
, FTy
->IsVariadic
);
1849 FTy
->IsNoexcept
= demangleThrowSpecification(MangledName
);
1854 FunctionSymbolNode
*
1855 Demangler::demangleFunctionEncoding(StringView
&MangledName
) {
1856 FuncClass ExtraFlags
= FC_None
;
1857 if (MangledName
.consumeFront("$$J0"))
1858 ExtraFlags
= FC_ExternC
;
1860 if (MangledName
.empty()) {
1865 FuncClass FC
= demangleFunctionClass(MangledName
);
1866 FC
= FuncClass(ExtraFlags
| FC
);
1868 FunctionSignatureNode
*FSN
= nullptr;
1869 ThunkSignatureNode
*TTN
= nullptr;
1870 if (FC
& FC_StaticThisAdjust
) {
1871 TTN
= Arena
.alloc
<ThunkSignatureNode
>();
1872 TTN
->ThisAdjust
.StaticOffset
= demangleSigned(MangledName
);
1873 } else if (FC
& FC_VirtualThisAdjust
) {
1874 TTN
= Arena
.alloc
<ThunkSignatureNode
>();
1875 if (FC
& FC_VirtualThisAdjustEx
) {
1876 TTN
->ThisAdjust
.VBPtrOffset
= demangleSigned(MangledName
);
1877 TTN
->ThisAdjust
.VBOffsetOffset
= demangleSigned(MangledName
);
1879 TTN
->ThisAdjust
.VtordispOffset
= demangleSigned(MangledName
);
1880 TTN
->ThisAdjust
.StaticOffset
= demangleSigned(MangledName
);
1883 if (FC
& FC_NoParameterList
) {
1884 // This is an extern "C" function whose full signature hasn't been mangled.
1885 // This happens when we need to mangle a local symbol inside of an extern
1887 FSN
= Arena
.alloc
<FunctionSignatureNode
>();
1889 bool HasThisQuals
= !(FC
& (FC_Global
| FC_Static
));
1890 FSN
= demangleFunctionType(MangledName
, HasThisQuals
);
1897 *static_cast<FunctionSignatureNode
*>(TTN
) = *FSN
;
1900 FSN
->FunctionClass
= FC
;
1902 FunctionSymbolNode
*Symbol
= Arena
.alloc
<FunctionSymbolNode
>();
1903 Symbol
->Signature
= FSN
;
1907 CustomTypeNode
*Demangler::demangleCustomType(StringView
&MangledName
) {
1908 assert(MangledName
.startsWith('?'));
1909 MangledName
.popFront();
1911 CustomTypeNode
*CTN
= Arena
.alloc
<CustomTypeNode
>();
1912 CTN
->Identifier
= demangleUnqualifiedTypeName(MangledName
, /*Memorize=*/true);
1913 if (!MangledName
.consumeFront('@'))
1920 // Reads a primitive type.
1921 PrimitiveTypeNode
*Demangler::demanglePrimitiveType(StringView
&MangledName
) {
1922 if (MangledName
.consumeFront("$$T"))
1923 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Nullptr
);
1925 switch (MangledName
.popFront()) {
1927 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Void
);
1929 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char
);
1931 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Schar
);
1933 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Uchar
);
1935 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Short
);
1937 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Ushort
);
1939 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Int
);
1941 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Uint
);
1943 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Long
);
1945 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Ulong
);
1947 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Float
);
1949 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Double
);
1951 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Ldouble
);
1953 if (MangledName
.empty()) {
1957 switch (MangledName
.popFront()) {
1959 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Bool
);
1961 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Int64
);
1963 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Uint64
);
1965 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Wchar
);
1967 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char8
);
1969 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char16
);
1971 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char32
);
1980 TagTypeNode
*Demangler::demangleClassType(StringView
&MangledName
) {
1981 TagTypeNode
*TT
= nullptr;
1983 switch (MangledName
.popFront()) {
1985 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Union
);
1988 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Struct
);
1991 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Class
);
1994 if (!MangledName
.consumeFront('4')) {
1998 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Enum
);
2004 TT
->QualifiedName
= demangleFullyQualifiedTypeName(MangledName
);
2008 // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type>
2009 // # the E is required for 64-bit non-static pointers
2010 PointerTypeNode
*Demangler::demanglePointerType(StringView
&MangledName
) {
2011 PointerTypeNode
*Pointer
= Arena
.alloc
<PointerTypeNode
>();
2013 std::tie(Pointer
->Quals
, Pointer
->Affinity
) =
2014 demanglePointerCVQualifiers(MangledName
);
2016 if (MangledName
.consumeFront("6")) {
2017 Pointer
->Pointee
= demangleFunctionType(MangledName
, false);
2021 Qualifiers ExtQuals
= demanglePointerExtQualifiers(MangledName
);
2022 Pointer
->Quals
= Qualifiers(Pointer
->Quals
| ExtQuals
);
2024 Pointer
->Pointee
= demangleType(MangledName
, QualifierMangleMode::Mangle
);
2028 PointerTypeNode
*Demangler::demangleMemberPointerType(StringView
&MangledName
) {
2029 PointerTypeNode
*Pointer
= Arena
.alloc
<PointerTypeNode
>();
2031 std::tie(Pointer
->Quals
, Pointer
->Affinity
) =
2032 demanglePointerCVQualifiers(MangledName
);
2033 assert(Pointer
->Affinity
== PointerAffinity::Pointer
);
2035 Qualifiers ExtQuals
= demanglePointerExtQualifiers(MangledName
);
2036 Pointer
->Quals
= Qualifiers(Pointer
->Quals
| ExtQuals
);
2038 // isMemberPointer() only returns true if there is at least one character
2039 // after the qualifiers.
2040 if (MangledName
.consumeFront("8")) {
2041 Pointer
->ClassParent
= demangleFullyQualifiedTypeName(MangledName
);
2042 Pointer
->Pointee
= demangleFunctionType(MangledName
, true);
2044 Qualifiers PointeeQuals
= Q_None
;
2045 bool IsMember
= false;
2046 std::tie(PointeeQuals
, IsMember
) = demangleQualifiers(MangledName
);
2047 assert(IsMember
|| Error
);
2048 Pointer
->ClassParent
= demangleFullyQualifiedTypeName(MangledName
);
2050 Pointer
->Pointee
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2051 if (Pointer
->Pointee
)
2052 Pointer
->Pointee
->Quals
= PointeeQuals
;
2058 Qualifiers
Demangler::demanglePointerExtQualifiers(StringView
&MangledName
) {
2059 Qualifiers Quals
= Q_None
;
2060 if (MangledName
.consumeFront('E'))
2061 Quals
= Qualifiers(Quals
| Q_Pointer64
);
2062 if (MangledName
.consumeFront('I'))
2063 Quals
= Qualifiers(Quals
| Q_Restrict
);
2064 if (MangledName
.consumeFront('F'))
2065 Quals
= Qualifiers(Quals
| Q_Unaligned
);
2070 ArrayTypeNode
*Demangler::demangleArrayType(StringView
&MangledName
) {
2071 assert(MangledName
.front() == 'Y');
2072 MangledName
.popFront();
2075 bool IsNegative
= false;
2076 std::tie(Rank
, IsNegative
) = demangleNumber(MangledName
);
2077 if (IsNegative
|| Rank
== 0) {
2082 ArrayTypeNode
*ATy
= Arena
.alloc
<ArrayTypeNode
>();
2083 NodeList
*Head
= Arena
.alloc
<NodeList
>();
2084 NodeList
*Tail
= Head
;
2086 for (uint64_t I
= 0; I
< Rank
; ++I
) {
2088 std::tie(D
, IsNegative
) = demangleNumber(MangledName
);
2089 if (Error
|| IsNegative
) {
2093 Tail
->N
= Arena
.alloc
<IntegerLiteralNode
>(D
, IsNegative
);
2095 Tail
->Next
= Arena
.alloc
<NodeList
>();
2099 ATy
->Dimensions
= nodeListToNodeArray(Arena
, Head
, Rank
);
2101 if (MangledName
.consumeFront("$$C")) {
2102 bool IsMember
= false;
2103 std::tie(ATy
->Quals
, IsMember
) = demangleQualifiers(MangledName
);
2110 ATy
->ElementType
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2114 // Reads a function's parameters.
2115 NodeArrayNode
*Demangler::demangleFunctionParameterList(StringView
&MangledName
,
2117 // Empty parameter list.
2118 if (MangledName
.consumeFront('X'))
2121 NodeList
*Head
= Arena
.alloc
<NodeList
>();
2122 NodeList
**Current
= &Head
;
2124 while (!Error
&& !MangledName
.startsWith('@') &&
2125 !MangledName
.startsWith('Z')) {
2128 if (startsWithDigit(MangledName
)) {
2129 size_t N
= MangledName
[0] - '0';
2130 if (N
>= Backrefs
.FunctionParamCount
) {
2134 MangledName
= MangledName
.dropFront();
2136 *Current
= Arena
.alloc
<NodeList
>();
2137 (*Current
)->N
= Backrefs
.FunctionParams
[N
];
2138 Current
= &(*Current
)->Next
;
2142 size_t OldSize
= MangledName
.size();
2144 *Current
= Arena
.alloc
<NodeList
>();
2145 TypeNode
*TN
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2151 size_t CharsConsumed
= OldSize
- MangledName
.size();
2152 assert(CharsConsumed
!= 0);
2154 // Single-letter types are ignored for backreferences because memorizing
2155 // them doesn't save anything.
2156 if (Backrefs
.FunctionParamCount
<= 9 && CharsConsumed
> 1)
2157 Backrefs
.FunctionParams
[Backrefs
.FunctionParamCount
++] = TN
;
2159 Current
= &(*Current
)->Next
;
2165 NodeArrayNode
*NA
= nodeListToNodeArray(Arena
, Head
, Count
);
2166 // A non-empty parameter list is terminated by either 'Z' (variadic) parameter
2167 // list or '@' (non variadic). Careful not to consume "@Z", as in that case
2168 // the following Z could be a throw specifier.
2169 if (MangledName
.consumeFront('@'))
2172 if (MangledName
.consumeFront('Z')) {
2177 DEMANGLE_UNREACHABLE
;
2181 Demangler::demangleTemplateParameterList(StringView
&MangledName
) {
2183 NodeList
**Current
= &Head
;
2186 while (!MangledName
.startsWith('@')) {
2187 if (MangledName
.consumeFront("$S") || MangledName
.consumeFront("$$V") ||
2188 MangledName
.consumeFront("$$$V") || MangledName
.consumeFront("$$Z")) {
2189 // parameter pack separator
2195 // Template parameter lists don't participate in back-referencing.
2196 *Current
= Arena
.alloc
<NodeList
>();
2198 NodeList
&TP
= **Current
;
2200 TemplateParameterReferenceNode
*TPRN
= nullptr;
2201 if (MangledName
.consumeFront("$$Y")) {
2203 TP
.N
= demangleFullyQualifiedTypeName(MangledName
);
2204 } else if (MangledName
.consumeFront("$$B")) {
2206 TP
.N
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2207 } else if (MangledName
.consumeFront("$$C")) {
2208 // Type has qualifiers.
2209 TP
.N
= demangleType(MangledName
, QualifierMangleMode::Mangle
);
2210 } else if (MangledName
.startsWith("$1") || MangledName
.startsWith("$H") ||
2211 MangledName
.startsWith("$I") || MangledName
.startsWith("$J")) {
2212 // Pointer to member
2213 TP
.N
= TPRN
= Arena
.alloc
<TemplateParameterReferenceNode
>();
2214 TPRN
->IsMemberPointer
= true;
2216 MangledName
= MangledName
.dropFront();
2217 // 1 - single inheritance <name>
2218 // H - multiple inheritance <name> <number>
2219 // I - virtual inheritance <name> <number> <number>
2220 // J - unspecified inheritance <name> <number> <number> <number>
2221 char InheritanceSpecifier
= MangledName
.popFront();
2222 SymbolNode
*S
= nullptr;
2223 if (MangledName
.startsWith('?')) {
2224 S
= parse(MangledName
);
2225 if (Error
|| !S
->Name
) {
2229 memorizeIdentifier(S
->Name
->getUnqualifiedIdentifier());
2232 switch (InheritanceSpecifier
) {
2234 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2235 demangleSigned(MangledName
);
2236 DEMANGLE_FALLTHROUGH
;
2238 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2239 demangleSigned(MangledName
);
2240 DEMANGLE_FALLTHROUGH
;
2242 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2243 demangleSigned(MangledName
);
2244 DEMANGLE_FALLTHROUGH
;
2248 DEMANGLE_UNREACHABLE
;
2250 TPRN
->Affinity
= PointerAffinity::Pointer
;
2252 } else if (MangledName
.startsWith("$E?")) {
2253 MangledName
.consumeFront("$E");
2254 // Reference to symbol
2255 TP
.N
= TPRN
= Arena
.alloc
<TemplateParameterReferenceNode
>();
2256 TPRN
->Symbol
= parse(MangledName
);
2257 TPRN
->Affinity
= PointerAffinity::Reference
;
2258 } else if (MangledName
.startsWith("$F") || MangledName
.startsWith("$G")) {
2259 TP
.N
= TPRN
= Arena
.alloc
<TemplateParameterReferenceNode
>();
2261 // Data member pointer.
2262 MangledName
= MangledName
.dropFront();
2263 char InheritanceSpecifier
= MangledName
.popFront();
2265 switch (InheritanceSpecifier
) {
2267 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2268 demangleSigned(MangledName
);
2269 DEMANGLE_FALLTHROUGH
;
2271 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2272 demangleSigned(MangledName
);
2273 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2274 demangleSigned(MangledName
);
2277 DEMANGLE_UNREACHABLE
;
2279 TPRN
->IsMemberPointer
= true;
2281 } else if (MangledName
.consumeFront("$0")) {
2282 // Integral non-type template parameter
2283 bool IsNegative
= false;
2285 std::tie(Value
, IsNegative
) = demangleNumber(MangledName
);
2287 TP
.N
= Arena
.alloc
<IntegerLiteralNode
>(Value
, IsNegative
);
2289 TP
.N
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2297 // The loop above returns nullptr on Error.
2300 // Template parameter lists cannot be variadic, so it can only be terminated
2301 // by @ (as opposed to 'Z' in the function parameter case).
2302 assert(MangledName
.startsWith('@')); // The above loop exits only on '@'.
2303 MangledName
.consumeFront('@');
2304 return nodeListToNodeArray(Arena
, Head
, Count
);
2307 void Demangler::dumpBackReferences() {
2308 std::printf("%d function parameter backreferences\n",
2309 (int)Backrefs
.FunctionParamCount
);
2311 // Create an output stream so we can render each type.
2313 if (!initializeOutputStream(nullptr, nullptr, OS
, 1024))
2315 for (size_t I
= 0; I
< Backrefs
.FunctionParamCount
; ++I
) {
2316 OS
.setCurrentPosition(0);
2318 TypeNode
*T
= Backrefs
.FunctionParams
[I
];
2319 T
->output(OS
, OF_Default
);
2321 std::printf(" [%d] - %.*s\n", (int)I
, (int)OS
.getCurrentPosition(),
2324 std::free(OS
.getBuffer());
2326 if (Backrefs
.FunctionParamCount
> 0)
2328 std::printf("%d name backreferences\n", (int)Backrefs
.NamesCount
);
2329 for (size_t I
= 0; I
< Backrefs
.NamesCount
; ++I
) {
2330 std::printf(" [%d] - %.*s\n", (int)I
, (int)Backrefs
.Names
[I
]->Name
.size(),
2331 Backrefs
.Names
[I
]->Name
.begin());
2333 if (Backrefs
.NamesCount
> 0)
2337 char *llvm::microsoftDemangle(const char *MangledName
, char *Buf
, size_t *N
,
2338 int *Status
, MSDemangleFlags Flags
) {
2339 int InternalStatus
= demangle_success
;
2343 StringView Name
{MangledName
};
2344 SymbolNode
*AST
= D
.parse(Name
);
2346 if (Flags
& MSDF_DumpBackrefs
)
2347 D
.dumpBackReferences();
2350 InternalStatus
= demangle_invalid_mangled_name
;
2351 else if (!initializeOutputStream(Buf
, N
, S
, 1024))
2352 InternalStatus
= demangle_memory_alloc_failure
;
2354 AST
->output(S
, OF_Default
);
2357 *N
= S
.getCurrentPosition();
2358 Buf
= S
.getBuffer();
2362 *Status
= InternalStatus
;
2363 return InternalStatus
== demangle_success
? Buf
: nullptr;