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());
249 std::memcpy(Stable
, Borrowed
.begin(), Borrowed
.size());
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")) {
830 MangledName
.consumeFront(".?A");
831 if (MangledName
.empty()) {
836 return demangleClassType(MangledName
);
839 // <type-encoding> ::= <storage-class> <variable-type>
840 // <storage-class> ::= 0 # private static member
841 // ::= 1 # protected static member
842 // ::= 2 # public static member
844 // ::= 4 # static local
846 VariableSymbolNode
*Demangler::demangleVariableEncoding(StringView
&MangledName
,
848 VariableSymbolNode
*VSN
= Arena
.alloc
<VariableSymbolNode
>();
850 VSN
->Type
= demangleType(MangledName
, QualifierMangleMode::Drop
);
856 // <variable-type> ::= <type> <cvr-qualifiers>
857 // ::= <type> <pointee-cvr-qualifiers> # pointers, references
858 switch (VSN
->Type
->kind()) {
859 case NodeKind::PointerType
: {
860 PointerTypeNode
*PTN
= static_cast<PointerTypeNode
*>(VSN
->Type
);
862 Qualifiers ExtraChildQuals
= Q_None
;
863 PTN
->Quals
= Qualifiers(VSN
->Type
->Quals
|
864 demanglePointerExtQualifiers(MangledName
));
866 bool IsMember
= false;
867 std::tie(ExtraChildQuals
, IsMember
) = demangleQualifiers(MangledName
);
869 if (PTN
->ClassParent
) {
870 QualifiedNameNode
*BackRefName
=
871 demangleFullyQualifiedTypeName(MangledName
);
874 PTN
->Pointee
->Quals
= Qualifiers(PTN
->Pointee
->Quals
| ExtraChildQuals
);
879 VSN
->Type
->Quals
= demangleQualifiers(MangledName
).first
;
886 // Sometimes numbers are encoded in mangled symbols. For example,
887 // "int (*x)[20]" is a valid C type (x is a pointer to an array of
888 // length 20), so we need some way to embed numbers as part of symbols.
889 // This function parses it.
891 // <number> ::= [?] <non-negative integer>
893 // <non-negative integer> ::= <decimal digit> # when 1 <= Number <= 10
894 // ::= <hex digit>+ @ # when Number == 0 or >= 10
896 // <hex-digit> ::= [A-P] # A = 0, B = 1, ...
897 std::pair
<uint64_t, bool> Demangler::demangleNumber(StringView
&MangledName
) {
898 bool IsNegative
= MangledName
.consumeFront('?');
900 if (startsWithDigit(MangledName
)) {
901 uint64_t Ret
= MangledName
[0] - '0' + 1;
902 MangledName
= MangledName
.dropFront(1);
903 return {Ret
, IsNegative
};
907 for (size_t i
= 0; i
< MangledName
.size(); ++i
) {
908 char C
= MangledName
[i
];
910 MangledName
= MangledName
.dropFront(i
+ 1);
911 return {Ret
, IsNegative
};
913 if ('A' <= C
&& C
<= 'P') {
914 Ret
= (Ret
<< 4) + (C
- 'A');
921 return {0ULL, false};
924 uint64_t Demangler::demangleUnsigned(StringView
&MangledName
) {
925 bool IsNegative
= false;
927 std::tie(Number
, IsNegative
) = demangleNumber(MangledName
);
933 int64_t Demangler::demangleSigned(StringView
&MangledName
) {
934 bool IsNegative
= false;
936 std::tie(Number
, IsNegative
) = demangleNumber(MangledName
);
937 if (Number
> INT64_MAX
)
939 int64_t I
= static_cast<int64_t>(Number
);
940 return IsNegative
? -I
: I
;
943 // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
945 void Demangler::memorizeString(StringView S
) {
946 if (Backrefs
.NamesCount
>= BackrefContext::Max
)
948 for (size_t i
= 0; i
< Backrefs
.NamesCount
; ++i
)
949 if (S
== Backrefs
.Names
[i
]->Name
)
951 NamedIdentifierNode
*N
= Arena
.alloc
<NamedIdentifierNode
>();
953 Backrefs
.Names
[Backrefs
.NamesCount
++] = N
;
956 NamedIdentifierNode
*Demangler::demangleBackRefName(StringView
&MangledName
) {
957 assert(startsWithDigit(MangledName
));
959 size_t I
= MangledName
[0] - '0';
960 if (I
>= Backrefs
.NamesCount
) {
965 MangledName
= MangledName
.dropFront();
966 return Backrefs
.Names
[I
];
969 void Demangler::memorizeIdentifier(IdentifierNode
*Identifier
) {
970 // Render this class template name into a string buffer so that we can
971 // memorize it for the purpose of back-referencing.
973 if (!initializeOutputBuffer(nullptr, nullptr, OB
, 1024))
974 // FIXME: Propagate out-of-memory as an error?
976 Identifier
->output(OB
, OF_Default
);
977 StringView Owned
= copyString(OB
);
978 memorizeString(Owned
);
979 std::free(OB
.getBuffer());
983 Demangler::demangleTemplateInstantiationName(StringView
&MangledName
,
984 NameBackrefBehavior NBB
) {
985 assert(MangledName
.startsWith("?$"));
986 MangledName
.consumeFront("?$");
988 BackrefContext OuterContext
;
989 std::swap(OuterContext
, Backrefs
);
991 IdentifierNode
*Identifier
=
992 demangleUnqualifiedSymbolName(MangledName
, NBB_Simple
);
994 Identifier
->TemplateParams
= demangleTemplateParameterList(MangledName
);
996 std::swap(OuterContext
, Backrefs
);
1000 if (NBB
& NBB_Template
) {
1001 // NBB_Template is only set for types and non-leaf names ("a::" in "a::b").
1002 // Structors and conversion operators only makes sense in a leaf name, so
1003 // reject them in NBB_Template contexts.
1004 if (Identifier
->kind() == NodeKind::ConversionOperatorIdentifier
||
1005 Identifier
->kind() == NodeKind::StructorIdentifier
) {
1010 memorizeIdentifier(Identifier
);
1016 NamedIdentifierNode
*Demangler::demangleSimpleName(StringView
&MangledName
,
1018 StringView S
= demangleSimpleString(MangledName
, Memorize
);
1022 NamedIdentifierNode
*Name
= Arena
.alloc
<NamedIdentifierNode
>();
1027 static bool isRebasedHexDigit(char C
) { return (C
>= 'A' && C
<= 'P'); }
1029 static uint8_t rebasedHexDigitToNumber(char C
) {
1030 assert(isRebasedHexDigit(C
));
1031 return (C
<= 'J') ? (C
- 'A') : (10 + C
- 'K');
1034 uint8_t Demangler::demangleCharLiteral(StringView
&MangledName
) {
1035 assert(!MangledName
.empty());
1036 if (!MangledName
.startsWith('?'))
1037 return MangledName
.popFront();
1039 MangledName
= MangledName
.dropFront();
1040 if (MangledName
.empty())
1041 goto CharLiteralError
;
1043 if (MangledName
.consumeFront('$')) {
1045 if (MangledName
.size() < 2)
1046 goto CharLiteralError
;
1047 StringView Nibbles
= MangledName
.substr(0, 2);
1048 if (!isRebasedHexDigit(Nibbles
[0]) || !isRebasedHexDigit(Nibbles
[1]))
1049 goto CharLiteralError
;
1050 // Don't append the null terminator.
1051 uint8_t C1
= rebasedHexDigitToNumber(Nibbles
[0]);
1052 uint8_t C2
= rebasedHexDigitToNumber(Nibbles
[1]);
1053 MangledName
= MangledName
.dropFront(2);
1054 return (C1
<< 4) | C2
;
1057 if (startsWithDigit(MangledName
)) {
1058 const char *Lookup
= ",/\\:. \n\t'-";
1059 char C
= Lookup
[MangledName
[0] - '0'];
1060 MangledName
= MangledName
.dropFront();
1064 if (MangledName
[0] >= 'a' && MangledName
[0] <= 'z') {
1065 char Lookup
[26] = {'\xE1', '\xE2', '\xE3', '\xE4', '\xE5', '\xE6', '\xE7',
1066 '\xE8', '\xE9', '\xEA', '\xEB', '\xEC', '\xED', '\xEE',
1067 '\xEF', '\xF0', '\xF1', '\xF2', '\xF3', '\xF4', '\xF5',
1068 '\xF6', '\xF7', '\xF8', '\xF9', '\xFA'};
1069 char C
= Lookup
[MangledName
[0] - 'a'];
1070 MangledName
= MangledName
.dropFront();
1074 if (MangledName
[0] >= 'A' && MangledName
[0] <= 'Z') {
1075 char Lookup
[26] = {'\xC1', '\xC2', '\xC3', '\xC4', '\xC5', '\xC6', '\xC7',
1076 '\xC8', '\xC9', '\xCA', '\xCB', '\xCC', '\xCD', '\xCE',
1077 '\xCF', '\xD0', '\xD1', '\xD2', '\xD3', '\xD4', '\xD5',
1078 '\xD6', '\xD7', '\xD8', '\xD9', '\xDA'};
1079 char C
= Lookup
[MangledName
[0] - 'A'];
1080 MangledName
= MangledName
.dropFront();
1089 wchar_t Demangler::demangleWcharLiteral(StringView
&MangledName
) {
1092 C1
= demangleCharLiteral(MangledName
);
1093 if (Error
|| MangledName
.empty())
1094 goto WCharLiteralError
;
1095 C2
= demangleCharLiteral(MangledName
);
1097 goto WCharLiteralError
;
1099 return ((wchar_t)C1
<< 8) | (wchar_t)C2
;
1106 static void writeHexDigit(char *Buffer
, uint8_t Digit
) {
1107 assert(Digit
<= 15);
1108 *Buffer
= (Digit
< 10) ? ('0' + Digit
) : ('A' + Digit
- 10);
1111 static void outputHex(OutputBuffer
&OB
, unsigned C
) {
1114 // It's easier to do the math if we can work from right to left, but we need
1115 // to print the numbers from left to right. So render this into a temporary
1116 // buffer first, then output the temporary buffer. Each byte is of the form
1117 // \xAB, which means that each byte needs 4 characters. Since there are at
1118 // most 4 bytes, we need a 4*4+1 = 17 character temporary buffer.
1119 char TempBuffer
[17];
1121 ::memset(TempBuffer
, 0, sizeof(TempBuffer
));
1122 constexpr int MaxPos
= sizeof(TempBuffer
) - 1;
1124 int Pos
= MaxPos
- 1; // TempBuffer[MaxPos] is the terminating \0.
1126 for (int I
= 0; I
< 2; ++I
) {
1127 writeHexDigit(&TempBuffer
[Pos
--], C
% 16);
1131 TempBuffer
[Pos
--] = 'x';
1133 TempBuffer
[Pos
--] = '\\';
1134 OB
<< StringView(&TempBuffer
[Pos
+ 1]);
1137 static void outputEscapedChar(OutputBuffer
&OB
, unsigned C
) {
1142 case '\'': // single quote
1145 case '\"': // double quote
1148 case '\\': // backslash
1154 case '\b': // backspace
1157 case '\f': // form feed
1160 case '\n': // new line
1163 case '\r': // carriage return
1169 case '\v': // vertical tab
1176 if (C
> 0x1F && C
< 0x7F) {
1177 // Standard ascii char.
1185 static unsigned countTrailingNullBytes(const uint8_t *StringBytes
, int Length
) {
1186 const uint8_t *End
= StringBytes
+ Length
- 1;
1188 while (Length
> 0 && *End
== 0) {
1196 static unsigned countEmbeddedNulls(const uint8_t *StringBytes
,
1198 unsigned Result
= 0;
1199 for (unsigned I
= 0; I
< Length
; ++I
) {
1200 if (*StringBytes
++ == 0)
1206 // A mangled (non-wide) string literal stores the total length of the string it
1207 // refers to (passed in NumBytes), and it contains up to 32 bytes of actual text
1208 // (passed in StringBytes, NumChars).
1209 static unsigned guessCharByteSize(const uint8_t *StringBytes
, unsigned NumChars
,
1210 uint64_t NumBytes
) {
1211 assert(NumBytes
> 0);
1213 // If the number of bytes is odd, this is guaranteed to be a char string.
1214 if (NumBytes
% 2 == 1)
1217 // All strings can encode at most 32 bytes of data. If it's less than that,
1218 // then we encoded the entire string. In this case we check for a 1-byte,
1219 // 2-byte, or 4-byte null terminator.
1220 if (NumBytes
< 32) {
1221 unsigned TrailingNulls
= countTrailingNullBytes(StringBytes
, NumChars
);
1222 if (TrailingNulls
>= 4 && NumBytes
% 4 == 0)
1224 if (TrailingNulls
>= 2)
1229 // The whole string was not able to be encoded. Try to look at embedded null
1230 // terminators to guess. The heuristic is that we count all embedded null
1231 // terminators. If more than 2/3 are null, it's a char32. If more than 1/3
1232 // are null, it's a char16. Otherwise it's a char8. This obviously isn't
1233 // perfect and is biased towards languages that have ascii alphabets, but this
1234 // was always going to be best effort since the encoding is lossy.
1235 unsigned Nulls
= countEmbeddedNulls(StringBytes
, NumChars
);
1236 if (Nulls
>= 2 * NumChars
/ 3 && NumBytes
% 4 == 0)
1238 if (Nulls
>= NumChars
/ 3)
1243 static unsigned decodeMultiByteChar(const uint8_t *StringBytes
,
1244 unsigned CharIndex
, unsigned CharBytes
) {
1245 assert(CharBytes
== 1 || CharBytes
== 2 || CharBytes
== 4);
1246 unsigned Offset
= CharIndex
* CharBytes
;
1247 unsigned Result
= 0;
1248 StringBytes
= StringBytes
+ Offset
;
1249 for (unsigned I
= 0; I
< CharBytes
; ++I
) {
1250 unsigned C
= static_cast<unsigned>(StringBytes
[I
]);
1251 Result
|= C
<< (8 * I
);
1256 FunctionSymbolNode
*Demangler::demangleVcallThunkNode(StringView
&MangledName
) {
1257 FunctionSymbolNode
*FSN
= Arena
.alloc
<FunctionSymbolNode
>();
1258 VcallThunkIdentifierNode
*VTIN
= Arena
.alloc
<VcallThunkIdentifierNode
>();
1259 FSN
->Signature
= Arena
.alloc
<ThunkSignatureNode
>();
1260 FSN
->Signature
->FunctionClass
= FC_NoParameterList
;
1262 FSN
->Name
= demangleNameScopeChain(MangledName
, VTIN
);
1264 Error
= !MangledName
.consumeFront("$B");
1266 VTIN
->OffsetInVTable
= demangleUnsigned(MangledName
);
1268 Error
= !MangledName
.consumeFront('A');
1270 FSN
->Signature
->CallConvention
= demangleCallingConvention(MangledName
);
1271 return (Error
) ? nullptr : FSN
;
1274 EncodedStringLiteralNode
*
1275 Demangler::demangleStringLiteral(StringView
&MangledName
) {
1276 // This function uses goto, so declare all variables up front.
1279 uint64_t StringByteSize
;
1280 bool IsWcharT
= false;
1281 bool IsNegative
= false;
1282 size_t CrcEndPos
= 0;
1284 EncodedStringLiteralNode
*Result
= Arena
.alloc
<EncodedStringLiteralNode
>();
1286 // Must happen before the first `goto StringLiteralError`.
1287 if (!initializeOutputBuffer(nullptr, nullptr, OB
, 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(OB
, 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(OB
, NextChar
);
1378 Result
->DecodedString
= copyString(OB
);
1379 std::free(OB
.getBuffer());
1384 std::free(OB
.getBuffer());
1388 // Returns MangledName's prefix before the first '@', or an error if
1389 // MangledName contains no '@' or the prefix has length 0.
1390 StringView
Demangler::demangleSimpleString(StringView
&MangledName
,
1393 for (size_t i
= 0; i
< MangledName
.size(); ++i
) {
1394 if (MangledName
[i
] != '@')
1398 S
= MangledName
.substr(0, i
);
1399 MangledName
= MangledName
.dropFront(i
+ 1);
1410 NamedIdentifierNode
*
1411 Demangler::demangleAnonymousNamespaceName(StringView
&MangledName
) {
1412 assert(MangledName
.startsWith("?A"));
1413 MangledName
.consumeFront("?A");
1415 NamedIdentifierNode
*Node
= Arena
.alloc
<NamedIdentifierNode
>();
1416 Node
->Name
= "`anonymous namespace'";
1417 size_t EndPos
= MangledName
.find('@');
1418 if (EndPos
== StringView::npos
) {
1422 StringView NamespaceKey
= MangledName
.substr(0, EndPos
);
1423 memorizeString(NamespaceKey
);
1424 MangledName
= MangledName
.substr(EndPos
+ 1);
1428 NamedIdentifierNode
*
1429 Demangler::demangleLocallyScopedNamePiece(StringView
&MangledName
) {
1430 assert(startsWithLocalScopePattern(MangledName
));
1432 NamedIdentifierNode
*Identifier
= Arena
.alloc
<NamedIdentifierNode
>();
1433 MangledName
.consumeFront('?');
1434 uint64_t Number
= 0;
1435 bool IsNegative
= false;
1436 std::tie(Number
, IsNegative
) = demangleNumber(MangledName
);
1437 assert(!IsNegative
);
1439 // One ? to terminate the number
1440 MangledName
.consumeFront('?');
1443 Node
*Scope
= parse(MangledName
);
1447 // Render the parent symbol's name into a buffer.
1449 if (!initializeOutputBuffer(nullptr, nullptr, OB
, 1024))
1450 // FIXME: Propagate out-of-memory as an error?
1453 Scope
->output(OB
, OF_Default
);
1455 OB
<< "::`" << Number
<< "'";
1457 Identifier
->Name
= copyString(OB
);
1458 std::free(OB
.getBuffer());
1462 // Parses a type name in the form of A@B@C@@ which represents C::B::A.
1464 Demangler::demangleFullyQualifiedTypeName(StringView
&MangledName
) {
1465 IdentifierNode
*Identifier
=
1466 demangleUnqualifiedTypeName(MangledName
, /*Memorize=*/true);
1471 QualifiedNameNode
*QN
= demangleNameScopeChain(MangledName
, Identifier
);
1478 // Parses a symbol name in the form of A@B@C@@ which represents C::B::A.
1479 // Symbol names have slightly different rules regarding what can appear
1480 // so we separate out the implementations for flexibility.
1482 Demangler::demangleFullyQualifiedSymbolName(StringView
&MangledName
) {
1483 // This is the final component of a symbol name (i.e. the leftmost component
1484 // of a mangled name. Since the only possible template instantiation that
1485 // can appear in this context is a function template, and since those are
1486 // not saved for the purposes of name backreferences, only backref simple
1488 IdentifierNode
*Identifier
=
1489 demangleUnqualifiedSymbolName(MangledName
, NBB_Simple
);
1493 QualifiedNameNode
*QN
= demangleNameScopeChain(MangledName
, Identifier
);
1497 if (Identifier
->kind() == NodeKind::StructorIdentifier
) {
1498 if (QN
->Components
->Count
< 2) {
1502 StructorIdentifierNode
*SIN
=
1503 static_cast<StructorIdentifierNode
*>(Identifier
);
1504 Node
*ClassNode
= QN
->Components
->Nodes
[QN
->Components
->Count
- 2];
1505 SIN
->Class
= static_cast<IdentifierNode
*>(ClassNode
);
1511 IdentifierNode
*Demangler::demangleUnqualifiedTypeName(StringView
&MangledName
,
1513 // An inner-most name can be a back-reference, because a fully-qualified name
1514 // (e.g. Scope + Inner) can contain other fully qualified names inside of
1515 // them (for example template parameters), and these nested parameters can
1516 // refer to previously mangled types.
1517 if (startsWithDigit(MangledName
))
1518 return demangleBackRefName(MangledName
);
1520 if (MangledName
.startsWith("?$"))
1521 return demangleTemplateInstantiationName(MangledName
, NBB_Template
);
1523 return demangleSimpleName(MangledName
, Memorize
);
1527 Demangler::demangleUnqualifiedSymbolName(StringView
&MangledName
,
1528 NameBackrefBehavior NBB
) {
1529 if (startsWithDigit(MangledName
))
1530 return demangleBackRefName(MangledName
);
1531 if (MangledName
.startsWith("?$"))
1532 return demangleTemplateInstantiationName(MangledName
, NBB
);
1533 if (MangledName
.startsWith('?'))
1534 return demangleFunctionIdentifierCode(MangledName
);
1535 return demangleSimpleName(MangledName
, /*Memorize=*/(NBB
& NBB_Simple
) != 0);
1538 IdentifierNode
*Demangler::demangleNameScopePiece(StringView
&MangledName
) {
1539 if (startsWithDigit(MangledName
))
1540 return demangleBackRefName(MangledName
);
1542 if (MangledName
.startsWith("?$"))
1543 return demangleTemplateInstantiationName(MangledName
, NBB_Template
);
1545 if (MangledName
.startsWith("?A"))
1546 return demangleAnonymousNamespaceName(MangledName
);
1548 if (startsWithLocalScopePattern(MangledName
))
1549 return demangleLocallyScopedNamePiece(MangledName
);
1551 return demangleSimpleName(MangledName
, /*Memorize=*/true);
1554 static NodeArrayNode
*nodeListToNodeArray(ArenaAllocator
&Arena
, NodeList
*Head
,
1556 NodeArrayNode
*N
= Arena
.alloc
<NodeArrayNode
>();
1558 N
->Nodes
= Arena
.allocArray
<Node
*>(Count
);
1559 for (size_t I
= 0; I
< Count
; ++I
) {
1560 N
->Nodes
[I
] = Head
->N
;
1567 Demangler::demangleNameScopeChain(StringView
&MangledName
,
1568 IdentifierNode
*UnqualifiedName
) {
1569 NodeList
*Head
= Arena
.alloc
<NodeList
>();
1571 Head
->N
= UnqualifiedName
;
1574 while (!MangledName
.consumeFront("@")) {
1576 NodeList
*NewHead
= Arena
.alloc
<NodeList
>();
1577 NewHead
->Next
= Head
;
1580 if (MangledName
.empty()) {
1586 IdentifierNode
*Elem
= demangleNameScopePiece(MangledName
);
1593 QualifiedNameNode
*QN
= Arena
.alloc
<QualifiedNameNode
>();
1594 QN
->Components
= nodeListToNodeArray(Arena
, Head
, Count
);
1598 FuncClass
Demangler::demangleFunctionClass(StringView
&MangledName
) {
1599 switch (MangledName
.popFront()) {
1601 return FuncClass(FC_ExternC
| FC_NoParameterList
);
1605 return FuncClass(FC_Private
| FC_Far
);
1607 return FuncClass(FC_Private
| FC_Static
);
1609 return FuncClass(FC_Private
| FC_Static
| FC_Far
);
1611 return FuncClass(FC_Private
| FC_Virtual
);
1613 return FuncClass(FC_Private
| FC_Virtual
| FC_Far
);
1615 return FuncClass(FC_Private
| FC_StaticThisAdjust
);
1617 return FuncClass(FC_Private
| FC_StaticThisAdjust
| FC_Far
);
1619 return FuncClass(FC_Protected
);
1621 return FuncClass(FC_Protected
| FC_Far
);
1623 return FuncClass(FC_Protected
| FC_Static
);
1625 return FuncClass(FC_Protected
| FC_Static
| FC_Far
);
1627 return FuncClass(FC_Protected
| FC_Virtual
);
1629 return FuncClass(FC_Protected
| FC_Virtual
| FC_Far
);
1631 return FuncClass(FC_Protected
| FC_Virtual
| FC_StaticThisAdjust
);
1633 return FuncClass(FC_Protected
| FC_Virtual
| FC_StaticThisAdjust
| FC_Far
);
1635 return FuncClass(FC_Public
);
1637 return FuncClass(FC_Public
| FC_Far
);
1639 return FuncClass(FC_Public
| FC_Static
);
1641 return FuncClass(FC_Public
| FC_Static
| FC_Far
);
1643 return FuncClass(FC_Public
| FC_Virtual
);
1645 return FuncClass(FC_Public
| FC_Virtual
| FC_Far
);
1647 return FuncClass(FC_Public
| FC_Virtual
| FC_StaticThisAdjust
);
1649 return FuncClass(FC_Public
| FC_Virtual
| FC_StaticThisAdjust
| FC_Far
);
1651 return FuncClass(FC_Global
);
1653 return FuncClass(FC_Global
| FC_Far
);
1655 FuncClass VFlag
= FC_VirtualThisAdjust
;
1656 if (MangledName
.consumeFront('R'))
1657 VFlag
= FuncClass(VFlag
| FC_VirtualThisAdjustEx
);
1658 if (MangledName
.empty())
1660 switch (MangledName
.popFront()) {
1662 return FuncClass(FC_Private
| FC_Virtual
| VFlag
);
1664 return FuncClass(FC_Private
| FC_Virtual
| VFlag
| FC_Far
);
1666 return FuncClass(FC_Protected
| FC_Virtual
| VFlag
);
1668 return FuncClass(FC_Protected
| FC_Virtual
| VFlag
| FC_Far
);
1670 return FuncClass(FC_Public
| FC_Virtual
| VFlag
);
1672 return FuncClass(FC_Public
| FC_Virtual
| VFlag
| FC_Far
);
1681 CallingConv
Demangler::demangleCallingConvention(StringView
&MangledName
) {
1682 if (MangledName
.empty()) {
1684 return CallingConv::None
;
1687 switch (MangledName
.popFront()) {
1690 return CallingConv::Cdecl
;
1693 return CallingConv::Pascal
;
1696 return CallingConv::Thiscall
;
1699 return CallingConv::Stdcall
;
1702 return CallingConv::Fastcall
;
1705 return CallingConv::Clrcall
;
1708 return CallingConv::Eabi
;
1710 return CallingConv::Vectorcall
;
1712 return CallingConv::Swift
;
1714 return CallingConv::SwiftAsync
;
1717 return CallingConv::None
;
1720 StorageClass
Demangler::demangleVariableStorageClass(StringView
&MangledName
) {
1721 assert(MangledName
.front() >= '0' && MangledName
.front() <= '4');
1723 switch (MangledName
.popFront()) {
1725 return StorageClass::PrivateStatic
;
1727 return StorageClass::ProtectedStatic
;
1729 return StorageClass::PublicStatic
;
1731 return StorageClass::Global
;
1733 return StorageClass::FunctionLocalStatic
;
1735 DEMANGLE_UNREACHABLE
;
1738 std::pair
<Qualifiers
, bool>
1739 Demangler::demangleQualifiers(StringView
&MangledName
) {
1740 if (MangledName
.empty()) {
1742 return std::make_pair(Q_None
, false);
1745 switch (MangledName
.popFront()) {
1746 // Member qualifiers
1748 return std::make_pair(Q_None
, true);
1750 return std::make_pair(Q_Const
, true);
1752 return std::make_pair(Q_Volatile
, true);
1754 return std::make_pair(Qualifiers(Q_Const
| Q_Volatile
), true);
1755 // Non-Member qualifiers
1757 return std::make_pair(Q_None
, false);
1759 return std::make_pair(Q_Const
, false);
1761 return std::make_pair(Q_Volatile
, false);
1763 return std::make_pair(Qualifiers(Q_Const
| Q_Volatile
), false);
1766 return std::make_pair(Q_None
, false);
1769 // <variable-type> ::= <type> <cvr-qualifiers>
1770 // ::= <type> <pointee-cvr-qualifiers> # pointers, references
1771 TypeNode
*Demangler::demangleType(StringView
&MangledName
,
1772 QualifierMangleMode QMM
) {
1773 Qualifiers Quals
= Q_None
;
1774 bool IsMember
= false;
1775 if (QMM
== QualifierMangleMode::Mangle
) {
1776 std::tie(Quals
, IsMember
) = demangleQualifiers(MangledName
);
1777 } else if (QMM
== QualifierMangleMode::Result
) {
1778 if (MangledName
.consumeFront('?'))
1779 std::tie(Quals
, IsMember
) = demangleQualifiers(MangledName
);
1782 if (MangledName
.empty()) {
1787 TypeNode
*Ty
= nullptr;
1788 if (isTagType(MangledName
))
1789 Ty
= demangleClassType(MangledName
);
1790 else if (isPointerType(MangledName
)) {
1791 if (isMemberPointer(MangledName
, Error
))
1792 Ty
= demangleMemberPointerType(MangledName
);
1794 Ty
= demanglePointerType(MangledName
);
1797 } else if (isArrayType(MangledName
))
1798 Ty
= demangleArrayType(MangledName
);
1799 else if (isFunctionType(MangledName
)) {
1800 if (MangledName
.consumeFront("$$A8@@"))
1801 Ty
= demangleFunctionType(MangledName
, true);
1803 assert(MangledName
.startsWith("$$A6"));
1804 MangledName
.consumeFront("$$A6");
1805 Ty
= demangleFunctionType(MangledName
, false);
1807 } else if (isCustomType(MangledName
)) {
1808 Ty
= demangleCustomType(MangledName
);
1810 Ty
= demanglePrimitiveType(MangledName
);
1815 Ty
->Quals
= Qualifiers(Ty
->Quals
| Quals
);
1819 bool Demangler::demangleThrowSpecification(StringView
&MangledName
) {
1820 if (MangledName
.consumeFront("_E"))
1822 if (MangledName
.consumeFront('Z'))
1829 FunctionSignatureNode
*Demangler::demangleFunctionType(StringView
&MangledName
,
1830 bool HasThisQuals
) {
1831 FunctionSignatureNode
*FTy
= Arena
.alloc
<FunctionSignatureNode
>();
1834 FTy
->Quals
= demanglePointerExtQualifiers(MangledName
);
1835 FTy
->RefQualifier
= demangleFunctionRefQualifier(MangledName
);
1836 FTy
->Quals
= Qualifiers(FTy
->Quals
| demangleQualifiers(MangledName
).first
);
1839 // Fields that appear on both member and non-member functions.
1840 FTy
->CallConvention
= demangleCallingConvention(MangledName
);
1842 // <return-type> ::= <type>
1843 // ::= @ # structors (they have no declared return type)
1844 bool IsStructor
= MangledName
.consumeFront('@');
1846 FTy
->ReturnType
= demangleType(MangledName
, QualifierMangleMode::Result
);
1848 FTy
->Params
= demangleFunctionParameterList(MangledName
, FTy
->IsVariadic
);
1850 FTy
->IsNoexcept
= demangleThrowSpecification(MangledName
);
1855 FunctionSymbolNode
*
1856 Demangler::demangleFunctionEncoding(StringView
&MangledName
) {
1857 FuncClass ExtraFlags
= FC_None
;
1858 if (MangledName
.consumeFront("$$J0"))
1859 ExtraFlags
= FC_ExternC
;
1861 if (MangledName
.empty()) {
1866 FuncClass FC
= demangleFunctionClass(MangledName
);
1867 FC
= FuncClass(ExtraFlags
| FC
);
1869 FunctionSignatureNode
*FSN
= nullptr;
1870 ThunkSignatureNode
*TTN
= nullptr;
1871 if (FC
& FC_StaticThisAdjust
) {
1872 TTN
= Arena
.alloc
<ThunkSignatureNode
>();
1873 TTN
->ThisAdjust
.StaticOffset
= demangleSigned(MangledName
);
1874 } else if (FC
& FC_VirtualThisAdjust
) {
1875 TTN
= Arena
.alloc
<ThunkSignatureNode
>();
1876 if (FC
& FC_VirtualThisAdjustEx
) {
1877 TTN
->ThisAdjust
.VBPtrOffset
= demangleSigned(MangledName
);
1878 TTN
->ThisAdjust
.VBOffsetOffset
= demangleSigned(MangledName
);
1880 TTN
->ThisAdjust
.VtordispOffset
= demangleSigned(MangledName
);
1881 TTN
->ThisAdjust
.StaticOffset
= demangleSigned(MangledName
);
1884 if (FC
& FC_NoParameterList
) {
1885 // This is an extern "C" function whose full signature hasn't been mangled.
1886 // This happens when we need to mangle a local symbol inside of an extern
1888 FSN
= Arena
.alloc
<FunctionSignatureNode
>();
1890 bool HasThisQuals
= !(FC
& (FC_Global
| FC_Static
));
1891 FSN
= demangleFunctionType(MangledName
, HasThisQuals
);
1898 *static_cast<FunctionSignatureNode
*>(TTN
) = *FSN
;
1901 FSN
->FunctionClass
= FC
;
1903 FunctionSymbolNode
*Symbol
= Arena
.alloc
<FunctionSymbolNode
>();
1904 Symbol
->Signature
= FSN
;
1908 CustomTypeNode
*Demangler::demangleCustomType(StringView
&MangledName
) {
1909 assert(MangledName
.startsWith('?'));
1910 MangledName
.popFront();
1912 CustomTypeNode
*CTN
= Arena
.alloc
<CustomTypeNode
>();
1913 CTN
->Identifier
= demangleUnqualifiedTypeName(MangledName
, /*Memorize=*/true);
1914 if (!MangledName
.consumeFront('@'))
1921 // Reads a primitive type.
1922 PrimitiveTypeNode
*Demangler::demanglePrimitiveType(StringView
&MangledName
) {
1923 if (MangledName
.consumeFront("$$T"))
1924 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Nullptr
);
1926 switch (MangledName
.popFront()) {
1928 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Void
);
1930 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char
);
1932 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Schar
);
1934 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Uchar
);
1936 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Short
);
1938 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Ushort
);
1940 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Int
);
1942 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Uint
);
1944 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Long
);
1946 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Ulong
);
1948 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Float
);
1950 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Double
);
1952 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Ldouble
);
1954 if (MangledName
.empty()) {
1958 switch (MangledName
.popFront()) {
1960 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Bool
);
1962 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Int64
);
1964 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Uint64
);
1966 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Wchar
);
1968 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char8
);
1970 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char16
);
1972 return Arena
.alloc
<PrimitiveTypeNode
>(PrimitiveKind::Char32
);
1981 TagTypeNode
*Demangler::demangleClassType(StringView
&MangledName
) {
1982 TagTypeNode
*TT
= nullptr;
1984 switch (MangledName
.popFront()) {
1986 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Union
);
1989 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Struct
);
1992 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Class
);
1995 if (!MangledName
.consumeFront('4')) {
1999 TT
= Arena
.alloc
<TagTypeNode
>(TagKind::Enum
);
2005 TT
->QualifiedName
= demangleFullyQualifiedTypeName(MangledName
);
2009 // <pointer-type> ::= E? <pointer-cvr-qualifiers> <ext-qualifiers> <type>
2010 // # the E is required for 64-bit non-static pointers
2011 PointerTypeNode
*Demangler::demanglePointerType(StringView
&MangledName
) {
2012 PointerTypeNode
*Pointer
= Arena
.alloc
<PointerTypeNode
>();
2014 std::tie(Pointer
->Quals
, Pointer
->Affinity
) =
2015 demanglePointerCVQualifiers(MangledName
);
2017 if (MangledName
.consumeFront("6")) {
2018 Pointer
->Pointee
= demangleFunctionType(MangledName
, false);
2022 Qualifiers ExtQuals
= demanglePointerExtQualifiers(MangledName
);
2023 Pointer
->Quals
= Qualifiers(Pointer
->Quals
| ExtQuals
);
2025 Pointer
->Pointee
= demangleType(MangledName
, QualifierMangleMode::Mangle
);
2029 PointerTypeNode
*Demangler::demangleMemberPointerType(StringView
&MangledName
) {
2030 PointerTypeNode
*Pointer
= Arena
.alloc
<PointerTypeNode
>();
2032 std::tie(Pointer
->Quals
, Pointer
->Affinity
) =
2033 demanglePointerCVQualifiers(MangledName
);
2034 assert(Pointer
->Affinity
== PointerAffinity::Pointer
);
2036 Qualifiers ExtQuals
= demanglePointerExtQualifiers(MangledName
);
2037 Pointer
->Quals
= Qualifiers(Pointer
->Quals
| ExtQuals
);
2039 // isMemberPointer() only returns true if there is at least one character
2040 // after the qualifiers.
2041 if (MangledName
.consumeFront("8")) {
2042 Pointer
->ClassParent
= demangleFullyQualifiedTypeName(MangledName
);
2043 Pointer
->Pointee
= demangleFunctionType(MangledName
, true);
2045 Qualifiers PointeeQuals
= Q_None
;
2046 bool IsMember
= false;
2047 std::tie(PointeeQuals
, IsMember
) = demangleQualifiers(MangledName
);
2048 assert(IsMember
|| Error
);
2049 Pointer
->ClassParent
= demangleFullyQualifiedTypeName(MangledName
);
2051 Pointer
->Pointee
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2052 if (Pointer
->Pointee
)
2053 Pointer
->Pointee
->Quals
= PointeeQuals
;
2059 Qualifiers
Demangler::demanglePointerExtQualifiers(StringView
&MangledName
) {
2060 Qualifiers Quals
= Q_None
;
2061 if (MangledName
.consumeFront('E'))
2062 Quals
= Qualifiers(Quals
| Q_Pointer64
);
2063 if (MangledName
.consumeFront('I'))
2064 Quals
= Qualifiers(Quals
| Q_Restrict
);
2065 if (MangledName
.consumeFront('F'))
2066 Quals
= Qualifiers(Quals
| Q_Unaligned
);
2071 ArrayTypeNode
*Demangler::demangleArrayType(StringView
&MangledName
) {
2072 assert(MangledName
.front() == 'Y');
2073 MangledName
.popFront();
2076 bool IsNegative
= false;
2077 std::tie(Rank
, IsNegative
) = demangleNumber(MangledName
);
2078 if (IsNegative
|| Rank
== 0) {
2083 ArrayTypeNode
*ATy
= Arena
.alloc
<ArrayTypeNode
>();
2084 NodeList
*Head
= Arena
.alloc
<NodeList
>();
2085 NodeList
*Tail
= Head
;
2087 for (uint64_t I
= 0; I
< Rank
; ++I
) {
2089 std::tie(D
, IsNegative
) = demangleNumber(MangledName
);
2090 if (Error
|| IsNegative
) {
2094 Tail
->N
= Arena
.alloc
<IntegerLiteralNode
>(D
, IsNegative
);
2096 Tail
->Next
= Arena
.alloc
<NodeList
>();
2100 ATy
->Dimensions
= nodeListToNodeArray(Arena
, Head
, Rank
);
2102 if (MangledName
.consumeFront("$$C")) {
2103 bool IsMember
= false;
2104 std::tie(ATy
->Quals
, IsMember
) = demangleQualifiers(MangledName
);
2111 ATy
->ElementType
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2115 // Reads a function's parameters.
2116 NodeArrayNode
*Demangler::demangleFunctionParameterList(StringView
&MangledName
,
2118 // Empty parameter list.
2119 if (MangledName
.consumeFront('X'))
2122 NodeList
*Head
= Arena
.alloc
<NodeList
>();
2123 NodeList
**Current
= &Head
;
2125 while (!Error
&& !MangledName
.startsWith('@') &&
2126 !MangledName
.startsWith('Z')) {
2129 if (startsWithDigit(MangledName
)) {
2130 size_t N
= MangledName
[0] - '0';
2131 if (N
>= Backrefs
.FunctionParamCount
) {
2135 MangledName
= MangledName
.dropFront();
2137 *Current
= Arena
.alloc
<NodeList
>();
2138 (*Current
)->N
= Backrefs
.FunctionParams
[N
];
2139 Current
= &(*Current
)->Next
;
2143 size_t OldSize
= MangledName
.size();
2145 *Current
= Arena
.alloc
<NodeList
>();
2146 TypeNode
*TN
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2152 size_t CharsConsumed
= OldSize
- MangledName
.size();
2153 assert(CharsConsumed
!= 0);
2155 // Single-letter types are ignored for backreferences because memorizing
2156 // them doesn't save anything.
2157 if (Backrefs
.FunctionParamCount
<= 9 && CharsConsumed
> 1)
2158 Backrefs
.FunctionParams
[Backrefs
.FunctionParamCount
++] = TN
;
2160 Current
= &(*Current
)->Next
;
2166 NodeArrayNode
*NA
= nodeListToNodeArray(Arena
, Head
, Count
);
2167 // A non-empty parameter list is terminated by either 'Z' (variadic) parameter
2168 // list or '@' (non variadic). Careful not to consume "@Z", as in that case
2169 // the following Z could be a throw specifier.
2170 if (MangledName
.consumeFront('@'))
2173 if (MangledName
.consumeFront('Z')) {
2178 DEMANGLE_UNREACHABLE
;
2182 Demangler::demangleTemplateParameterList(StringView
&MangledName
) {
2183 NodeList
*Head
= nullptr;
2184 NodeList
**Current
= &Head
;
2187 while (!MangledName
.startsWith('@')) {
2188 if (MangledName
.consumeFront("$S") || MangledName
.consumeFront("$$V") ||
2189 MangledName
.consumeFront("$$$V") || MangledName
.consumeFront("$$Z")) {
2190 // parameter pack separator
2196 // Template parameter lists don't participate in back-referencing.
2197 *Current
= Arena
.alloc
<NodeList
>();
2199 NodeList
&TP
= **Current
;
2201 TemplateParameterReferenceNode
*TPRN
= nullptr;
2202 if (MangledName
.consumeFront("$$Y")) {
2204 TP
.N
= demangleFullyQualifiedTypeName(MangledName
);
2205 } else if (MangledName
.consumeFront("$$B")) {
2207 TP
.N
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2208 } else if (MangledName
.consumeFront("$$C")) {
2209 // Type has qualifiers.
2210 TP
.N
= demangleType(MangledName
, QualifierMangleMode::Mangle
);
2211 } else if (MangledName
.startsWith("$1") || MangledName
.startsWith("$H") ||
2212 MangledName
.startsWith("$I") || MangledName
.startsWith("$J")) {
2213 // Pointer to member
2214 TP
.N
= TPRN
= Arena
.alloc
<TemplateParameterReferenceNode
>();
2215 TPRN
->IsMemberPointer
= true;
2217 MangledName
= MangledName
.dropFront();
2218 // 1 - single inheritance <name>
2219 // H - multiple inheritance <name> <number>
2220 // I - virtual inheritance <name> <number> <number>
2221 // J - unspecified inheritance <name> <number> <number> <number>
2222 char InheritanceSpecifier
= MangledName
.popFront();
2223 SymbolNode
*S
= nullptr;
2224 if (MangledName
.startsWith('?')) {
2225 S
= parse(MangledName
);
2226 if (Error
|| !S
->Name
) {
2230 memorizeIdentifier(S
->Name
->getUnqualifiedIdentifier());
2233 switch (InheritanceSpecifier
) {
2235 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2236 demangleSigned(MangledName
);
2237 DEMANGLE_FALLTHROUGH
;
2239 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2240 demangleSigned(MangledName
);
2241 DEMANGLE_FALLTHROUGH
;
2243 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2244 demangleSigned(MangledName
);
2245 DEMANGLE_FALLTHROUGH
;
2249 DEMANGLE_UNREACHABLE
;
2251 TPRN
->Affinity
= PointerAffinity::Pointer
;
2253 } else if (MangledName
.startsWith("$E?")) {
2254 MangledName
.consumeFront("$E");
2255 // Reference to symbol
2256 TP
.N
= TPRN
= Arena
.alloc
<TemplateParameterReferenceNode
>();
2257 TPRN
->Symbol
= parse(MangledName
);
2258 TPRN
->Affinity
= PointerAffinity::Reference
;
2259 } else if (MangledName
.startsWith("$F") || MangledName
.startsWith("$G")) {
2260 TP
.N
= TPRN
= Arena
.alloc
<TemplateParameterReferenceNode
>();
2262 // Data member pointer.
2263 MangledName
= MangledName
.dropFront();
2264 char InheritanceSpecifier
= MangledName
.popFront();
2266 switch (InheritanceSpecifier
) {
2268 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2269 demangleSigned(MangledName
);
2270 DEMANGLE_FALLTHROUGH
;
2272 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2273 demangleSigned(MangledName
);
2274 TPRN
->ThunkOffsets
[TPRN
->ThunkOffsetCount
++] =
2275 demangleSigned(MangledName
);
2278 DEMANGLE_UNREACHABLE
;
2280 TPRN
->IsMemberPointer
= true;
2282 } else if (MangledName
.consumeFront("$0")) {
2283 // Integral non-type template parameter
2284 bool IsNegative
= false;
2286 std::tie(Value
, IsNegative
) = demangleNumber(MangledName
);
2288 TP
.N
= Arena
.alloc
<IntegerLiteralNode
>(Value
, IsNegative
);
2290 TP
.N
= demangleType(MangledName
, QualifierMangleMode::Drop
);
2298 // The loop above returns nullptr on Error.
2301 // Template parameter lists cannot be variadic, so it can only be terminated
2302 // by @ (as opposed to 'Z' in the function parameter case).
2303 assert(MangledName
.startsWith('@')); // The above loop exits only on '@'.
2304 MangledName
.consumeFront('@');
2305 return nodeListToNodeArray(Arena
, Head
, Count
);
2308 void Demangler::dumpBackReferences() {
2309 std::printf("%d function parameter backreferences\n",
2310 (int)Backrefs
.FunctionParamCount
);
2312 // Create an output stream so we can render each type.
2314 if (!initializeOutputBuffer(nullptr, nullptr, OB
, 1024))
2316 for (size_t I
= 0; I
< Backrefs
.FunctionParamCount
; ++I
) {
2317 OB
.setCurrentPosition(0);
2319 TypeNode
*T
= Backrefs
.FunctionParams
[I
];
2320 T
->output(OB
, OF_Default
);
2323 std::printf(" [%d] - %.*s\n", (int)I
, (int)B
.size(), B
.begin());
2325 std::free(OB
.getBuffer());
2327 if (Backrefs
.FunctionParamCount
> 0)
2329 std::printf("%d name backreferences\n", (int)Backrefs
.NamesCount
);
2330 for (size_t I
= 0; I
< Backrefs
.NamesCount
; ++I
) {
2331 std::printf(" [%d] - %.*s\n", (int)I
, (int)Backrefs
.Names
[I
]->Name
.size(),
2332 Backrefs
.Names
[I
]->Name
.begin());
2334 if (Backrefs
.NamesCount
> 0)
2338 char *llvm::microsoftDemangle(const char *MangledName
, size_t *NMangled
,
2339 char *Buf
, size_t *N
,
2340 int *Status
, MSDemangleFlags Flags
) {
2344 StringView Name
{MangledName
};
2345 SymbolNode
*AST
= D
.parse(Name
);
2346 if (!D
.Error
&& NMangled
)
2347 *NMangled
= Name
.begin() - MangledName
;
2349 if (Flags
& MSDF_DumpBackrefs
)
2350 D
.dumpBackReferences();
2352 OutputFlags OF
= OF_Default
;
2353 if (Flags
& MSDF_NoCallingConvention
)
2354 OF
= OutputFlags(OF
| OF_NoCallingConvention
);
2355 if (Flags
& MSDF_NoAccessSpecifier
)
2356 OF
= OutputFlags(OF
| OF_NoAccessSpecifier
);
2357 if (Flags
& MSDF_NoReturnType
)
2358 OF
= OutputFlags(OF
| OF_NoReturnType
);
2359 if (Flags
& MSDF_NoMemberType
)
2360 OF
= OutputFlags(OF
| OF_NoMemberType
);
2361 if (Flags
& MSDF_NoVariableType
)
2362 OF
= OutputFlags(OF
| OF_NoVariableType
);
2364 int InternalStatus
= demangle_success
;
2366 InternalStatus
= demangle_invalid_mangled_name
;
2367 else if (!initializeOutputBuffer(Buf
, N
, OB
, 1024))
2368 InternalStatus
= demangle_memory_alloc_failure
;
2370 AST
->output(OB
, OF
);
2373 *N
= OB
.getCurrentPosition();
2374 Buf
= OB
.getBuffer();
2378 *Status
= InternalStatus
;
2379 return InternalStatus
== demangle_success
? Buf
: nullptr;