1 //===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===//
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 // Generic itanium demangler library.
10 // There are two copies of this file in the source tree. The one under
11 // libcxxabi is the original and the one under llvm is the copy. Use
12 // cp-to-llvm.sh to update the copy. See README.txt for more details.
14 //===----------------------------------------------------------------------===//
16 #ifndef DEMANGLE_ITANIUMDEMANGLE_H
17 #define DEMANGLE_ITANIUMDEMANGLE_H
19 #include "DemangleConfig.h"
20 #include "StringViewExtras.h"
22 #include <__cxxabi_config.h>
30 #include <string_view>
31 #include <type_traits>
34 #ifdef _LIBCXXABI_COMPILER_CLANG
35 #pragma clang diagnostic push
36 #pragma clang diagnostic ignored "-Wunused-template"
39 DEMANGLE_NAMESPACE_BEGIN
41 template <class T
, size_t N
> class PODSmallVector
{
42 static_assert(std::is_trivial
<T
>::value
,
43 "T is required to be a trivial type");
49 bool isInline() const { return First
== Inline
; }
57 void reserve(size_t NewCap
) {
60 auto *Tmp
= static_cast<T
*>(std::malloc(NewCap
* sizeof(T
)));
63 std::copy(First
, Last
, Tmp
);
66 First
= static_cast<T
*>(std::realloc(First
, NewCap
* sizeof(T
)));
75 PODSmallVector() : First(Inline
), Last(First
), Cap(Inline
+ N
) {}
77 PODSmallVector(const PODSmallVector
&) = delete;
78 PODSmallVector
&operator=(const PODSmallVector
&) = delete;
80 PODSmallVector(PODSmallVector
&&Other
) : PODSmallVector() {
81 if (Other
.isInline()) {
82 std::copy(Other
.begin(), Other
.end(), First
);
83 Last
= First
+ Other
.size();
94 PODSmallVector
&operator=(PODSmallVector
&&Other
) {
95 if (Other
.isInline()) {
100 std::copy(Other
.begin(), Other
.end(), First
);
101 Last
= First
+ Other
.size();
114 std::swap(First
, Other
.First
);
115 std::swap(Last
, Other
.Last
);
116 std::swap(Cap
, Other
.Cap
);
121 // NOLINTNEXTLINE(readability-identifier-naming)
122 void push_back(const T
&Elem
) {
128 // NOLINTNEXTLINE(readability-identifier-naming)
130 DEMANGLE_ASSERT(Last
!= First
, "Popping empty vector!");
134 void shrinkToSize(size_t Index
) {
135 DEMANGLE_ASSERT(Index
<= size(), "shrinkToSize() can't expand!");
136 Last
= First
+ Index
;
139 T
*begin() { return First
; }
140 T
*end() { return Last
; }
142 bool empty() const { return First
== Last
; }
143 size_t size() const { return static_cast<size_t>(Last
- First
); }
145 DEMANGLE_ASSERT(Last
!= First
, "Calling back() on empty vector!");
148 T
&operator[](size_t Index
) {
149 DEMANGLE_ASSERT(Index
< size(), "Invalid access!");
150 return *(begin() + Index
);
152 void clear() { Last
= First
; }
160 // Base class of all AST nodes. The AST is built by the parser, then is
161 // traversed by the printLeft/Right functions to produce a demangled string.
164 enum Kind
: unsigned char {
165 #define NODE(NodeKind) K##NodeKind,
166 #include "ItaniumNodes.def"
169 /// Three-way bool to track a cached value. Unknown is possible if this node
170 /// has an unexpanded parameter pack below it that may affect this cache.
171 enum class Cache
: unsigned char { Yes
, No
, Unknown
, };
173 /// Operator precedence for expression nodes. Used to determine required
174 /// parens in expression emission.
203 // FIXME: Make these protected.
205 /// Tracks if this node has a component on its right side, in which case we
206 /// need to call printRight.
207 Cache RHSComponentCache
: 2;
209 /// Track if this node is a (possibly qualified) array type. This can affect
210 /// how we format the output string.
211 Cache ArrayCache
: 2;
213 /// Track if this node is a (possibly qualified) function type. This can
214 /// affect how we format the output string.
215 Cache FunctionCache
: 2;
218 Node(Kind K_
, Prec Precedence_
= Prec::Primary
,
219 Cache RHSComponentCache_
= Cache::No
, Cache ArrayCache_
= Cache::No
,
220 Cache FunctionCache_
= Cache::No
)
221 : K(K_
), Precedence(Precedence_
), RHSComponentCache(RHSComponentCache_
),
222 ArrayCache(ArrayCache_
), FunctionCache(FunctionCache_
) {}
223 Node(Kind K_
, Cache RHSComponentCache_
, Cache ArrayCache_
= Cache::No
,
224 Cache FunctionCache_
= Cache::No
)
225 : Node(K_
, Prec::Primary
, RHSComponentCache_
, ArrayCache_
,
228 /// Visit the most-derived object corresponding to this object.
229 template<typename Fn
> void visit(Fn F
) const;
231 // The following function is provided by all derived classes:
233 // Call F with arguments that, when passed to the constructor of this node,
234 // would construct an equivalent node.
235 //template<typename Fn> void match(Fn F) const;
237 bool hasRHSComponent(OutputBuffer
&OB
) const {
238 if (RHSComponentCache
!= Cache::Unknown
)
239 return RHSComponentCache
== Cache::Yes
;
240 return hasRHSComponentSlow(OB
);
243 bool hasArray(OutputBuffer
&OB
) const {
244 if (ArrayCache
!= Cache::Unknown
)
245 return ArrayCache
== Cache::Yes
;
246 return hasArraySlow(OB
);
249 bool hasFunction(OutputBuffer
&OB
) const {
250 if (FunctionCache
!= Cache::Unknown
)
251 return FunctionCache
== Cache::Yes
;
252 return hasFunctionSlow(OB
);
255 Kind
getKind() const { return K
; }
257 Prec
getPrecedence() const { return Precedence
; }
259 virtual bool hasRHSComponentSlow(OutputBuffer
&) const { return false; }
260 virtual bool hasArraySlow(OutputBuffer
&) const { return false; }
261 virtual bool hasFunctionSlow(OutputBuffer
&) const { return false; }
263 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
264 // get at a node that actually represents some concrete syntax.
265 virtual const Node
*getSyntaxNode(OutputBuffer
&) const { return this; }
267 // Print this node as an expression operand, surrounding it in parentheses if
268 // its precedence is [Strictly] weaker than P.
269 void printAsOperand(OutputBuffer
&OB
, Prec P
= Prec::Default
,
270 bool StrictlyWorse
= false) const {
272 unsigned(getPrecedence()) >= unsigned(P
) + unsigned(StrictlyWorse
);
280 void print(OutputBuffer
&OB
) const {
282 if (RHSComponentCache
!= Cache::No
)
286 // Print the "left" side of this Node into OutputBuffer.
287 virtual void printLeft(OutputBuffer
&) const = 0;
289 // Print the "right". This distinction is necessary to represent C++ types
290 // that appear on the RHS of their subtype, such as arrays or functions.
291 // Since most types don't have such a component, provide a default
293 virtual void printRight(OutputBuffer
&) const {}
295 virtual std::string_view
getBaseName() const { return {}; }
297 // Silence compiler warnings, this dtor will never be called.
298 virtual ~Node() = default;
301 DEMANGLE_DUMP_METHOD
void dump() const;
310 NodeArray() : Elements(nullptr), NumElements(0) {}
311 NodeArray(Node
**Elements_
, size_t NumElements_
)
312 : Elements(Elements_
), NumElements(NumElements_
) {}
314 bool empty() const { return NumElements
== 0; }
315 size_t size() const { return NumElements
; }
317 Node
**begin() const { return Elements
; }
318 Node
**end() const { return Elements
+ NumElements
; }
320 Node
*operator[](size_t Idx
) const { return Elements
[Idx
]; }
322 void printWithComma(OutputBuffer
&OB
) const {
323 bool FirstElement
= true;
324 for (size_t Idx
= 0; Idx
!= NumElements
; ++Idx
) {
325 size_t BeforeComma
= OB
.getCurrentPosition();
328 size_t AfterComma
= OB
.getCurrentPosition();
329 Elements
[Idx
]->printAsOperand(OB
, Node::Prec::Comma
);
331 // Elements[Idx] is an empty parameter pack expansion, we should erase the
332 // comma we just printed.
333 if (AfterComma
== OB
.getCurrentPosition()) {
334 OB
.setCurrentPosition(BeforeComma
);
338 FirstElement
= false;
343 struct NodeArrayNode
: Node
{
345 NodeArrayNode(NodeArray Array_
) : Node(KNodeArrayNode
), Array(Array_
) {}
347 template<typename Fn
> void match(Fn F
) const { F(Array
); }
349 void printLeft(OutputBuffer
&OB
) const override
{ Array
.printWithComma(OB
); }
352 class DotSuffix final
: public Node
{
354 const std::string_view Suffix
;
357 DotSuffix(const Node
*Prefix_
, std::string_view Suffix_
)
358 : Node(KDotSuffix
), Prefix(Prefix_
), Suffix(Suffix_
) {}
360 template<typename Fn
> void match(Fn F
) const { F(Prefix
, Suffix
); }
362 void printLeft(OutputBuffer
&OB
) const override
{
370 class VendorExtQualType final
: public Node
{
372 std::string_view Ext
;
376 VendorExtQualType(const Node
*Ty_
, std::string_view Ext_
, const Node
*TA_
)
377 : Node(KVendorExtQualType
), Ty(Ty_
), Ext(Ext_
), TA(TA_
) {}
379 const Node
*getTy() const { return Ty
; }
380 std::string_view
getExt() const { return Ext
; }
381 const Node
*getTA() const { return TA
; }
383 template <typename Fn
> void match(Fn F
) const { F(Ty
, Ext
, TA
); }
385 void printLeft(OutputBuffer
&OB
) const override
{
394 enum FunctionRefQual
: unsigned char {
407 inline Qualifiers
operator|=(Qualifiers
&Q1
, Qualifiers Q2
) {
408 return Q1
= static_cast<Qualifiers
>(Q1
| Q2
);
411 class QualType final
: public Node
{
413 const Qualifiers Quals
;
416 void printQuals(OutputBuffer
&OB
) const {
417 if (Quals
& QualConst
)
419 if (Quals
& QualVolatile
)
421 if (Quals
& QualRestrict
)
426 QualType(const Node
*Child_
, Qualifiers Quals_
)
427 : Node(KQualType
, Child_
->RHSComponentCache
,
428 Child_
->ArrayCache
, Child_
->FunctionCache
),
429 Quals(Quals_
), Child(Child_
) {}
431 Qualifiers
getQuals() const { return Quals
; }
432 const Node
*getChild() const { return Child
; }
434 template<typename Fn
> void match(Fn F
) const { F(Child
, Quals
); }
436 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
437 return Child
->hasRHSComponent(OB
);
439 bool hasArraySlow(OutputBuffer
&OB
) const override
{
440 return Child
->hasArray(OB
);
442 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
443 return Child
->hasFunction(OB
);
446 void printLeft(OutputBuffer
&OB
) const override
{
447 Child
->printLeft(OB
);
451 void printRight(OutputBuffer
&OB
) const override
{ Child
->printRight(OB
); }
454 class ConversionOperatorType final
: public Node
{
458 ConversionOperatorType(const Node
*Ty_
)
459 : Node(KConversionOperatorType
), Ty(Ty_
) {}
461 template<typename Fn
> void match(Fn F
) const { F(Ty
); }
463 void printLeft(OutputBuffer
&OB
) const override
{
469 class PostfixQualifiedType final
: public Node
{
471 const std::string_view Postfix
;
474 PostfixQualifiedType(const Node
*Ty_
, std::string_view Postfix_
)
475 : Node(KPostfixQualifiedType
), Ty(Ty_
), Postfix(Postfix_
) {}
477 template<typename Fn
> void match(Fn F
) const { F(Ty
, Postfix
); }
479 void printLeft(OutputBuffer
&OB
) const override
{
485 class NameType final
: public Node
{
486 const std::string_view Name
;
489 NameType(std::string_view Name_
) : Node(KNameType
), Name(Name_
) {}
491 template<typename Fn
> void match(Fn F
) const { F(Name
); }
493 std::string_view
getName() const { return Name
; }
494 std::string_view
getBaseName() const override
{ return Name
; }
496 void printLeft(OutputBuffer
&OB
) const override
{ OB
+= Name
; }
499 class BitIntType final
: public Node
{
504 BitIntType(const Node
*Size_
, bool Signed_
)
505 : Node(KBitIntType
), Size(Size_
), Signed(Signed_
) {}
507 template <typename Fn
> void match(Fn F
) const { F(Size
, Signed
); }
509 void printLeft(OutputBuffer
&OB
) const override
{
514 Size
->printAsOperand(OB
);
519 class ElaboratedTypeSpefType
: public Node
{
520 std::string_view Kind
;
523 ElaboratedTypeSpefType(std::string_view Kind_
, Node
*Child_
)
524 : Node(KElaboratedTypeSpefType
), Kind(Kind_
), Child(Child_
) {}
526 template<typename Fn
> void match(Fn F
) const { F(Kind
, Child
); }
528 void printLeft(OutputBuffer
&OB
) const override
{
535 class TransformedType
: public Node
{
536 std::string_view Transform
;
539 TransformedType(std::string_view Transform_
, Node
*BaseType_
)
540 : Node(KTransformedType
), Transform(Transform_
), BaseType(BaseType_
) {}
542 template<typename Fn
> void match(Fn F
) const { F(Transform
, BaseType
); }
544 void printLeft(OutputBuffer
&OB
) const override
{
552 struct AbiTagAttr
: Node
{
554 std::string_view Tag
;
556 AbiTagAttr(Node
*Base_
, std::string_view Tag_
)
557 : Node(KAbiTagAttr
, Base_
->RHSComponentCache
, Base_
->ArrayCache
,
558 Base_
->FunctionCache
),
559 Base(Base_
), Tag(Tag_
) {}
561 template<typename Fn
> void match(Fn F
) const { F(Base
, Tag
); }
563 std::string_view
getBaseName() const override
{ return Base
->getBaseName(); }
565 void printLeft(OutputBuffer
&OB
) const override
{
573 class EnableIfAttr
: public Node
{
574 NodeArray Conditions
;
576 EnableIfAttr(NodeArray Conditions_
)
577 : Node(KEnableIfAttr
), Conditions(Conditions_
) {}
579 template<typename Fn
> void match(Fn F
) const { F(Conditions
); }
581 void printLeft(OutputBuffer
&OB
) const override
{
582 OB
+= " [enable_if:";
583 Conditions
.printWithComma(OB
);
588 class ObjCProtoName
: public Node
{
590 std::string_view Protocol
;
592 friend class PointerType
;
595 ObjCProtoName(const Node
*Ty_
, std::string_view Protocol_
)
596 : Node(KObjCProtoName
), Ty(Ty_
), Protocol(Protocol_
) {}
598 template<typename Fn
> void match(Fn F
) const { F(Ty
, Protocol
); }
600 bool isObjCObject() const {
601 return Ty
->getKind() == KNameType
&&
602 static_cast<const NameType
*>(Ty
)->getName() == "objc_object";
605 void printLeft(OutputBuffer
&OB
) const override
{
613 class PointerType final
: public Node
{
617 PointerType(const Node
*Pointee_
)
618 : Node(KPointerType
, Pointee_
->RHSComponentCache
),
621 const Node
*getPointee() const { return Pointee
; }
623 template<typename Fn
> void match(Fn F
) const { F(Pointee
); }
625 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
626 return Pointee
->hasRHSComponent(OB
);
629 void printLeft(OutputBuffer
&OB
) const override
{
630 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
631 if (Pointee
->getKind() != KObjCProtoName
||
632 !static_cast<const ObjCProtoName
*>(Pointee
)->isObjCObject()) {
633 Pointee
->printLeft(OB
);
634 if (Pointee
->hasArray(OB
))
636 if (Pointee
->hasArray(OB
) || Pointee
->hasFunction(OB
))
640 const auto *objcProto
= static_cast<const ObjCProtoName
*>(Pointee
);
642 OB
+= objcProto
->Protocol
;
647 void printRight(OutputBuffer
&OB
) const override
{
648 if (Pointee
->getKind() != KObjCProtoName
||
649 !static_cast<const ObjCProtoName
*>(Pointee
)->isObjCObject()) {
650 if (Pointee
->hasArray(OB
) || Pointee
->hasFunction(OB
))
652 Pointee
->printRight(OB
);
657 enum class ReferenceKind
{
662 // Represents either a LValue or an RValue reference type.
663 class ReferenceType
: public Node
{
667 mutable bool Printing
= false;
669 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
670 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
671 // other combination collapses to a lvalue ref.
673 // A combination of a TemplateForwardReference and a back-ref Substitution
674 // from an ill-formed string may have created a cycle; use cycle detection to
675 // avoid looping forever.
676 std::pair
<ReferenceKind
, const Node
*> collapse(OutputBuffer
&OB
) const {
677 auto SoFar
= std::make_pair(RK
, Pointee
);
678 // Track the chain of nodes for the Floyd's 'tortoise and hare'
679 // cycle-detection algorithm, since getSyntaxNode(S) is impure
680 PODSmallVector
<const Node
*, 8> Prev
;
682 const Node
*SN
= SoFar
.second
->getSyntaxNode(OB
);
683 if (SN
->getKind() != KReferenceType
)
685 auto *RT
= static_cast<const ReferenceType
*>(SN
);
686 SoFar
.second
= RT
->Pointee
;
687 SoFar
.first
= std::min(SoFar
.first
, RT
->RK
);
689 // The middle of Prev is the 'slow' pointer moving at half speed
690 Prev
.push_back(SoFar
.second
);
691 if (Prev
.size() > 1 && SoFar
.second
== Prev
[(Prev
.size() - 1) / 2]) {
693 SoFar
.second
= nullptr;
701 ReferenceType(const Node
*Pointee_
, ReferenceKind RK_
)
702 : Node(KReferenceType
, Pointee_
->RHSComponentCache
),
703 Pointee(Pointee_
), RK(RK_
) {}
705 template<typename Fn
> void match(Fn F
) const { F(Pointee
, RK
); }
707 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
708 return Pointee
->hasRHSComponent(OB
);
711 void printLeft(OutputBuffer
&OB
) const override
{
714 ScopedOverride
<bool> SavePrinting(Printing
, true);
715 std::pair
<ReferenceKind
, const Node
*> Collapsed
= collapse(OB
);
716 if (!Collapsed
.second
)
718 Collapsed
.second
->printLeft(OB
);
719 if (Collapsed
.second
->hasArray(OB
))
721 if (Collapsed
.second
->hasArray(OB
) || Collapsed
.second
->hasFunction(OB
))
724 OB
+= (Collapsed
.first
== ReferenceKind::LValue
? "&" : "&&");
726 void printRight(OutputBuffer
&OB
) const override
{
729 ScopedOverride
<bool> SavePrinting(Printing
, true);
730 std::pair
<ReferenceKind
, const Node
*> Collapsed
= collapse(OB
);
731 if (!Collapsed
.second
)
733 if (Collapsed
.second
->hasArray(OB
) || Collapsed
.second
->hasFunction(OB
))
735 Collapsed
.second
->printRight(OB
);
739 class PointerToMemberType final
: public Node
{
740 const Node
*ClassType
;
741 const Node
*MemberType
;
744 PointerToMemberType(const Node
*ClassType_
, const Node
*MemberType_
)
745 : Node(KPointerToMemberType
, MemberType_
->RHSComponentCache
),
746 ClassType(ClassType_
), MemberType(MemberType_
) {}
748 template<typename Fn
> void match(Fn F
) const { F(ClassType
, MemberType
); }
750 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
751 return MemberType
->hasRHSComponent(OB
);
754 void printLeft(OutputBuffer
&OB
) const override
{
755 MemberType
->printLeft(OB
);
756 if (MemberType
->hasArray(OB
) || MemberType
->hasFunction(OB
))
760 ClassType
->print(OB
);
764 void printRight(OutputBuffer
&OB
) const override
{
765 if (MemberType
->hasArray(OB
) || MemberType
->hasFunction(OB
))
767 MemberType
->printRight(OB
);
771 class ArrayType final
: public Node
{
776 ArrayType(const Node
*Base_
, Node
*Dimension_
)
778 /*RHSComponentCache=*/Cache::Yes
,
779 /*ArrayCache=*/Cache::Yes
),
780 Base(Base_
), Dimension(Dimension_
) {}
782 template<typename Fn
> void match(Fn F
) const { F(Base
, Dimension
); }
784 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
785 bool hasArraySlow(OutputBuffer
&) const override
{ return true; }
787 void printLeft(OutputBuffer
&OB
) const override
{ Base
->printLeft(OB
); }
789 void printRight(OutputBuffer
&OB
) const override
{
790 if (OB
.back() != ']')
794 Dimension
->print(OB
);
796 Base
->printRight(OB
);
800 class FunctionType final
: public Node
{
804 FunctionRefQual RefQual
;
805 const Node
*ExceptionSpec
;
808 FunctionType(const Node
*Ret_
, NodeArray Params_
, Qualifiers CVQuals_
,
809 FunctionRefQual RefQual_
, const Node
*ExceptionSpec_
)
810 : Node(KFunctionType
,
811 /*RHSComponentCache=*/Cache::Yes
, /*ArrayCache=*/Cache::No
,
812 /*FunctionCache=*/Cache::Yes
),
813 Ret(Ret_
), Params(Params_
), CVQuals(CVQuals_
), RefQual(RefQual_
),
814 ExceptionSpec(ExceptionSpec_
) {}
816 template<typename Fn
> void match(Fn F
) const {
817 F(Ret
, Params
, CVQuals
, RefQual
, ExceptionSpec
);
820 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
821 bool hasFunctionSlow(OutputBuffer
&) const override
{ return true; }
823 // Handle C++'s ... quirky decl grammar by using the left & right
824 // distinction. Consider:
825 // int (*f(float))(char) {}
826 // f is a function that takes a float and returns a pointer to a function
827 // that takes a char and returns an int. If we're trying to print f, start
828 // by printing out the return types's left, then print our parameters, then
829 // finally print right of the return type.
830 void printLeft(OutputBuffer
&OB
) const override
{
835 void printRight(OutputBuffer
&OB
) const override
{
837 Params
.printWithComma(OB
);
841 if (CVQuals
& QualConst
)
843 if (CVQuals
& QualVolatile
)
845 if (CVQuals
& QualRestrict
)
848 if (RefQual
== FrefQualLValue
)
850 else if (RefQual
== FrefQualRValue
)
853 if (ExceptionSpec
!= nullptr) {
855 ExceptionSpec
->print(OB
);
860 class NoexceptSpec
: public Node
{
863 NoexceptSpec(const Node
*E_
) : Node(KNoexceptSpec
), E(E_
) {}
865 template<typename Fn
> void match(Fn F
) const { F(E
); }
867 void printLeft(OutputBuffer
&OB
) const override
{
870 E
->printAsOperand(OB
);
875 class DynamicExceptionSpec
: public Node
{
878 DynamicExceptionSpec(NodeArray Types_
)
879 : Node(KDynamicExceptionSpec
), Types(Types_
) {}
881 template<typename Fn
> void match(Fn F
) const { F(Types
); }
883 void printLeft(OutputBuffer
&OB
) const override
{
886 Types
.printWithComma(OB
);
891 /// Represents the explicitly named object parameter.
895 /// void bar(this Foo && self);
898 class ExplicitObjectParameter final
: public Node
{
902 ExplicitObjectParameter(Node
*Base_
)
903 : Node(KExplicitObjectParameter
), Base(Base_
) {
906 "Creating an ExplicitObjectParameter without a valid Base Node.");
909 template <typename Fn
> void match(Fn F
) const { F(Base
); }
911 void printLeft(OutputBuffer
&OB
) const override
{
917 class FunctionEncoding final
: public Node
{
922 const Node
*Requires
;
924 FunctionRefQual RefQual
;
927 FunctionEncoding(const Node
*Ret_
, const Node
*Name_
, NodeArray Params_
,
928 const Node
*Attrs_
, const Node
*Requires_
,
929 Qualifiers CVQuals_
, FunctionRefQual RefQual_
)
930 : Node(KFunctionEncoding
,
931 /*RHSComponentCache=*/Cache::Yes
, /*ArrayCache=*/Cache::No
,
932 /*FunctionCache=*/Cache::Yes
),
933 Ret(Ret_
), Name(Name_
), Params(Params_
), Attrs(Attrs_
),
934 Requires(Requires_
), CVQuals(CVQuals_
), RefQual(RefQual_
) {}
936 template<typename Fn
> void match(Fn F
) const {
937 F(Ret
, Name
, Params
, Attrs
, Requires
, CVQuals
, RefQual
);
940 Qualifiers
getCVQuals() const { return CVQuals
; }
941 FunctionRefQual
getRefQual() const { return RefQual
; }
942 NodeArray
getParams() const { return Params
; }
943 const Node
*getReturnType() const { return Ret
; }
945 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
946 bool hasFunctionSlow(OutputBuffer
&) const override
{ return true; }
948 const Node
*getName() const { return Name
; }
950 void printLeft(OutputBuffer
&OB
) const override
{
953 if (!Ret
->hasRHSComponent(OB
))
959 void printRight(OutputBuffer
&OB
) const override
{
961 Params
.printWithComma(OB
);
966 if (CVQuals
& QualConst
)
968 if (CVQuals
& QualVolatile
)
970 if (CVQuals
& QualRestrict
)
973 if (RefQual
== FrefQualLValue
)
975 else if (RefQual
== FrefQualRValue
)
978 if (Attrs
!= nullptr)
981 if (Requires
!= nullptr) {
988 class LiteralOperator
: public Node
{
992 LiteralOperator(const Node
*OpName_
)
993 : Node(KLiteralOperator
), OpName(OpName_
) {}
995 template<typename Fn
> void match(Fn F
) const { F(OpName
); }
997 void printLeft(OutputBuffer
&OB
) const override
{
998 OB
+= "operator\"\" ";
1003 class SpecialName final
: public Node
{
1004 const std::string_view Special
;
1008 SpecialName(std::string_view Special_
, const Node
*Child_
)
1009 : Node(KSpecialName
), Special(Special_
), Child(Child_
) {}
1011 template<typename Fn
> void match(Fn F
) const { F(Special
, Child
); }
1013 void printLeft(OutputBuffer
&OB
) const override
{
1019 class CtorVtableSpecialName final
: public Node
{
1020 const Node
*FirstType
;
1021 const Node
*SecondType
;
1024 CtorVtableSpecialName(const Node
*FirstType_
, const Node
*SecondType_
)
1025 : Node(KCtorVtableSpecialName
),
1026 FirstType(FirstType_
), SecondType(SecondType_
) {}
1028 template<typename Fn
> void match(Fn F
) const { F(FirstType
, SecondType
); }
1030 void printLeft(OutputBuffer
&OB
) const override
{
1031 OB
+= "construction vtable for ";
1032 FirstType
->print(OB
);
1034 SecondType
->print(OB
);
1038 struct NestedName
: Node
{
1042 NestedName(Node
*Qual_
, Node
*Name_
)
1043 : Node(KNestedName
), Qual(Qual_
), Name(Name_
) {}
1045 template<typename Fn
> void match(Fn F
) const { F(Qual
, Name
); }
1047 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1049 void printLeft(OutputBuffer
&OB
) const override
{
1056 struct MemberLikeFriendName
: Node
{
1060 MemberLikeFriendName(Node
*Qual_
, Node
*Name_
)
1061 : Node(KMemberLikeFriendName
), Qual(Qual_
), Name(Name_
) {}
1063 template<typename Fn
> void match(Fn F
) const { F(Qual
, Name
); }
1065 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1067 void printLeft(OutputBuffer
&OB
) const override
{
1074 struct ModuleName
: Node
{
1079 ModuleName(ModuleName
*Parent_
, Node
*Name_
, bool IsPartition_
= false)
1080 : Node(KModuleName
), Parent(Parent_
), Name(Name_
),
1081 IsPartition(IsPartition_
) {}
1083 template <typename Fn
> void match(Fn F
) const {
1084 F(Parent
, Name
, IsPartition
);
1087 void printLeft(OutputBuffer
&OB
) const override
{
1090 if (Parent
|| IsPartition
)
1091 OB
+= IsPartition
? ':' : '.';
1096 struct ModuleEntity
: Node
{
1100 ModuleEntity(ModuleName
*Module_
, Node
*Name_
)
1101 : Node(KModuleEntity
), Module(Module_
), Name(Name_
) {}
1103 template <typename Fn
> void match(Fn F
) const { F(Module
, Name
); }
1105 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1107 void printLeft(OutputBuffer
&OB
) const override
{
1114 struct LocalName
: Node
{
1118 LocalName(Node
*Encoding_
, Node
*Entity_
)
1119 : Node(KLocalName
), Encoding(Encoding_
), Entity(Entity_
) {}
1121 template<typename Fn
> void match(Fn F
) const { F(Encoding
, Entity
); }
1123 void printLeft(OutputBuffer
&OB
) const override
{
1124 Encoding
->print(OB
);
1130 class QualifiedName final
: public Node
{
1132 const Node
*Qualifier
;
1136 QualifiedName(const Node
*Qualifier_
, const Node
*Name_
)
1137 : Node(KQualifiedName
), Qualifier(Qualifier_
), Name(Name_
) {}
1139 template<typename Fn
> void match(Fn F
) const { F(Qualifier
, Name
); }
1141 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1143 void printLeft(OutputBuffer
&OB
) const override
{
1144 Qualifier
->print(OB
);
1150 class VectorType final
: public Node
{
1151 const Node
*BaseType
;
1152 const Node
*Dimension
;
1155 VectorType(const Node
*BaseType_
, const Node
*Dimension_
)
1156 : Node(KVectorType
), BaseType(BaseType_
), Dimension(Dimension_
) {}
1158 const Node
*getBaseType() const { return BaseType
; }
1159 const Node
*getDimension() const { return Dimension
; }
1161 template<typename Fn
> void match(Fn F
) const { F(BaseType
, Dimension
); }
1163 void printLeft(OutputBuffer
&OB
) const override
{
1164 BaseType
->print(OB
);
1167 Dimension
->print(OB
);
1172 class PixelVectorType final
: public Node
{
1173 const Node
*Dimension
;
1176 PixelVectorType(const Node
*Dimension_
)
1177 : Node(KPixelVectorType
), Dimension(Dimension_
) {}
1179 template<typename Fn
> void match(Fn F
) const { F(Dimension
); }
1181 void printLeft(OutputBuffer
&OB
) const override
{
1182 // FIXME: This should demangle as "vector pixel".
1183 OB
+= "pixel vector[";
1184 Dimension
->print(OB
);
1189 class BinaryFPType final
: public Node
{
1190 const Node
*Dimension
;
1193 BinaryFPType(const Node
*Dimension_
)
1194 : Node(KBinaryFPType
), Dimension(Dimension_
) {}
1196 template<typename Fn
> void match(Fn F
) const { F(Dimension
); }
1198 void printLeft(OutputBuffer
&OB
) const override
{
1200 Dimension
->print(OB
);
1204 enum class TemplateParamKind
{ Type
, NonType
, Template
};
1206 /// An invented name for a template parameter for which we don't have a
1207 /// corresponding template argument.
1209 /// This node is created when parsing the <lambda-sig> for a lambda with
1210 /// explicit template arguments, which might be referenced in the parameter
1211 /// types appearing later in the <lambda-sig>.
1212 class SyntheticTemplateParamName final
: public Node
{
1213 TemplateParamKind Kind
;
1217 SyntheticTemplateParamName(TemplateParamKind Kind_
, unsigned Index_
)
1218 : Node(KSyntheticTemplateParamName
), Kind(Kind_
), Index(Index_
) {}
1220 template<typename Fn
> void match(Fn F
) const { F(Kind
, Index
); }
1222 void printLeft(OutputBuffer
&OB
) const override
{
1224 case TemplateParamKind::Type
:
1227 case TemplateParamKind::NonType
:
1230 case TemplateParamKind::Template
:
1239 class TemplateParamQualifiedArg final
: public Node
{
1244 TemplateParamQualifiedArg(Node
*Param_
, Node
*Arg_
)
1245 : Node(KTemplateParamQualifiedArg
), Param(Param_
), Arg(Arg_
) {}
1247 template <typename Fn
> void match(Fn F
) const { F(Param
, Arg
); }
1249 Node
*getArg() { return Arg
; }
1251 void printLeft(OutputBuffer
&OB
) const override
{
1252 // Don't print Param to keep the output consistent.
1257 /// A template type parameter declaration, 'typename T'.
1258 class TypeTemplateParamDecl final
: public Node
{
1262 TypeTemplateParamDecl(Node
*Name_
)
1263 : Node(KTypeTemplateParamDecl
, Cache::Yes
), Name(Name_
) {}
1265 template<typename Fn
> void match(Fn F
) const { F(Name
); }
1267 void printLeft(OutputBuffer
&OB
) const override
{ OB
+= "typename "; }
1269 void printRight(OutputBuffer
&OB
) const override
{ Name
->print(OB
); }
1272 /// A constrained template type parameter declaration, 'C<U> T'.
1273 class ConstrainedTypeTemplateParamDecl final
: public Node
{
1278 ConstrainedTypeTemplateParamDecl(Node
*Constraint_
, Node
*Name_
)
1279 : Node(KConstrainedTypeTemplateParamDecl
, Cache::Yes
),
1280 Constraint(Constraint_
), Name(Name_
) {}
1282 template<typename Fn
> void match(Fn F
) const { F(Constraint
, Name
); }
1284 void printLeft(OutputBuffer
&OB
) const override
{
1285 Constraint
->print(OB
);
1289 void printRight(OutputBuffer
&OB
) const override
{ Name
->print(OB
); }
1292 /// A non-type template parameter declaration, 'int N'.
1293 class NonTypeTemplateParamDecl final
: public Node
{
1298 NonTypeTemplateParamDecl(Node
*Name_
, Node
*Type_
)
1299 : Node(KNonTypeTemplateParamDecl
, Cache::Yes
), Name(Name_
), Type(Type_
) {}
1301 template<typename Fn
> void match(Fn F
) const { F(Name
, Type
); }
1303 void printLeft(OutputBuffer
&OB
) const override
{
1304 Type
->printLeft(OB
);
1305 if (!Type
->hasRHSComponent(OB
))
1309 void printRight(OutputBuffer
&OB
) const override
{
1311 Type
->printRight(OB
);
1315 /// A template template parameter declaration,
1316 /// 'template<typename T> typename N'.
1317 class TemplateTemplateParamDecl final
: public Node
{
1323 TemplateTemplateParamDecl(Node
*Name_
, NodeArray Params_
, Node
*Requires_
)
1324 : Node(KTemplateTemplateParamDecl
, Cache::Yes
), Name(Name_
),
1325 Params(Params_
), Requires(Requires_
) {}
1327 template <typename Fn
> void match(Fn F
) const { F(Name
, Params
, Requires
); }
1329 void printLeft(OutputBuffer
&OB
) const override
{
1330 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1332 Params
.printWithComma(OB
);
1333 OB
+= "> typename ";
1336 void printRight(OutputBuffer
&OB
) const override
{
1338 if (Requires
!= nullptr) {
1340 Requires
->print(OB
);
1345 /// A template parameter pack declaration, 'typename ...T'.
1346 class TemplateParamPackDecl final
: public Node
{
1350 TemplateParamPackDecl(Node
*Param_
)
1351 : Node(KTemplateParamPackDecl
, Cache::Yes
), Param(Param_
) {}
1353 template<typename Fn
> void match(Fn F
) const { F(Param
); }
1355 void printLeft(OutputBuffer
&OB
) const override
{
1356 Param
->printLeft(OB
);
1360 void printRight(OutputBuffer
&OB
) const override
{ Param
->printRight(OB
); }
1363 /// An unexpanded parameter pack (either in the expression or type context). If
1364 /// this AST is correct, this node will have a ParameterPackExpansion node above
1367 /// This node is created when some <template-args> are found that apply to an
1368 /// <encoding>, and is stored in the TemplateParams table. In order for this to
1369 /// appear in the final AST, it has to referenced via a <template-param> (ie,
1371 class ParameterPack final
: public Node
{
1374 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1376 void initializePackExpansion(OutputBuffer
&OB
) const {
1377 if (OB
.CurrentPackMax
== std::numeric_limits
<unsigned>::max()) {
1378 OB
.CurrentPackMax
= static_cast<unsigned>(Data
.size());
1379 OB
.CurrentPackIndex
= 0;
1384 ParameterPack(NodeArray Data_
) : Node(KParameterPack
), Data(Data_
) {
1385 ArrayCache
= FunctionCache
= RHSComponentCache
= Cache::Unknown
;
1386 if (std::all_of(Data
.begin(), Data
.end(), [](Node
* P
) {
1387 return P
->ArrayCache
== Cache::No
;
1389 ArrayCache
= Cache::No
;
1390 if (std::all_of(Data
.begin(), Data
.end(), [](Node
* P
) {
1391 return P
->FunctionCache
== Cache::No
;
1393 FunctionCache
= Cache::No
;
1394 if (std::all_of(Data
.begin(), Data
.end(), [](Node
* P
) {
1395 return P
->RHSComponentCache
== Cache::No
;
1397 RHSComponentCache
= Cache::No
;
1400 template<typename Fn
> void match(Fn F
) const { F(Data
); }
1402 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
1403 initializePackExpansion(OB
);
1404 size_t Idx
= OB
.CurrentPackIndex
;
1405 return Idx
< Data
.size() && Data
[Idx
]->hasRHSComponent(OB
);
1407 bool hasArraySlow(OutputBuffer
&OB
) const override
{
1408 initializePackExpansion(OB
);
1409 size_t Idx
= OB
.CurrentPackIndex
;
1410 return Idx
< Data
.size() && Data
[Idx
]->hasArray(OB
);
1412 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
1413 initializePackExpansion(OB
);
1414 size_t Idx
= OB
.CurrentPackIndex
;
1415 return Idx
< Data
.size() && Data
[Idx
]->hasFunction(OB
);
1417 const Node
*getSyntaxNode(OutputBuffer
&OB
) const override
{
1418 initializePackExpansion(OB
);
1419 size_t Idx
= OB
.CurrentPackIndex
;
1420 return Idx
< Data
.size() ? Data
[Idx
]->getSyntaxNode(OB
) : this;
1423 void printLeft(OutputBuffer
&OB
) const override
{
1424 initializePackExpansion(OB
);
1425 size_t Idx
= OB
.CurrentPackIndex
;
1426 if (Idx
< Data
.size())
1427 Data
[Idx
]->printLeft(OB
);
1429 void printRight(OutputBuffer
&OB
) const override
{
1430 initializePackExpansion(OB
);
1431 size_t Idx
= OB
.CurrentPackIndex
;
1432 if (Idx
< Data
.size())
1433 Data
[Idx
]->printRight(OB
);
1437 /// A variadic template argument. This node represents an occurrence of
1438 /// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1439 /// one of its Elements is. The parser inserts a ParameterPack into the
1440 /// TemplateParams table if the <template-args> this pack belongs to apply to an
1442 class TemplateArgumentPack final
: public Node
{
1445 TemplateArgumentPack(NodeArray Elements_
)
1446 : Node(KTemplateArgumentPack
), Elements(Elements_
) {}
1448 template<typename Fn
> void match(Fn F
) const { F(Elements
); }
1450 NodeArray
getElements() const { return Elements
; }
1452 void printLeft(OutputBuffer
&OB
) const override
{
1453 Elements
.printWithComma(OB
);
1457 /// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1458 /// which each have Child->ParameterPackSize elements.
1459 class ParameterPackExpansion final
: public Node
{
1463 ParameterPackExpansion(const Node
*Child_
)
1464 : Node(KParameterPackExpansion
), Child(Child_
) {}
1466 template<typename Fn
> void match(Fn F
) const { F(Child
); }
1468 const Node
*getChild() const { return Child
; }
1470 void printLeft(OutputBuffer
&OB
) const override
{
1471 constexpr unsigned Max
= std::numeric_limits
<unsigned>::max();
1472 ScopedOverride
<unsigned> SavePackIdx(OB
.CurrentPackIndex
, Max
);
1473 ScopedOverride
<unsigned> SavePackMax(OB
.CurrentPackMax
, Max
);
1474 size_t StreamPos
= OB
.getCurrentPosition();
1476 // Print the first element in the pack. If Child contains a ParameterPack,
1477 // it will set up S.CurrentPackMax and print the first element.
1480 // No ParameterPack was found in Child. This can occur if we've found a pack
1481 // expansion on a <function-param>.
1482 if (OB
.CurrentPackMax
== Max
) {
1487 // We found a ParameterPack, but it has no elements. Erase whatever we may
1489 if (OB
.CurrentPackMax
== 0) {
1490 OB
.setCurrentPosition(StreamPos
);
1494 // Else, iterate through the rest of the elements in the pack.
1495 for (unsigned I
= 1, E
= OB
.CurrentPackMax
; I
< E
; ++I
) {
1497 OB
.CurrentPackIndex
= I
;
1503 class TemplateArgs final
: public Node
{
1508 TemplateArgs(NodeArray Params_
, Node
*Requires_
)
1509 : Node(KTemplateArgs
), Params(Params_
), Requires(Requires_
) {}
1511 template<typename Fn
> void match(Fn F
) const { F(Params
, Requires
); }
1513 NodeArray
getParams() { return Params
; }
1515 void printLeft(OutputBuffer
&OB
) const override
{
1516 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1518 Params
.printWithComma(OB
);
1520 // Don't print the requires clause to keep the output simple.
1524 /// A forward-reference to a template argument that was not known at the point
1525 /// where the template parameter name was parsed in a mangling.
1527 /// This is created when demangling the name of a specialization of a
1528 /// conversion function template:
1532 /// template<typename T> operator T*();
1536 /// When demangling a specialization of the conversion function template, we
1537 /// encounter the name of the template (including the \c T) before we reach
1538 /// the template argument list, so we cannot substitute the parameter name
1539 /// for the corresponding argument while parsing. Instead, we create a
1540 /// \c ForwardTemplateReference node that is resolved after we parse the
1541 /// template arguments.
1542 struct ForwardTemplateReference
: Node
{
1544 Node
*Ref
= nullptr;
1546 // If we're currently printing this node. It is possible (though invalid) for
1547 // a forward template reference to refer to itself via a substitution. This
1548 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1549 // out if more than one print* function is active.
1550 mutable bool Printing
= false;
1552 ForwardTemplateReference(size_t Index_
)
1553 : Node(KForwardTemplateReference
, Cache::Unknown
, Cache::Unknown
,
1557 // We don't provide a matcher for these, because the value of the node is
1558 // not determined by its construction parameters, and it generally needs
1559 // special handling.
1560 template<typename Fn
> void match(Fn F
) const = delete;
1562 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
1565 ScopedOverride
<bool> SavePrinting(Printing
, true);
1566 return Ref
->hasRHSComponent(OB
);
1568 bool hasArraySlow(OutputBuffer
&OB
) const override
{
1571 ScopedOverride
<bool> SavePrinting(Printing
, true);
1572 return Ref
->hasArray(OB
);
1574 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
1577 ScopedOverride
<bool> SavePrinting(Printing
, true);
1578 return Ref
->hasFunction(OB
);
1580 const Node
*getSyntaxNode(OutputBuffer
&OB
) const override
{
1583 ScopedOverride
<bool> SavePrinting(Printing
, true);
1584 return Ref
->getSyntaxNode(OB
);
1587 void printLeft(OutputBuffer
&OB
) const override
{
1590 ScopedOverride
<bool> SavePrinting(Printing
, true);
1593 void printRight(OutputBuffer
&OB
) const override
{
1596 ScopedOverride
<bool> SavePrinting(Printing
, true);
1597 Ref
->printRight(OB
);
1601 struct NameWithTemplateArgs
: Node
{
1602 // name<template_args>
1606 NameWithTemplateArgs(Node
*Name_
, Node
*TemplateArgs_
)
1607 : Node(KNameWithTemplateArgs
), Name(Name_
), TemplateArgs(TemplateArgs_
) {}
1609 template<typename Fn
> void match(Fn F
) const { F(Name
, TemplateArgs
); }
1611 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1613 void printLeft(OutputBuffer
&OB
) const override
{
1615 TemplateArgs
->print(OB
);
1619 class GlobalQualifiedName final
: public Node
{
1623 GlobalQualifiedName(Node
* Child_
)
1624 : Node(KGlobalQualifiedName
), Child(Child_
) {}
1626 template<typename Fn
> void match(Fn F
) const { F(Child
); }
1628 std::string_view
getBaseName() const override
{ return Child
->getBaseName(); }
1630 void printLeft(OutputBuffer
&OB
) const override
{
1636 enum class SpecialSubKind
{
1645 class SpecialSubstitution
;
1646 class ExpandedSpecialSubstitution
: public Node
{
1650 ExpandedSpecialSubstitution(SpecialSubKind SSK_
, Kind K_
)
1651 : Node(K_
), SSK(SSK_
) {}
1653 ExpandedSpecialSubstitution(SpecialSubKind SSK_
)
1654 : ExpandedSpecialSubstitution(SSK_
, KExpandedSpecialSubstitution
) {}
1655 inline ExpandedSpecialSubstitution(SpecialSubstitution
const *);
1657 template<typename Fn
> void match(Fn F
) const { F(SSK
); }
1660 bool isInstantiation() const {
1661 return unsigned(SSK
) >= unsigned(SpecialSubKind::string
);
1664 std::string_view
getBaseName() const override
{
1666 case SpecialSubKind::allocator
:
1667 return {"allocator"};
1668 case SpecialSubKind::basic_string
:
1669 return {"basic_string"};
1670 case SpecialSubKind::string
:
1671 return {"basic_string"};
1672 case SpecialSubKind::istream
:
1673 return {"basic_istream"};
1674 case SpecialSubKind::ostream
:
1675 return {"basic_ostream"};
1676 case SpecialSubKind::iostream
:
1677 return {"basic_iostream"};
1679 DEMANGLE_UNREACHABLE
;
1683 void printLeft(OutputBuffer
&OB
) const override
{
1684 OB
<< "std::" << getBaseName();
1685 if (isInstantiation()) {
1686 OB
<< "<char, std::char_traits<char>";
1687 if (SSK
== SpecialSubKind::string
)
1688 OB
<< ", std::allocator<char>";
1694 class SpecialSubstitution final
: public ExpandedSpecialSubstitution
{
1696 SpecialSubstitution(SpecialSubKind SSK_
)
1697 : ExpandedSpecialSubstitution(SSK_
, KSpecialSubstitution
) {}
1699 template<typename Fn
> void match(Fn F
) const { F(SSK
); }
1701 std::string_view
getBaseName() const override
{
1702 std::string_view SV
= ExpandedSpecialSubstitution::getBaseName();
1703 if (isInstantiation()) {
1704 // The instantiations are typedefs that drop the "basic_" prefix.
1705 DEMANGLE_ASSERT(starts_with(SV
, "basic_"), "");
1706 SV
.remove_prefix(sizeof("basic_") - 1);
1711 void printLeft(OutputBuffer
&OB
) const override
{
1712 OB
<< "std::" << getBaseName();
1716 inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(
1717 SpecialSubstitution
const *SS
)
1718 : ExpandedSpecialSubstitution(SS
->SSK
) {}
1720 class CtorDtorName final
: public Node
{
1721 const Node
*Basename
;
1726 CtorDtorName(const Node
*Basename_
, bool IsDtor_
, int Variant_
)
1727 : Node(KCtorDtorName
), Basename(Basename_
), IsDtor(IsDtor_
),
1728 Variant(Variant_
) {}
1730 template<typename Fn
> void match(Fn F
) const { F(Basename
, IsDtor
, Variant
); }
1732 void printLeft(OutputBuffer
&OB
) const override
{
1735 OB
+= Basename
->getBaseName();
1739 class DtorName
: public Node
{
1743 DtorName(const Node
*Base_
) : Node(KDtorName
), Base(Base_
) {}
1745 template<typename Fn
> void match(Fn F
) const { F(Base
); }
1747 void printLeft(OutputBuffer
&OB
) const override
{
1749 Base
->printLeft(OB
);
1753 class UnnamedTypeName
: public Node
{
1754 const std::string_view Count
;
1757 UnnamedTypeName(std::string_view Count_
)
1758 : Node(KUnnamedTypeName
), Count(Count_
) {}
1760 template<typename Fn
> void match(Fn F
) const { F(Count
); }
1762 void printLeft(OutputBuffer
&OB
) const override
{
1769 class ClosureTypeName
: public Node
{
1770 NodeArray TemplateParams
;
1771 const Node
*Requires1
;
1773 const Node
*Requires2
;
1774 std::string_view Count
;
1777 ClosureTypeName(NodeArray TemplateParams_
, const Node
*Requires1_
,
1778 NodeArray Params_
, const Node
*Requires2_
,
1779 std::string_view Count_
)
1780 : Node(KClosureTypeName
), TemplateParams(TemplateParams_
),
1781 Requires1(Requires1_
), Params(Params_
), Requires2(Requires2_
),
1784 template<typename Fn
> void match(Fn F
) const {
1785 F(TemplateParams
, Requires1
, Params
, Requires2
, Count
);
1788 void printDeclarator(OutputBuffer
&OB
) const {
1789 if (!TemplateParams
.empty()) {
1790 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1792 TemplateParams
.printWithComma(OB
);
1795 if (Requires1
!= nullptr) {
1797 Requires1
->print(OB
);
1801 Params
.printWithComma(OB
);
1803 if (Requires2
!= nullptr) {
1805 Requires2
->print(OB
);
1809 void printLeft(OutputBuffer
&OB
) const override
{
1810 // FIXME: This demangling is not particularly readable.
1814 printDeclarator(OB
);
1818 class StructuredBindingName
: public Node
{
1821 StructuredBindingName(NodeArray Bindings_
)
1822 : Node(KStructuredBindingName
), Bindings(Bindings_
) {}
1824 template<typename Fn
> void match(Fn F
) const { F(Bindings
); }
1826 void printLeft(OutputBuffer
&OB
) const override
{
1828 Bindings
.printWithComma(OB
);
1833 // -- Expression Nodes --
1835 class BinaryExpr
: public Node
{
1837 const std::string_view InfixOperator
;
1841 BinaryExpr(const Node
*LHS_
, std::string_view InfixOperator_
,
1842 const Node
*RHS_
, Prec Prec_
)
1843 : Node(KBinaryExpr
, Prec_
), LHS(LHS_
), InfixOperator(InfixOperator_
),
1846 template <typename Fn
> void match(Fn F
) const {
1847 F(LHS
, InfixOperator
, RHS
, getPrecedence());
1850 void printLeft(OutputBuffer
&OB
) const override
{
1851 bool ParenAll
= OB
.isGtInsideTemplateArgs() &&
1852 (InfixOperator
== ">" || InfixOperator
== ">>");
1855 // Assignment is right associative, with special LHS precedence.
1856 bool IsAssign
= getPrecedence() == Prec::Assign
;
1857 LHS
->printAsOperand(OB
, IsAssign
? Prec::OrIf
: getPrecedence(), !IsAssign
);
1858 // No space before comma operator
1859 if (!(InfixOperator
== ","))
1861 OB
+= InfixOperator
;
1863 RHS
->printAsOperand(OB
, getPrecedence(), IsAssign
);
1869 class ArraySubscriptExpr
: public Node
{
1874 ArraySubscriptExpr(const Node
*Op1_
, const Node
*Op2_
, Prec Prec_
)
1875 : Node(KArraySubscriptExpr
, Prec_
), Op1(Op1_
), Op2(Op2_
) {}
1877 template <typename Fn
> void match(Fn F
) const {
1878 F(Op1
, Op2
, getPrecedence());
1881 void printLeft(OutputBuffer
&OB
) const override
{
1882 Op1
->printAsOperand(OB
, getPrecedence());
1884 Op2
->printAsOperand(OB
);
1889 class PostfixExpr
: public Node
{
1891 const std::string_view Operator
;
1894 PostfixExpr(const Node
*Child_
, std::string_view Operator_
, Prec Prec_
)
1895 : Node(KPostfixExpr
, Prec_
), Child(Child_
), Operator(Operator_
) {}
1897 template <typename Fn
> void match(Fn F
) const {
1898 F(Child
, Operator
, getPrecedence());
1901 void printLeft(OutputBuffer
&OB
) const override
{
1902 Child
->printAsOperand(OB
, getPrecedence(), true);
1907 class ConditionalExpr
: public Node
{
1913 ConditionalExpr(const Node
*Cond_
, const Node
*Then_
, const Node
*Else_
,
1915 : Node(KConditionalExpr
, Prec_
), Cond(Cond_
), Then(Then_
), Else(Else_
) {}
1917 template <typename Fn
> void match(Fn F
) const {
1918 F(Cond
, Then
, Else
, getPrecedence());
1921 void printLeft(OutputBuffer
&OB
) const override
{
1922 Cond
->printAsOperand(OB
, getPrecedence());
1924 Then
->printAsOperand(OB
);
1926 Else
->printAsOperand(OB
, Prec::Assign
, true);
1930 class MemberExpr
: public Node
{
1932 const std::string_view Kind
;
1936 MemberExpr(const Node
*LHS_
, std::string_view Kind_
, const Node
*RHS_
,
1938 : Node(KMemberExpr
, Prec_
), LHS(LHS_
), Kind(Kind_
), RHS(RHS_
) {}
1940 template <typename Fn
> void match(Fn F
) const {
1941 F(LHS
, Kind
, RHS
, getPrecedence());
1944 void printLeft(OutputBuffer
&OB
) const override
{
1945 LHS
->printAsOperand(OB
, getPrecedence(), true);
1947 RHS
->printAsOperand(OB
, getPrecedence(), false);
1951 class SubobjectExpr
: public Node
{
1953 const Node
*SubExpr
;
1954 std::string_view Offset
;
1955 NodeArray UnionSelectors
;
1959 SubobjectExpr(const Node
*Type_
, const Node
*SubExpr_
,
1960 std::string_view Offset_
, NodeArray UnionSelectors_
,
1961 bool OnePastTheEnd_
)
1962 : Node(KSubobjectExpr
), Type(Type_
), SubExpr(SubExpr_
), Offset(Offset_
),
1963 UnionSelectors(UnionSelectors_
), OnePastTheEnd(OnePastTheEnd_
) {}
1965 template<typename Fn
> void match(Fn F
) const {
1966 F(Type
, SubExpr
, Offset
, UnionSelectors
, OnePastTheEnd
);
1969 void printLeft(OutputBuffer
&OB
) const override
{
1973 OB
+= " at offset ";
1974 if (Offset
.empty()) {
1976 } else if (Offset
[0] == 'n') {
1978 OB
+= std::string_view(Offset
.data() + 1, Offset
.size() - 1);
1986 class EnclosingExpr
: public Node
{
1987 const std::string_view Prefix
;
1989 const std::string_view Postfix
;
1992 EnclosingExpr(std::string_view Prefix_
, const Node
*Infix_
,
1993 Prec Prec_
= Prec::Primary
)
1994 : Node(KEnclosingExpr
, Prec_
), Prefix(Prefix_
), Infix(Infix_
) {}
1996 template <typename Fn
> void match(Fn F
) const {
1997 F(Prefix
, Infix
, getPrecedence());
2000 void printLeft(OutputBuffer
&OB
) const override
{
2009 class CastExpr
: public Node
{
2010 // cast_kind<to>(from)
2011 const std::string_view CastKind
;
2016 CastExpr(std::string_view CastKind_
, const Node
*To_
, const Node
*From_
,
2018 : Node(KCastExpr
, Prec_
), CastKind(CastKind_
), To(To_
), From(From_
) {}
2020 template <typename Fn
> void match(Fn F
) const {
2021 F(CastKind
, To
, From
, getPrecedence());
2024 void printLeft(OutputBuffer
&OB
) const override
{
2027 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
2033 From
->printAsOperand(OB
);
2038 class SizeofParamPackExpr
: public Node
{
2042 SizeofParamPackExpr(const Node
*Pack_
)
2043 : Node(KSizeofParamPackExpr
), Pack(Pack_
) {}
2045 template<typename Fn
> void match(Fn F
) const { F(Pack
); }
2047 void printLeft(OutputBuffer
&OB
) const override
{
2050 ParameterPackExpansion
PPE(Pack
);
2056 class CallExpr
: public Node
{
2061 CallExpr(const Node
*Callee_
, NodeArray Args_
, Prec Prec_
)
2062 : Node(KCallExpr
, Prec_
), Callee(Callee_
), Args(Args_
) {}
2064 template <typename Fn
> void match(Fn F
) const {
2065 F(Callee
, Args
, getPrecedence());
2068 void printLeft(OutputBuffer
&OB
) const override
{
2071 Args
.printWithComma(OB
);
2076 class NewExpr
: public Node
{
2077 // new (expr_list) type(init_list)
2081 bool IsGlobal
; // ::operator new ?
2082 bool IsArray
; // new[] ?
2084 NewExpr(NodeArray ExprList_
, Node
*Type_
, NodeArray InitList_
, bool IsGlobal_
,
2085 bool IsArray_
, Prec Prec_
)
2086 : Node(KNewExpr
, Prec_
), ExprList(ExprList_
), Type(Type_
),
2087 InitList(InitList_
), IsGlobal(IsGlobal_
), IsArray(IsArray_
) {}
2089 template<typename Fn
> void match(Fn F
) const {
2090 F(ExprList
, Type
, InitList
, IsGlobal
, IsArray
, getPrecedence());
2093 void printLeft(OutputBuffer
&OB
) const override
{
2099 if (!ExprList
.empty()) {
2101 ExprList
.printWithComma(OB
);
2106 if (!InitList
.empty()) {
2108 InitList
.printWithComma(OB
);
2114 class DeleteExpr
: public Node
{
2120 DeleteExpr(Node
*Op_
, bool IsGlobal_
, bool IsArray_
, Prec Prec_
)
2121 : Node(KDeleteExpr
, Prec_
), Op(Op_
), IsGlobal(IsGlobal_
),
2122 IsArray(IsArray_
) {}
2124 template <typename Fn
> void match(Fn F
) const {
2125 F(Op
, IsGlobal
, IsArray
, getPrecedence());
2128 void printLeft(OutputBuffer
&OB
) const override
{
2139 class PrefixExpr
: public Node
{
2140 std::string_view Prefix
;
2144 PrefixExpr(std::string_view Prefix_
, Node
*Child_
, Prec Prec_
)
2145 : Node(KPrefixExpr
, Prec_
), Prefix(Prefix_
), Child(Child_
) {}
2147 template <typename Fn
> void match(Fn F
) const {
2148 F(Prefix
, Child
, getPrecedence());
2151 void printLeft(OutputBuffer
&OB
) const override
{
2153 Child
->printAsOperand(OB
, getPrecedence());
2157 class FunctionParam
: public Node
{
2158 std::string_view Number
;
2161 FunctionParam(std::string_view Number_
)
2162 : Node(KFunctionParam
), Number(Number_
) {}
2164 template<typename Fn
> void match(Fn F
) const { F(Number
); }
2166 void printLeft(OutputBuffer
&OB
) const override
{
2172 class ConversionExpr
: public Node
{
2174 NodeArray Expressions
;
2177 ConversionExpr(const Node
*Type_
, NodeArray Expressions_
, Prec Prec_
)
2178 : Node(KConversionExpr
, Prec_
), Type(Type_
), Expressions(Expressions_
) {}
2180 template <typename Fn
> void match(Fn F
) const {
2181 F(Type
, Expressions
, getPrecedence());
2184 void printLeft(OutputBuffer
&OB
) const override
{
2189 Expressions
.printWithComma(OB
);
2194 class PointerToMemberConversionExpr
: public Node
{
2196 const Node
*SubExpr
;
2197 std::string_view Offset
;
2200 PointerToMemberConversionExpr(const Node
*Type_
, const Node
*SubExpr_
,
2201 std::string_view Offset_
, Prec Prec_
)
2202 : Node(KPointerToMemberConversionExpr
, Prec_
), Type(Type_
),
2203 SubExpr(SubExpr_
), Offset(Offset_
) {}
2205 template <typename Fn
> void match(Fn F
) const {
2206 F(Type
, SubExpr
, Offset
, getPrecedence());
2209 void printLeft(OutputBuffer
&OB
) const override
{
2219 class InitListExpr
: public Node
{
2223 InitListExpr(const Node
*Ty_
, NodeArray Inits_
)
2224 : Node(KInitListExpr
), Ty(Ty_
), Inits(Inits_
) {}
2226 template<typename Fn
> void match(Fn F
) const { F(Ty
, Inits
); }
2228 void printLeft(OutputBuffer
&OB
) const override
{
2232 Inits
.printWithComma(OB
);
2237 class BracedExpr
: public Node
{
2242 BracedExpr(const Node
*Elem_
, const Node
*Init_
, bool IsArray_
)
2243 : Node(KBracedExpr
), Elem(Elem_
), Init(Init_
), IsArray(IsArray_
) {}
2245 template<typename Fn
> void match(Fn F
) const { F(Elem
, Init
, IsArray
); }
2247 void printLeft(OutputBuffer
&OB
) const override
{
2256 if (Init
->getKind() != KBracedExpr
&& Init
->getKind() != KBracedRangeExpr
)
2262 class BracedRangeExpr
: public Node
{
2267 BracedRangeExpr(const Node
*First_
, const Node
*Last_
, const Node
*Init_
)
2268 : Node(KBracedRangeExpr
), First(First_
), Last(Last_
), Init(Init_
) {}
2270 template<typename Fn
> void match(Fn F
) const { F(First
, Last
, Init
); }
2272 void printLeft(OutputBuffer
&OB
) const override
{
2278 if (Init
->getKind() != KBracedExpr
&& Init
->getKind() != KBracedRangeExpr
)
2284 class FoldExpr
: public Node
{
2285 const Node
*Pack
, *Init
;
2286 std::string_view OperatorName
;
2290 FoldExpr(bool IsLeftFold_
, std::string_view OperatorName_
, const Node
*Pack_
,
2292 : Node(KFoldExpr
), Pack(Pack_
), Init(Init_
), OperatorName(OperatorName_
),
2293 IsLeftFold(IsLeftFold_
) {}
2295 template<typename Fn
> void match(Fn F
) const {
2296 F(IsLeftFold
, OperatorName
, Pack
, Init
);
2299 void printLeft(OutputBuffer
&OB
) const override
{
2300 auto PrintPack
= [&] {
2302 ParameterPackExpansion(Pack
).print(OB
);
2307 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2308 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2309 // Fold expr operands are cast-expressions
2310 if (!IsLeftFold
|| Init
!= nullptr) {
2311 // '(init|pack) op '
2313 Init
->printAsOperand(OB
, Prec::Cast
, true);
2316 OB
<< " " << OperatorName
<< " ";
2319 if (IsLeftFold
|| Init
!= nullptr) {
2320 // ' op (init|pack)'
2321 OB
<< " " << OperatorName
<< " ";
2325 Init
->printAsOperand(OB
, Prec::Cast
, true);
2331 class ThrowExpr
: public Node
{
2335 ThrowExpr(const Node
*Op_
) : Node(KThrowExpr
), Op(Op_
) {}
2337 template<typename Fn
> void match(Fn F
) const { F(Op
); }
2339 void printLeft(OutputBuffer
&OB
) const override
{
2345 class BoolExpr
: public Node
{
2349 BoolExpr(bool Value_
) : Node(KBoolExpr
), Value(Value_
) {}
2351 template<typename Fn
> void match(Fn F
) const { F(Value
); }
2353 void printLeft(OutputBuffer
&OB
) const override
{
2354 OB
+= Value
? std::string_view("true") : std::string_view("false");
2358 class StringLiteral
: public Node
{
2362 StringLiteral(const Node
*Type_
) : Node(KStringLiteral
), Type(Type_
) {}
2364 template<typename Fn
> void match(Fn F
) const { F(Type
); }
2366 void printLeft(OutputBuffer
&OB
) const override
{
2373 class LambdaExpr
: public Node
{
2377 LambdaExpr(const Node
*Type_
) : Node(KLambdaExpr
), Type(Type_
) {}
2379 template<typename Fn
> void match(Fn F
) const { F(Type
); }
2381 void printLeft(OutputBuffer
&OB
) const override
{
2383 if (Type
->getKind() == KClosureTypeName
)
2384 static_cast<const ClosureTypeName
*>(Type
)->printDeclarator(OB
);
2389 class EnumLiteral
: public Node
{
2392 std::string_view Integer
;
2395 EnumLiteral(const Node
*Ty_
, std::string_view Integer_
)
2396 : Node(KEnumLiteral
), Ty(Ty_
), Integer(Integer_
) {}
2398 template<typename Fn
> void match(Fn F
) const { F(Ty
, Integer
); }
2400 void printLeft(OutputBuffer
&OB
) const override
{
2405 if (Integer
[0] == 'n')
2406 OB
<< '-' << std::string_view(Integer
.data() + 1, Integer
.size() - 1);
2412 class IntegerLiteral
: public Node
{
2413 std::string_view Type
;
2414 std::string_view Value
;
2417 IntegerLiteral(std::string_view Type_
, std::string_view Value_
)
2418 : Node(KIntegerLiteral
), Type(Type_
), Value(Value_
) {}
2420 template<typename Fn
> void match(Fn F
) const { F(Type
, Value
); }
2422 void printLeft(OutputBuffer
&OB
) const override
{
2423 if (Type
.size() > 3) {
2429 if (Value
[0] == 'n')
2430 OB
<< '-' << std::string_view(Value
.data() + 1, Value
.size() - 1);
2434 if (Type
.size() <= 3)
2439 class RequiresExpr
: public Node
{
2440 NodeArray Parameters
;
2441 NodeArray Requirements
;
2443 RequiresExpr(NodeArray Parameters_
, NodeArray Requirements_
)
2444 : Node(KRequiresExpr
), Parameters(Parameters_
),
2445 Requirements(Requirements_
) {}
2447 template<typename Fn
> void match(Fn F
) const { F(Parameters
, Requirements
); }
2449 void printLeft(OutputBuffer
&OB
) const override
{
2451 if (!Parameters
.empty()) {
2454 Parameters
.printWithComma(OB
);
2459 for (const Node
*Req
: Requirements
) {
2467 class ExprRequirement
: public Node
{
2470 const Node
*TypeConstraint
;
2472 ExprRequirement(const Node
*Expr_
, bool IsNoexcept_
,
2473 const Node
*TypeConstraint_
)
2474 : Node(KExprRequirement
), Expr(Expr_
), IsNoexcept(IsNoexcept_
),
2475 TypeConstraint(TypeConstraint_
) {}
2477 template <typename Fn
> void match(Fn F
) const {
2478 F(Expr
, IsNoexcept
, TypeConstraint
);
2481 void printLeft(OutputBuffer
&OB
) const override
{
2483 if (IsNoexcept
|| TypeConstraint
)
2486 if (IsNoexcept
|| TypeConstraint
)
2490 if (TypeConstraint
) {
2492 TypeConstraint
->print(OB
);
2498 class TypeRequirement
: public Node
{
2501 TypeRequirement(const Node
*Type_
)
2502 : Node(KTypeRequirement
), Type(Type_
) {}
2504 template <typename Fn
> void match(Fn F
) const { F(Type
); }
2506 void printLeft(OutputBuffer
&OB
) const override
{
2513 class NestedRequirement
: public Node
{
2514 const Node
*Constraint
;
2516 NestedRequirement(const Node
*Constraint_
)
2517 : Node(KNestedRequirement
), Constraint(Constraint_
) {}
2519 template <typename Fn
> void match(Fn F
) const { F(Constraint
); }
2521 void printLeft(OutputBuffer
&OB
) const override
{
2523 Constraint
->print(OB
);
2528 template <class Float
> struct FloatData
;
2530 namespace float_literal_impl
{
2531 constexpr Node::Kind
getFloatLiteralKind(float *) {
2532 return Node::KFloatLiteral
;
2534 constexpr Node::Kind
getFloatLiteralKind(double *) {
2535 return Node::KDoubleLiteral
;
2537 constexpr Node::Kind
getFloatLiteralKind(long double *) {
2538 return Node::KLongDoubleLiteral
;
2542 template <class Float
> class FloatLiteralImpl
: public Node
{
2543 const std::string_view Contents
;
2545 static constexpr Kind KindForClass
=
2546 float_literal_impl::getFloatLiteralKind((Float
*)nullptr);
2549 FloatLiteralImpl(std::string_view Contents_
)
2550 : Node(KindForClass
), Contents(Contents_
) {}
2552 template<typename Fn
> void match(Fn F
) const { F(Contents
); }
2554 void printLeft(OutputBuffer
&OB
) const override
{
2555 const size_t N
= FloatData
<Float
>::mangled_size
;
2556 if (Contents
.size() >= N
) {
2559 char buf
[sizeof(Float
)];
2561 const char *t
= Contents
.data();
2562 const char *last
= t
+ N
;
2564 for (; t
!= last
; ++t
, ++e
) {
2565 unsigned d1
= isdigit(*t
) ? static_cast<unsigned>(*t
- '0')
2566 : static_cast<unsigned>(*t
- 'a' + 10);
2568 unsigned d0
= isdigit(*t
) ? static_cast<unsigned>(*t
- '0')
2569 : static_cast<unsigned>(*t
- 'a' + 10);
2570 *e
= static_cast<char>((d1
<< 4) + d0
);
2572 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2573 std::reverse(buf
, e
);
2575 char num
[FloatData
<Float
>::max_demangled_size
] = {0};
2576 int n
= snprintf(num
, sizeof(num
), FloatData
<Float
>::spec
, value
);
2577 OB
+= std::string_view(num
, n
);
2582 using FloatLiteral
= FloatLiteralImpl
<float>;
2583 using DoubleLiteral
= FloatLiteralImpl
<double>;
2584 using LongDoubleLiteral
= FloatLiteralImpl
<long double>;
2586 /// Visit the node. Calls \c F(P), where \c P is the node cast to the
2587 /// appropriate derived class.
2588 template<typename Fn
>
2589 void Node::visit(Fn F
) const {
2593 return F(static_cast<const X *>(this));
2594 #include "ItaniumNodes.def"
2596 DEMANGLE_ASSERT(0, "unknown mangling node kind");
2599 /// Determine the kind of a node from its type.
2600 template<typename NodeT
> struct NodeKind
;
2602 template <> struct NodeKind<X> { \
2603 static constexpr Node::Kind Kind = Node::K##X; \
2604 static constexpr const char *name() { return #X; } \
2606 #include "ItaniumNodes.def"
2608 template <typename Derived
, typename Alloc
> struct AbstractManglingParser
{
2612 // Name stack, this is used by the parser to hold temporary names that were
2613 // parsed. The parser collapses multiple names into new nodes to construct
2614 // the AST. Once the parser is finished, names.size() == 1.
2615 PODSmallVector
<Node
*, 32> Names
;
2617 // Substitution table. Itanium supports name substitutions as a means of
2618 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2620 PODSmallVector
<Node
*, 32> Subs
;
2622 // A list of template argument values corresponding to a template parameter
2624 using TemplateParamList
= PODSmallVector
<Node
*, 8>;
2626 class ScopedTemplateParamList
{
2627 AbstractManglingParser
*Parser
;
2628 size_t OldNumTemplateParamLists
;
2629 TemplateParamList Params
;
2632 ScopedTemplateParamList(AbstractManglingParser
*TheParser
)
2633 : Parser(TheParser
),
2634 OldNumTemplateParamLists(TheParser
->TemplateParams
.size()) {
2635 Parser
->TemplateParams
.push_back(&Params
);
2637 ~ScopedTemplateParamList() {
2638 DEMANGLE_ASSERT(Parser
->TemplateParams
.size() >= OldNumTemplateParamLists
,
2640 Parser
->TemplateParams
.shrinkToSize(OldNumTemplateParamLists
);
2642 TemplateParamList
*params() { return &Params
; }
2645 // Template parameter table. Like the above, but referenced like "T42_".
2646 // This has a smaller size compared to Subs and Names because it can be
2647 // stored on the stack.
2648 TemplateParamList OuterTemplateParams
;
2650 // Lists of template parameters indexed by template parameter depth,
2651 // referenced like "TL2_4_". If nonempty, element 0 is always
2652 // OuterTemplateParams; inner elements are always template parameter lists of
2653 // lambda expressions. For a generic lambda with no explicit template
2654 // parameter list, the corresponding parameter list pointer will be null.
2655 PODSmallVector
<TemplateParamList
*, 4> TemplateParams
;
2657 class SaveTemplateParams
{
2658 AbstractManglingParser
*Parser
;
2659 decltype(TemplateParams
) OldParams
;
2660 decltype(OuterTemplateParams
) OldOuterParams
;
2663 SaveTemplateParams(AbstractManglingParser
*TheParser
) : Parser(TheParser
) {
2664 OldParams
= std::move(Parser
->TemplateParams
);
2665 OldOuterParams
= std::move(Parser
->OuterTemplateParams
);
2666 Parser
->TemplateParams
.clear();
2667 Parser
->OuterTemplateParams
.clear();
2669 ~SaveTemplateParams() {
2670 Parser
->TemplateParams
= std::move(OldParams
);
2671 Parser
->OuterTemplateParams
= std::move(OldOuterParams
);
2675 // Set of unresolved forward <template-param> references. These can occur in a
2676 // conversion operator's type, and are resolved in the enclosing <encoding>.
2677 PODSmallVector
<ForwardTemplateReference
*, 4> ForwardTemplateRefs
;
2679 bool TryToParseTemplateArgs
= true;
2680 bool PermitForwardTemplateReferences
= false;
2681 bool InConstraintExpr
= false;
2682 size_t ParsingLambdaParamsAtLevel
= (size_t)-1;
2684 unsigned NumSyntheticTemplateParameters
[3] = {};
2688 AbstractManglingParser(const char *First_
, const char *Last_
)
2689 : First(First_
), Last(Last_
) {}
2691 Derived
&getDerived() { return static_cast<Derived
&>(*this); }
2693 void reset(const char *First_
, const char *Last_
) {
2698 TemplateParams
.clear();
2699 ParsingLambdaParamsAtLevel
= (size_t)-1;
2700 TryToParseTemplateArgs
= true;
2701 PermitForwardTemplateReferences
= false;
2702 for (int I
= 0; I
!= 3; ++I
)
2703 NumSyntheticTemplateParameters
[I
] = 0;
2704 ASTAllocator
.reset();
2707 template <class T
, class... Args
> Node
*make(Args
&&... args
) {
2708 return ASTAllocator
.template makeNode
<T
>(std::forward
<Args
>(args
)...);
2711 template <class It
> NodeArray
makeNodeArray(It begin
, It end
) {
2712 size_t sz
= static_cast<size_t>(end
- begin
);
2713 void *mem
= ASTAllocator
.allocateNodeArray(sz
);
2714 Node
**data
= new (mem
) Node
*[sz
];
2715 std::copy(begin
, end
, data
);
2716 return NodeArray(data
, sz
);
2719 NodeArray
popTrailingNodeArray(size_t FromPosition
) {
2720 DEMANGLE_ASSERT(FromPosition
<= Names
.size(), "");
2722 makeNodeArray(Names
.begin() + (long)FromPosition
, Names
.end());
2723 Names
.shrinkToSize(FromPosition
);
2727 bool consumeIf(std::string_view S
) {
2728 if (starts_with(std::string_view(First
, Last
- First
), S
)) {
2735 bool consumeIf(char C
) {
2736 if (First
!= Last
&& *First
== C
) {
2743 char consume() { return First
!= Last
? *First
++ : '\0'; }
2745 char look(unsigned Lookahead
= 0) const {
2746 if (static_cast<size_t>(Last
- First
) <= Lookahead
)
2748 return First
[Lookahead
];
2751 size_t numLeft() const { return static_cast<size_t>(Last
- First
); }
2753 std::string_view
parseNumber(bool AllowNegative
= false);
2754 Qualifiers
parseCVQualifiers();
2755 bool parsePositiveInteger(size_t *Out
);
2756 std::string_view
parseBareSourceName();
2758 bool parseSeqId(size_t *Out
);
2759 Node
*parseSubstitution();
2760 Node
*parseTemplateParam();
2761 Node
*parseTemplateParamDecl(TemplateParamList
*Params
);
2762 Node
*parseTemplateArgs(bool TagTemplates
= false);
2763 Node
*parseTemplateArg();
2765 bool isTemplateParamDecl() {
2766 return look() == 'T' &&
2767 std::string_view("yptnk").find(look(1)) != std::string_view::npos
;
2770 /// Parse the <expression> production.
2772 Node
*parsePrefixExpr(std::string_view Kind
, Node::Prec Prec
);
2773 Node
*parseBinaryExpr(std::string_view Kind
, Node::Prec Prec
);
2774 Node
*parseIntegerLiteral(std::string_view Lit
);
2775 Node
*parseExprPrimary();
2776 template <class Float
> Node
*parseFloatingLiteral();
2777 Node
*parseFunctionParam();
2778 Node
*parseConversionExpr();
2779 Node
*parseBracedExpr();
2780 Node
*parseFoldExpr();
2781 Node
*parsePointerToMemberConversionExpr(Node::Prec Prec
);
2782 Node
*parseSubobjectExpr();
2783 Node
*parseConstraintExpr();
2784 Node
*parseRequiresExpr();
2786 /// Parse the <type> production.
2788 Node
*parseFunctionType();
2789 Node
*parseVectorType();
2790 Node
*parseDecltype();
2791 Node
*parseArrayType();
2792 Node
*parsePointerToMemberType();
2793 Node
*parseClassEnumType();
2794 Node
*parseQualifiedType();
2796 Node
*parseEncoding(bool ParseParams
= true);
2797 bool parseCallOffset();
2798 Node
*parseSpecialName();
2800 /// Holds some extra information about a <name> that is being parsed. This
2801 /// information is only pertinent if the <name> refers to an <encoding>.
2803 bool CtorDtorConversion
= false;
2804 bool EndsWithTemplateArgs
= false;
2805 Qualifiers CVQualifiers
= QualNone
;
2806 FunctionRefQual ReferenceQualifier
= FrefQualNone
;
2807 size_t ForwardTemplateRefsBegin
;
2808 bool HasExplicitObjectParameter
= false;
2810 NameState(AbstractManglingParser
*Enclosing
)
2811 : ForwardTemplateRefsBegin(Enclosing
->ForwardTemplateRefs
.size()) {}
2814 bool resolveForwardTemplateRefs(NameState
&State
) {
2815 size_t I
= State
.ForwardTemplateRefsBegin
;
2816 size_t E
= ForwardTemplateRefs
.size();
2817 for (; I
< E
; ++I
) {
2818 size_t Idx
= ForwardTemplateRefs
[I
]->Index
;
2819 if (TemplateParams
.empty() || !TemplateParams
[0] ||
2820 Idx
>= TemplateParams
[0]->size())
2822 ForwardTemplateRefs
[I
]->Ref
= (*TemplateParams
[0])[Idx
];
2824 ForwardTemplateRefs
.shrinkToSize(State
.ForwardTemplateRefsBegin
);
2828 /// Parse the <name> production>
2829 Node
*parseName(NameState
*State
= nullptr);
2830 Node
*parseLocalName(NameState
*State
);
2831 Node
*parseOperatorName(NameState
*State
);
2832 bool parseModuleNameOpt(ModuleName
*&Module
);
2833 Node
*parseUnqualifiedName(NameState
*State
, Node
*Scope
, ModuleName
*Module
);
2834 Node
*parseUnnamedTypeName(NameState
*State
);
2835 Node
*parseSourceName(NameState
*State
);
2836 Node
*parseUnscopedName(NameState
*State
, bool *isSubstName
);
2837 Node
*parseNestedName(NameState
*State
);
2838 Node
*parseCtorDtorName(Node
*&SoFar
, NameState
*State
);
2840 Node
*parseAbiTags(Node
*N
);
2842 struct OperatorInfo
{
2843 enum OIKind
: unsigned char {
2844 Prefix
, // Prefix unary: @ expr
2845 Postfix
, // Postfix unary: expr @
2846 Binary
, // Binary: lhs @ rhs
2847 Array
, // Array index: lhs [ rhs ]
2848 Member
, // Member access: lhs @ rhs
2851 Call
, // Function call: expr (expr*)
2852 CCast
, // C cast: (type)expr
2853 Conditional
, // Conditional: expr ? expr : expr
2854 NameOnly
, // Overload only, not allowed in expression.
2855 // Below do not have operator names
2856 NamedCast
, // Named cast, @<type>(expr)
2857 OfIdOp
, // alignof, sizeof, typeid
2859 Unnameable
= NamedCast
,
2861 char Enc
[2]; // Encoding
2862 OIKind Kind
; // Kind of operator
2863 bool Flag
: 1; // Entry-specific flag
2864 Node::Prec Prec
: 7; // Precedence
2865 const char *Name
; // Spelling
2868 constexpr OperatorInfo(const char (&E
)[3], OIKind K
, bool F
, Node::Prec P
,
2870 : Enc
{E
[0], E
[1]}, Kind
{K
}, Flag
{F
}, Prec
{P
}, Name
{N
} {}
2873 bool operator<(const OperatorInfo
&Other
) const {
2874 return *this < Other
.Enc
;
2876 bool operator<(const char *Peek
) const {
2877 return Enc
[0] < Peek
[0] || (Enc
[0] == Peek
[0] && Enc
[1] < Peek
[1]);
2879 bool operator==(const char *Peek
) const {
2880 return Enc
[0] == Peek
[0] && Enc
[1] == Peek
[1];
2882 bool operator!=(const char *Peek
) const { return !this->operator==(Peek
); }
2885 std::string_view
getSymbol() const {
2886 std::string_view Res
= Name
;
2887 if (Kind
< Unnameable
) {
2888 DEMANGLE_ASSERT(starts_with(Res
, "operator"),
2889 "operator name does not start with 'operator'");
2890 Res
.remove_prefix(sizeof("operator") - 1);
2891 if (starts_with(Res
, ' '))
2892 Res
.remove_prefix(1);
2896 std::string_view
getName() const { return Name
; }
2897 OIKind
getKind() const { return Kind
; }
2898 bool getFlag() const { return Flag
; }
2899 Node::Prec
getPrecedence() const { return Prec
; }
2901 static const OperatorInfo Ops
[];
2902 static const size_t NumOps
;
2903 const OperatorInfo
*parseOperatorEncoding();
2905 /// Parse the <unresolved-name> production.
2906 Node
*parseUnresolvedName(bool Global
);
2907 Node
*parseSimpleId();
2908 Node
*parseBaseUnresolvedName();
2909 Node
*parseUnresolvedType();
2910 Node
*parseDestructorName();
2912 /// Top-level entry point into the parser.
2913 Node
*parse(bool ParseParams
= true);
2916 const char* parse_discriminator(const char* first
, const char* last
);
2918 // <name> ::= <nested-name> // N
2919 // ::= <local-name> # See Scope Encoding below // Z
2920 // ::= <unscoped-template-name> <template-args>
2921 // ::= <unscoped-name>
2923 // <unscoped-template-name> ::= <unscoped-name>
2924 // ::= <substitution>
2925 template <typename Derived
, typename Alloc
>
2926 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseName(NameState
*State
) {
2928 return getDerived().parseNestedName(State
);
2930 return getDerived().parseLocalName(State
);
2932 Node
*Result
= nullptr;
2933 bool IsSubst
= false;
2935 Result
= getDerived().parseUnscopedName(State
, &IsSubst
);
2939 if (look() == 'I') {
2940 // ::= <unscoped-template-name> <template-args>
2942 // An unscoped-template-name is substitutable.
2943 Subs
.push_back(Result
);
2944 Node
*TA
= getDerived().parseTemplateArgs(State
!= nullptr);
2948 State
->EndsWithTemplateArgs
= true;
2949 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
2950 } else if (IsSubst
) {
2951 // The substitution case must be followed by <template-args>.
2958 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2959 // := Z <function encoding> E s [<discriminator>]
2960 // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
2961 template <typename Derived
, typename Alloc
>
2962 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseLocalName(NameState
*State
) {
2963 if (!consumeIf('Z'))
2965 Node
*Encoding
= getDerived().parseEncoding();
2966 if (Encoding
== nullptr || !consumeIf('E'))
2969 if (consumeIf('s')) {
2970 First
= parse_discriminator(First
, Last
);
2971 auto *StringLitName
= make
<NameType
>("string literal");
2974 return make
<LocalName
>(Encoding
, StringLitName
);
2977 // The template parameters of the inner name are unrelated to those of the
2978 // enclosing context.
2979 SaveTemplateParams
SaveTemplateParamsScope(this);
2981 if (consumeIf('d')) {
2983 if (!consumeIf('_'))
2985 Node
*N
= getDerived().parseName(State
);
2988 return make
<LocalName
>(Encoding
, N
);
2991 Node
*Entity
= getDerived().parseName(State
);
2992 if (Entity
== nullptr)
2994 First
= parse_discriminator(First
, Last
);
2995 return make
<LocalName
>(Encoding
, Entity
);
2998 // <unscoped-name> ::= <unqualified-name>
2999 // ::= St <unqualified-name> # ::std::
3001 template <typename Derived
, typename Alloc
>
3003 AbstractManglingParser
<Derived
, Alloc
>::parseUnscopedName(NameState
*State
,
3006 Node
*Std
= nullptr;
3007 if (consumeIf("St")) {
3008 Std
= make
<NameType
>("std");
3013 Node
*Res
= nullptr;
3014 ModuleName
*Module
= nullptr;
3015 if (look() == 'S') {
3016 Node
*S
= getDerived().parseSubstitution();
3019 if (S
->getKind() == Node::KModuleName
)
3020 Module
= static_cast<ModuleName
*>(S
);
3021 else if (IsSubst
&& Std
== nullptr) {
3029 if (Res
== nullptr || Std
!= nullptr) {
3030 Res
= getDerived().parseUnqualifiedName(State
, Std
, Module
);
3036 // <unqualified-name> ::= [<module-name>] F? L? <operator-name> [<abi-tags>]
3037 // ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
3038 // ::= [<module-name>] F? L? <source-name> [<abi-tags>]
3039 // ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
3040 // # structured binding declaration
3041 // ::= [<module-name>] L? DC <source-name>+ E
3042 template <typename Derived
, typename Alloc
>
3043 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnqualifiedName(
3044 NameState
*State
, Node
*Scope
, ModuleName
*Module
) {
3045 if (getDerived().parseModuleNameOpt(Module
))
3048 bool IsMemberLikeFriend
= Scope
&& consumeIf('F');
3053 if (look() >= '1' && look() <= '9') {
3054 Result
= getDerived().parseSourceName(State
);
3055 } else if (look() == 'U') {
3056 Result
= getDerived().parseUnnamedTypeName(State
);
3057 } else if (consumeIf("DC")) {
3058 // Structured binding
3059 size_t BindingsBegin
= Names
.size();
3061 Node
*Binding
= getDerived().parseSourceName(State
);
3062 if (Binding
== nullptr)
3064 Names
.push_back(Binding
);
3065 } while (!consumeIf('E'));
3066 Result
= make
<StructuredBindingName
>(popTrailingNodeArray(BindingsBegin
));
3067 } else if (look() == 'C' || look() == 'D') {
3068 // A <ctor-dtor-name>.
3069 if (Scope
== nullptr || Module
!= nullptr)
3071 Result
= getDerived().parseCtorDtorName(Scope
, State
);
3073 Result
= getDerived().parseOperatorName(State
);
3076 if (Result
!= nullptr && Module
!= nullptr)
3077 Result
= make
<ModuleEntity
>(Module
, Result
);
3078 if (Result
!= nullptr)
3079 Result
= getDerived().parseAbiTags(Result
);
3080 if (Result
!= nullptr && IsMemberLikeFriend
)
3081 Result
= make
<MemberLikeFriendName
>(Scope
, Result
);
3082 else if (Result
!= nullptr && Scope
!= nullptr)
3083 Result
= make
<NestedName
>(Scope
, Result
);
3088 // <module-name> ::= <module-subname>
3089 // ::= <module-name> <module-subname>
3090 // ::= <substitution> # passed in by caller
3091 // <module-subname> ::= W <source-name>
3092 // ::= W P <source-name>
3093 template <typename Derived
, typename Alloc
>
3094 bool AbstractManglingParser
<Derived
, Alloc
>::parseModuleNameOpt(
3095 ModuleName
*&Module
) {
3096 while (consumeIf('W')) {
3097 bool IsPartition
= consumeIf('P');
3098 Node
*Sub
= getDerived().parseSourceName(nullptr);
3102 static_cast<ModuleName
*>(make
<ModuleName
>(Module
, Sub
, IsPartition
));
3103 Subs
.push_back(Module
);
3109 // <unnamed-type-name> ::= Ut [<nonnegative number>] _
3110 // ::= <closure-type-name>
3112 // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
3114 // <lambda-sig> ::= <template-param-decl>* [Q <requires-clause expression>]
3115 // <parameter type>+ # or "v" if the lambda has no parameters
3116 template <typename Derived
, typename Alloc
>
3118 AbstractManglingParser
<Derived
, Alloc
>::parseUnnamedTypeName(NameState
*State
) {
3119 // <template-params> refer to the innermost <template-args>. Clear out any
3120 // outer args that we may have inserted into TemplateParams.
3121 if (State
!= nullptr)
3122 TemplateParams
.clear();
3124 if (consumeIf("Ut")) {
3125 std::string_view Count
= parseNumber();
3126 if (!consumeIf('_'))
3128 return make
<UnnamedTypeName
>(Count
);
3130 if (consumeIf("Ul")) {
3131 ScopedOverride
<size_t> SwapParams(ParsingLambdaParamsAtLevel
,
3132 TemplateParams
.size());
3133 ScopedTemplateParamList
LambdaTemplateParams(this);
3135 size_t ParamsBegin
= Names
.size();
3136 while (getDerived().isTemplateParamDecl()) {
3138 getDerived().parseTemplateParamDecl(LambdaTemplateParams
.params());
3143 NodeArray TempParams
= popTrailingNodeArray(ParamsBegin
);
3145 // FIXME: If TempParams is empty and none of the function parameters
3146 // includes 'auto', we should remove LambdaTemplateParams from the
3147 // TemplateParams list. Unfortunately, we don't find out whether there are
3148 // any 'auto' parameters until too late in an example such as:
3150 // template<typename T> void f(
3151 // decltype([](decltype([]<typename T>(T v) {}),
3153 // template<typename T> void f(
3154 // decltype([](decltype([]<typename T>(T w) {}),
3157 // Here, the type of v is at level 2 but the type of w is at level 1. We
3158 // don't find this out until we encounter the type of the next parameter.
3160 // However, compilers can't actually cope with the former example in
3161 // practice, and it's likely to be made ill-formed in future, so we don't
3162 // need to support it here.
3164 // If we encounter an 'auto' in the function parameter types, we will
3165 // recreate a template parameter scope for it, but any intervening lambdas
3166 // will be parsed in the 'wrong' template parameter depth.
3167 if (TempParams
.empty())
3168 TemplateParams
.pop_back();
3170 Node
*Requires1
= nullptr;
3171 if (consumeIf('Q')) {
3172 Requires1
= getDerived().parseConstraintExpr();
3173 if (Requires1
== nullptr)
3177 if (!consumeIf("v")) {
3179 Node
*P
= getDerived().parseType();
3183 } while (look() != 'E' && look() != 'Q');
3185 NodeArray Params
= popTrailingNodeArray(ParamsBegin
);
3187 Node
*Requires2
= nullptr;
3188 if (consumeIf('Q')) {
3189 Requires2
= getDerived().parseConstraintExpr();
3190 if (Requires2
== nullptr)
3194 if (!consumeIf('E'))
3197 std::string_view Count
= parseNumber();
3198 if (!consumeIf('_'))
3200 return make
<ClosureTypeName
>(TempParams
, Requires1
, Params
, Requires2
,
3203 if (consumeIf("Ub")) {
3204 (void)parseNumber();
3205 if (!consumeIf('_'))
3207 return make
<NameType
>("'block-literal'");
3212 // <source-name> ::= <positive length number> <identifier>
3213 template <typename Derived
, typename Alloc
>
3214 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSourceName(NameState
*) {
3216 if (parsePositiveInteger(&Length
))
3218 if (numLeft() < Length
|| Length
== 0)
3220 std::string_view
Name(First
, Length
);
3222 if (starts_with(Name
, "_GLOBAL__N"))
3223 return make
<NameType
>("(anonymous namespace)");
3224 return make
<NameType
>(Name
);
3227 // Operator encodings
3228 template <typename Derived
, typename Alloc
>
3229 const typename AbstractManglingParser
<
3230 Derived
, Alloc
>::OperatorInfo AbstractManglingParser
<Derived
,
3232 // Keep ordered by encoding
3233 {"aN", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator&="},
3234 {"aS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator="},
3235 {"aa", OperatorInfo::Binary
, false, Node::Prec::AndIf
, "operator&&"},
3236 {"ad", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator&"},
3237 {"an", OperatorInfo::Binary
, false, Node::Prec::And
, "operator&"},
3238 {"at", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Unary
, "alignof "},
3239 {"aw", OperatorInfo::NameOnly
, false, Node::Prec::Primary
,
3240 "operator co_await"},
3241 {"az", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Unary
, "alignof "},
3242 {"cc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "const_cast"},
3243 {"cl", OperatorInfo::Call
, false, Node::Prec::Postfix
, "operator()"},
3244 {"cm", OperatorInfo::Binary
, false, Node::Prec::Comma
, "operator,"},
3245 {"co", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator~"},
3246 {"cv", OperatorInfo::CCast
, false, Node::Prec::Cast
, "operator"}, // C Cast
3247 {"dV", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator/="},
3248 {"da", OperatorInfo::Del
, /*Ary*/ true, Node::Prec::Unary
,
3249 "operator delete[]"},
3250 {"dc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "dynamic_cast"},
3251 {"de", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator*"},
3252 {"dl", OperatorInfo::Del
, /*Ary*/ false, Node::Prec::Unary
,
3254 {"ds", OperatorInfo::Member
, /*Named*/ false, Node::Prec::PtrMem
,
3256 {"dt", OperatorInfo::Member
, /*Named*/ false, Node::Prec::Postfix
,
3258 {"dv", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator/"},
3259 {"eO", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator^="},
3260 {"eo", OperatorInfo::Binary
, false, Node::Prec::Xor
, "operator^"},
3261 {"eq", OperatorInfo::Binary
, false, Node::Prec::Equality
, "operator=="},
3262 {"ge", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator>="},
3263 {"gt", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator>"},
3264 {"ix", OperatorInfo::Array
, false, Node::Prec::Postfix
, "operator[]"},
3265 {"lS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator<<="},
3266 {"le", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator<="},
3267 {"ls", OperatorInfo::Binary
, false, Node::Prec::Shift
, "operator<<"},
3268 {"lt", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator<"},
3269 {"mI", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator-="},
3270 {"mL", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator*="},
3271 {"mi", OperatorInfo::Binary
, false, Node::Prec::Additive
, "operator-"},
3272 {"ml", OperatorInfo::Binary
, false, Node::Prec::Multiplicative
,
3274 {"mm", OperatorInfo::Postfix
, false, Node::Prec::Postfix
, "operator--"},
3275 {"na", OperatorInfo::New
, /*Ary*/ true, Node::Prec::Unary
,
3277 {"ne", OperatorInfo::Binary
, false, Node::Prec::Equality
, "operator!="},
3278 {"ng", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator-"},
3279 {"nt", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator!"},
3280 {"nw", OperatorInfo::New
, /*Ary*/ false, Node::Prec::Unary
, "operator new"},
3281 {"oR", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator|="},
3282 {"oo", OperatorInfo::Binary
, false, Node::Prec::OrIf
, "operator||"},
3283 {"or", OperatorInfo::Binary
, false, Node::Prec::Ior
, "operator|"},
3284 {"pL", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator+="},
3285 {"pl", OperatorInfo::Binary
, false, Node::Prec::Additive
, "operator+"},
3286 {"pm", OperatorInfo::Member
, /*Named*/ false, Node::Prec::PtrMem
,
3288 {"pp", OperatorInfo::Postfix
, false, Node::Prec::Postfix
, "operator++"},
3289 {"ps", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator+"},
3290 {"pt", OperatorInfo::Member
, /*Named*/ true, Node::Prec::Postfix
,
3292 {"qu", OperatorInfo::Conditional
, false, Node::Prec::Conditional
,
3294 {"rM", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator%="},
3295 {"rS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator>>="},
3296 {"rc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
,
3297 "reinterpret_cast"},
3298 {"rm", OperatorInfo::Binary
, false, Node::Prec::Multiplicative
,
3300 {"rs", OperatorInfo::Binary
, false, Node::Prec::Shift
, "operator>>"},
3301 {"sc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "static_cast"},
3302 {"ss", OperatorInfo::Binary
, false, Node::Prec::Spaceship
, "operator<=>"},
3303 {"st", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Unary
, "sizeof "},
3304 {"sz", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Unary
, "sizeof "},
3305 {"te", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Postfix
,
3307 {"ti", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Postfix
, "typeid "},
3309 template <typename Derived
, typename Alloc
>
3310 const size_t AbstractManglingParser
<Derived
, Alloc
>::NumOps
= sizeof(Ops
) /
3313 // If the next 2 chars are an operator encoding, consume them and return their
3314 // OperatorInfo. Otherwise return nullptr.
3315 template <typename Derived
, typename Alloc
>
3316 const typename AbstractManglingParser
<Derived
, Alloc
>::OperatorInfo
*
3317 AbstractManglingParser
<Derived
, Alloc
>::parseOperatorEncoding() {
3321 // We can't use lower_bound as that can link to symbols in the C++ library,
3322 // and this must remain independant of that.
3323 size_t lower
= 0u, upper
= NumOps
- 1; // Inclusive bounds.
3324 while (upper
!= lower
) {
3325 size_t middle
= (upper
+ lower
) / 2;
3326 if (Ops
[middle
] < First
)
3331 if (Ops
[lower
] != First
)
3338 // <operator-name> ::= See parseOperatorEncoding()
3339 // ::= li <source-name> # operator ""
3340 // ::= v <digit> <source-name> # vendor extended operator
3341 template <typename Derived
, typename Alloc
>
3343 AbstractManglingParser
<Derived
, Alloc
>::parseOperatorName(NameState
*State
) {
3344 if (const auto *Op
= parseOperatorEncoding()) {
3345 if (Op
->getKind() == OperatorInfo::CCast
) {
3346 // ::= cv <type> # (cast)
3347 ScopedOverride
<bool> SaveTemplate(TryToParseTemplateArgs
, false);
3348 // If we're parsing an encoding, State != nullptr and the conversion
3349 // operators' <type> could have a <template-param> that refers to some
3350 // <template-arg>s further ahead in the mangled name.
3351 ScopedOverride
<bool> SavePermit(PermitForwardTemplateReferences
,
3352 PermitForwardTemplateReferences
||
3354 Node
*Ty
= getDerived().parseType();
3357 if (State
) State
->CtorDtorConversion
= true;
3358 return make
<ConversionOperatorType
>(Ty
);
3361 if (Op
->getKind() >= OperatorInfo::Unnameable
)
3362 /* Not a nameable operator. */
3364 if (Op
->getKind() == OperatorInfo::Member
&& !Op
->getFlag())
3365 /* Not a nameable MemberExpr */
3368 return make
<NameType
>(Op
->getName());
3371 if (consumeIf("li")) {
3372 // ::= li <source-name> # operator ""
3373 Node
*SN
= getDerived().parseSourceName(State
);
3376 return make
<LiteralOperator
>(SN
);
3379 if (consumeIf('v')) {
3380 // ::= v <digit> <source-name> # vendor extended operator
3381 if (look() >= '0' && look() <= '9') {
3383 Node
*SN
= getDerived().parseSourceName(State
);
3386 return make
<ConversionOperatorType
>(SN
);
3394 // <ctor-dtor-name> ::= C1 # complete object constructor
3395 // ::= C2 # base object constructor
3396 // ::= C3 # complete object allocating constructor
3397 // extension ::= C4 # gcc old-style "[unified]" constructor
3398 // extension ::= C5 # the COMDAT used for ctors
3399 // ::= D0 # deleting destructor
3400 // ::= D1 # complete object destructor
3401 // ::= D2 # base object destructor
3402 // extension ::= D4 # gcc old-style "[unified]" destructor
3403 // extension ::= D5 # the COMDAT used for dtors
3404 template <typename Derived
, typename Alloc
>
3406 AbstractManglingParser
<Derived
, Alloc
>::parseCtorDtorName(Node
*&SoFar
,
3408 if (SoFar
->getKind() == Node::KSpecialSubstitution
) {
3409 // Expand the special substitution.
3410 SoFar
= make
<ExpandedSpecialSubstitution
>(
3411 static_cast<SpecialSubstitution
*>(SoFar
));
3416 if (consumeIf('C')) {
3417 bool IsInherited
= consumeIf('I');
3418 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3421 int Variant
= look() - '0';
3423 if (State
) State
->CtorDtorConversion
= true;
3425 if (getDerived().parseName(State
) == nullptr)
3428 return make
<CtorDtorName
>(SoFar
, /*IsDtor=*/false, Variant
);
3431 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3432 look(1) == '4' || look(1) == '5')) {
3433 int Variant
= look(1) - '0';
3435 if (State
) State
->CtorDtorConversion
= true;
3436 return make
<CtorDtorName
>(SoFar
, /*IsDtor=*/true, Variant
);
3442 // <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3443 // <unqualified-name> E
3444 // ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3445 // <template-args> E
3447 // <prefix> ::= <prefix> <unqualified-name>
3448 // ::= <template-prefix> <template-args>
3449 // ::= <template-param>
3452 // ::= <substitution>
3453 // ::= <prefix> <data-member-prefix>
3456 // <data-member-prefix> := <member source-name> [<template-args>] M
3458 // <template-prefix> ::= <prefix> <template unqualified-name>
3459 // ::= <template-param>
3460 // ::= <substitution>
3461 template <typename Derived
, typename Alloc
>
3463 AbstractManglingParser
<Derived
, Alloc
>::parseNestedName(NameState
*State
) {
3464 if (!consumeIf('N'))
3467 // 'H' specifies that the encoding that follows
3468 // has an explicit object parameter.
3469 if (!consumeIf('H')) {
3470 Qualifiers CVTmp
= parseCVQualifiers();
3472 State
->CVQualifiers
= CVTmp
;
3474 if (consumeIf('O')) {
3476 State
->ReferenceQualifier
= FrefQualRValue
;
3477 } else if (consumeIf('R')) {
3479 State
->ReferenceQualifier
= FrefQualLValue
;
3482 State
->ReferenceQualifier
= FrefQualNone
;
3485 State
->HasExplicitObjectParameter
= true;
3488 Node
*SoFar
= nullptr;
3489 while (!consumeIf('E')) {
3491 // Only set end-with-template on the case that does that.
3492 State
->EndsWithTemplateArgs
= false;
3494 if (look() == 'T') {
3495 // ::= <template-param>
3496 if (SoFar
!= nullptr)
3497 return nullptr; // Cannot have a prefix.
3498 SoFar
= getDerived().parseTemplateParam();
3499 } else if (look() == 'I') {
3500 // ::= <template-prefix> <template-args>
3501 if (SoFar
== nullptr)
3502 return nullptr; // Must have a prefix.
3503 Node
*TA
= getDerived().parseTemplateArgs(State
!= nullptr);
3506 if (SoFar
->getKind() == Node::KNameWithTemplateArgs
)
3507 // Semantically <template-args> <template-args> cannot be generated by a
3508 // C++ entity. There will always be [something like] a name between
3512 State
->EndsWithTemplateArgs
= true;
3513 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3514 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3516 if (SoFar
!= nullptr)
3517 return nullptr; // Cannot have a prefix.
3518 SoFar
= getDerived().parseDecltype();
3520 ModuleName
*Module
= nullptr;
3522 if (look() == 'S') {
3523 // ::= <substitution>
3525 if (look(1) == 't') {
3527 S
= make
<NameType
>("std");
3529 S
= getDerived().parseSubstitution();
3533 if (S
->getKind() == Node::KModuleName
) {
3534 Module
= static_cast<ModuleName
*>(S
);
3535 } else if (SoFar
!= nullptr) {
3536 return nullptr; // Cannot have a prefix.
3539 continue; // Do not push a new substitution.
3543 // ::= [<prefix>] <unqualified-name>
3544 SoFar
= getDerived().parseUnqualifiedName(State
, SoFar
, Module
);
3547 if (SoFar
== nullptr)
3549 Subs
.push_back(SoFar
);
3552 // <data-member-prefix> := <member source-name> [<template-args>] M
3556 if (SoFar
== nullptr || Subs
.empty())
3563 // <simple-id> ::= <source-name> [ <template-args> ]
3564 template <typename Derived
, typename Alloc
>
3565 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSimpleId() {
3566 Node
*SN
= getDerived().parseSourceName(/*NameState=*/nullptr);
3569 if (look() == 'I') {
3570 Node
*TA
= getDerived().parseTemplateArgs();
3573 return make
<NameWithTemplateArgs
>(SN
, TA
);
3578 // <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3579 // ::= <simple-id> # e.g., ~A<2*N>
3580 template <typename Derived
, typename Alloc
>
3581 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseDestructorName() {
3583 if (std::isdigit(look()))
3584 Result
= getDerived().parseSimpleId();
3586 Result
= getDerived().parseUnresolvedType();
3587 if (Result
== nullptr)
3589 return make
<DtorName
>(Result
);
3592 // <unresolved-type> ::= <template-param>
3594 // ::= <substitution>
3595 template <typename Derived
, typename Alloc
>
3596 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnresolvedType() {
3597 if (look() == 'T') {
3598 Node
*TP
= getDerived().parseTemplateParam();
3604 if (look() == 'D') {
3605 Node
*DT
= getDerived().parseDecltype();
3611 return getDerived().parseSubstitution();
3614 // <base-unresolved-name> ::= <simple-id> # unresolved name
3615 // extension ::= <operator-name> # unresolved operator-function-id
3616 // extension ::= <operator-name> <template-args> # unresolved operator template-id
3617 // ::= on <operator-name> # unresolved operator-function-id
3618 // ::= on <operator-name> <template-args> # unresolved operator template-id
3619 // ::= dn <destructor-name> # destructor or pseudo-destructor;
3620 // # e.g. ~X or ~X<N-1>
3621 template <typename Derived
, typename Alloc
>
3622 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseBaseUnresolvedName() {
3623 if (std::isdigit(look()))
3624 return getDerived().parseSimpleId();
3626 if (consumeIf("dn"))
3627 return getDerived().parseDestructorName();
3631 Node
*Oper
= getDerived().parseOperatorName(/*NameState=*/nullptr);
3632 if (Oper
== nullptr)
3634 if (look() == 'I') {
3635 Node
*TA
= getDerived().parseTemplateArgs();
3638 return make
<NameWithTemplateArgs
>(Oper
, TA
);
3643 // <unresolved-name>
3644 // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3645 // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3646 // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3647 // # A::x, N::y, A<T>::z; "gs" means leading "::"
3648 // [gs] has been parsed by caller.
3649 // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3650 // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3651 // # T::N::x /decltype(p)::N::x
3652 // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3654 // <unresolved-qualifier-level> ::= <simple-id>
3655 template <typename Derived
, typename Alloc
>
3656 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnresolvedName(bool Global
) {
3657 Node
*SoFar
= nullptr;
3659 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3660 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3661 if (consumeIf("srN")) {
3662 SoFar
= getDerived().parseUnresolvedType();
3663 if (SoFar
== nullptr)
3666 if (look() == 'I') {
3667 Node
*TA
= getDerived().parseTemplateArgs();
3670 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3675 while (!consumeIf('E')) {
3676 Node
*Qual
= getDerived().parseSimpleId();
3677 if (Qual
== nullptr)
3679 SoFar
= make
<QualifiedName
>(SoFar
, Qual
);
3684 Node
*Base
= getDerived().parseBaseUnresolvedName();
3685 if (Base
== nullptr)
3687 return make
<QualifiedName
>(SoFar
, Base
);
3690 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3691 if (!consumeIf("sr")) {
3692 SoFar
= getDerived().parseBaseUnresolvedName();
3693 if (SoFar
== nullptr)
3696 SoFar
= make
<GlobalQualifiedName
>(SoFar
);
3700 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3701 if (std::isdigit(look())) {
3703 Node
*Qual
= getDerived().parseSimpleId();
3704 if (Qual
== nullptr)
3707 SoFar
= make
<QualifiedName
>(SoFar
, Qual
);
3709 SoFar
= make
<GlobalQualifiedName
>(Qual
);
3714 } while (!consumeIf('E'));
3716 // sr <unresolved-type> <base-unresolved-name>
3717 // sr <unresolved-type> <template-args> <base-unresolved-name>
3719 SoFar
= getDerived().parseUnresolvedType();
3720 if (SoFar
== nullptr)
3723 if (look() == 'I') {
3724 Node
*TA
= getDerived().parseTemplateArgs();
3727 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3733 DEMANGLE_ASSERT(SoFar
!= nullptr, "");
3735 Node
*Base
= getDerived().parseBaseUnresolvedName();
3736 if (Base
== nullptr)
3738 return make
<QualifiedName
>(SoFar
, Base
);
3741 // <abi-tags> ::= <abi-tag> [<abi-tags>]
3742 // <abi-tag> ::= B <source-name>
3743 template <typename Derived
, typename Alloc
>
3744 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseAbiTags(Node
*N
) {
3745 while (consumeIf('B')) {
3746 std::string_view SN
= parseBareSourceName();
3749 N
= make
<AbiTagAttr
>(N
, SN
);
3756 // <number> ::= [n] <non-negative decimal integer>
3757 template <typename Alloc
, typename Derived
>
3759 AbstractManglingParser
<Alloc
, Derived
>::parseNumber(bool AllowNegative
) {
3760 const char *Tmp
= First
;
3763 if (numLeft() == 0 || !std::isdigit(*First
))
3764 return std::string_view();
3765 while (numLeft() != 0 && std::isdigit(*First
))
3767 return std::string_view(Tmp
, First
- Tmp
);
3770 // <positive length number> ::= [0-9]*
3771 template <typename Alloc
, typename Derived
>
3772 bool AbstractManglingParser
<Alloc
, Derived
>::parsePositiveInteger(size_t *Out
) {
3774 if (look() < '0' || look() > '9')
3776 while (look() >= '0' && look() <= '9') {
3778 *Out
+= static_cast<size_t>(consume() - '0');
3783 template <typename Alloc
, typename Derived
>
3784 std::string_view AbstractManglingParser
<Alloc
, Derived
>::parseBareSourceName() {
3786 if (parsePositiveInteger(&Int
) || numLeft() < Int
)
3788 std::string_view
R(First
, Int
);
3793 // <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3795 // <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3796 // ::= DO <expression> E # computed (instantiation-dependent) noexcept
3797 // ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3799 // <ref-qualifier> ::= R # & ref-qualifier
3800 // <ref-qualifier> ::= O # && ref-qualifier
3801 template <typename Derived
, typename Alloc
>
3802 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFunctionType() {
3803 Qualifiers CVQuals
= parseCVQualifiers();
3805 Node
*ExceptionSpec
= nullptr;
3806 if (consumeIf("Do")) {
3807 ExceptionSpec
= make
<NameType
>("noexcept");
3810 } else if (consumeIf("DO")) {
3811 Node
*E
= getDerived().parseExpr();
3812 if (E
== nullptr || !consumeIf('E'))
3814 ExceptionSpec
= make
<NoexceptSpec
>(E
);
3817 } else if (consumeIf("Dw")) {
3818 size_t SpecsBegin
= Names
.size();
3819 while (!consumeIf('E')) {
3820 Node
*T
= getDerived().parseType();
3826 make
<DynamicExceptionSpec
>(popTrailingNodeArray(SpecsBegin
));
3831 consumeIf("Dx"); // transaction safe
3833 if (!consumeIf('F'))
3835 consumeIf('Y'); // extern "C"
3836 Node
*ReturnType
= getDerived().parseType();
3837 if (ReturnType
== nullptr)
3840 FunctionRefQual ReferenceQualifier
= FrefQualNone
;
3841 size_t ParamsBegin
= Names
.size();
3847 if (consumeIf("RE")) {
3848 ReferenceQualifier
= FrefQualLValue
;
3851 if (consumeIf("OE")) {
3852 ReferenceQualifier
= FrefQualRValue
;
3855 Node
*T
= getDerived().parseType();
3861 NodeArray Params
= popTrailingNodeArray(ParamsBegin
);
3862 return make
<FunctionType
>(ReturnType
, Params
, CVQuals
,
3863 ReferenceQualifier
, ExceptionSpec
);
3867 // <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3868 // ::= Dv [<dimension expression>] _ <element type>
3869 // <extended element type> ::= <element type>
3870 // ::= p # AltiVec vector pixel
3871 template <typename Derived
, typename Alloc
>
3872 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseVectorType() {
3873 if (!consumeIf("Dv"))
3875 if (look() >= '1' && look() <= '9') {
3876 Node
*DimensionNumber
= make
<NameType
>(parseNumber());
3877 if (!DimensionNumber
)
3879 if (!consumeIf('_'))
3882 return make
<PixelVectorType
>(DimensionNumber
);
3883 Node
*ElemType
= getDerived().parseType();
3884 if (ElemType
== nullptr)
3886 return make
<VectorType
>(ElemType
, DimensionNumber
);
3889 if (!consumeIf('_')) {
3890 Node
*DimExpr
= getDerived().parseExpr();
3893 if (!consumeIf('_'))
3895 Node
*ElemType
= getDerived().parseType();
3898 return make
<VectorType
>(ElemType
, DimExpr
);
3900 Node
*ElemType
= getDerived().parseType();
3903 return make
<VectorType
>(ElemType
, /*Dimension=*/nullptr);
3906 // <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3907 // ::= DT <expression> E # decltype of an expression (C++0x)
3908 template <typename Derived
, typename Alloc
>
3909 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseDecltype() {
3910 if (!consumeIf('D'))
3912 if (!consumeIf('t') && !consumeIf('T'))
3914 Node
*E
= getDerived().parseExpr();
3917 if (!consumeIf('E'))
3919 return make
<EnclosingExpr
>("decltype", E
);
3922 // <array-type> ::= A <positive dimension number> _ <element type>
3923 // ::= A [<dimension expression>] _ <element type>
3924 template <typename Derived
, typename Alloc
>
3925 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseArrayType() {
3926 if (!consumeIf('A'))
3929 Node
*Dimension
= nullptr;
3931 if (std::isdigit(look())) {
3932 Dimension
= make
<NameType
>(parseNumber());
3935 if (!consumeIf('_'))
3937 } else if (!consumeIf('_')) {
3938 Node
*DimExpr
= getDerived().parseExpr();
3939 if (DimExpr
== nullptr)
3941 if (!consumeIf('_'))
3943 Dimension
= DimExpr
;
3946 Node
*Ty
= getDerived().parseType();
3949 return make
<ArrayType
>(Ty
, Dimension
);
3952 // <pointer-to-member-type> ::= M <class type> <member type>
3953 template <typename Derived
, typename Alloc
>
3954 Node
*AbstractManglingParser
<Derived
, Alloc
>::parsePointerToMemberType() {
3955 if (!consumeIf('M'))
3957 Node
*ClassType
= getDerived().parseType();
3958 if (ClassType
== nullptr)
3960 Node
*MemberType
= getDerived().parseType();
3961 if (MemberType
== nullptr)
3963 return make
<PointerToMemberType
>(ClassType
, MemberType
);
3966 // <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3967 // ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3968 // ::= Tu <name> # dependent elaborated type specifier using 'union'
3969 // ::= Te <name> # dependent elaborated type specifier using 'enum'
3970 template <typename Derived
, typename Alloc
>
3971 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseClassEnumType() {
3972 std::string_view ElabSpef
;
3973 if (consumeIf("Ts"))
3974 ElabSpef
= "struct";
3975 else if (consumeIf("Tu"))
3977 else if (consumeIf("Te"))
3980 Node
*Name
= getDerived().parseName();
3981 if (Name
== nullptr)
3984 if (!ElabSpef
.empty())
3985 return make
<ElaboratedTypeSpefType
>(ElabSpef
, Name
);
3990 // <qualified-type> ::= <qualifiers> <type>
3991 // <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3992 // <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
3993 template <typename Derived
, typename Alloc
>
3994 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseQualifiedType() {
3995 if (consumeIf('U')) {
3996 std::string_view Qual
= parseBareSourceName();
4000 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
4001 if (starts_with(Qual
, "objcproto")) {
4002 constexpr size_t Len
= sizeof("objcproto") - 1;
4003 std::string_view
ProtoSourceName(Qual
.data() + Len
, Qual
.size() - Len
);
4004 std::string_view Proto
;
4006 ScopedOverride
<const char *> SaveFirst(First
, ProtoSourceName
.data()),
4007 SaveLast(Last
, &*ProtoSourceName
.rbegin() + 1);
4008 Proto
= parseBareSourceName();
4012 Node
*Child
= getDerived().parseQualifiedType();
4013 if (Child
== nullptr)
4015 return make
<ObjCProtoName
>(Child
, Proto
);
4019 if (look() == 'I') {
4020 TA
= getDerived().parseTemplateArgs();
4025 Node
*Child
= getDerived().parseQualifiedType();
4026 if (Child
== nullptr)
4028 return make
<VendorExtQualType
>(Child
, Qual
, TA
);
4031 Qualifiers Quals
= parseCVQualifiers();
4032 Node
*Ty
= getDerived().parseType();
4035 if (Quals
!= QualNone
)
4036 Ty
= make
<QualType
>(Ty
, Quals
);
4040 // <type> ::= <builtin-type>
4041 // ::= <qualified-type>
4042 // ::= <function-type>
4043 // ::= <class-enum-type>
4045 // ::= <pointer-to-member-type>
4046 // ::= <template-param>
4047 // ::= <template-template-param> <template-args>
4049 // ::= P <type> # pointer
4050 // ::= R <type> # l-value reference
4051 // ::= O <type> # r-value reference (C++11)
4052 // ::= C <type> # complex pair (C99)
4053 // ::= G <type> # imaginary (C99)
4054 // ::= <substitution> # See Compression below
4055 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
4056 // extension ::= <vector-type> # <vector-type> starts with Dv
4058 // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
4059 // <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
4060 template <typename Derived
, typename Alloc
>
4061 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseType() {
4062 Node
*Result
= nullptr;
4065 // ::= <qualified-type>
4069 unsigned AfterQuals
= 0;
4070 if (look(AfterQuals
) == 'r') ++AfterQuals
;
4071 if (look(AfterQuals
) == 'V') ++AfterQuals
;
4072 if (look(AfterQuals
) == 'K') ++AfterQuals
;
4074 if (look(AfterQuals
) == 'F' ||
4075 (look(AfterQuals
) == 'D' &&
4076 (look(AfterQuals
+ 1) == 'o' || look(AfterQuals
+ 1) == 'O' ||
4077 look(AfterQuals
+ 1) == 'w' || look(AfterQuals
+ 1) == 'x'))) {
4078 Result
= getDerived().parseFunctionType();
4081 DEMANGLE_FALLTHROUGH
;
4084 Result
= getDerived().parseQualifiedType();
4087 // <builtin-type> ::= v # void
4090 return make
<NameType
>("void");
4094 return make
<NameType
>("wchar_t");
4098 return make
<NameType
>("bool");
4102 return make
<NameType
>("char");
4103 // ::= a # signed char
4106 return make
<NameType
>("signed char");
4107 // ::= h # unsigned char
4110 return make
<NameType
>("unsigned char");
4114 return make
<NameType
>("short");
4115 // ::= t # unsigned short
4118 return make
<NameType
>("unsigned short");
4122 return make
<NameType
>("int");
4123 // ::= j # unsigned int
4126 return make
<NameType
>("unsigned int");
4130 return make
<NameType
>("long");
4131 // ::= m # unsigned long
4134 return make
<NameType
>("unsigned long");
4135 // ::= x # long long, __int64
4138 return make
<NameType
>("long long");
4139 // ::= y # unsigned long long, __int64
4142 return make
<NameType
>("unsigned long long");
4146 return make
<NameType
>("__int128");
4147 // ::= o # unsigned __int128
4150 return make
<NameType
>("unsigned __int128");
4154 return make
<NameType
>("float");
4158 return make
<NameType
>("double");
4159 // ::= e # long double, __float80
4162 return make
<NameType
>("long double");
4163 // ::= g # __float128
4166 return make
<NameType
>("__float128");
4170 return make
<NameType
>("...");
4172 // <builtin-type> ::= u <source-name> # vendor extended type
4175 std::string_view Res
= parseBareSourceName();
4178 // Typically, <builtin-type>s are not considered substitution candidates,
4179 // but the exception to that exception is vendor extended types (Itanium C++
4181 if (consumeIf('I')) {
4182 Node
*BaseType
= parseType();
4183 if (BaseType
== nullptr)
4185 if (!consumeIf('E'))
4187 Result
= make
<TransformedType
>(Res
, BaseType
);
4189 Result
= make
<NameType
>(Res
);
4194 // ::= Dd # IEEE 754r decimal floating point (64 bits)
4197 return make
<NameType
>("decimal64");
4198 // ::= De # IEEE 754r decimal floating point (128 bits)
4201 return make
<NameType
>("decimal128");
4202 // ::= Df # IEEE 754r decimal floating point (32 bits)
4205 return make
<NameType
>("decimal32");
4206 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
4209 return make
<NameType
>("half");
4210 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
4213 Node
*DimensionNumber
= make
<NameType
>(parseNumber());
4214 if (!DimensionNumber
)
4216 if (!consumeIf('_'))
4218 return make
<BinaryFPType
>(DimensionNumber
);
4220 // ::= DB <number> _ # C23 signed _BitInt(N)
4221 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
4222 // ::= DU <number> _ # C23 unsigned _BitInt(N)
4223 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
4226 bool Signed
= look(1) == 'B';
4228 Node
*Size
= std::isdigit(look()) ? make
<NameType
>(parseNumber())
4229 : getDerived().parseExpr();
4232 if (!consumeIf('_'))
4234 return make
<BitIntType
>(Size
, Signed
);
4236 // ::= Di # char32_t
4239 return make
<NameType
>("char32_t");
4240 // ::= Ds # char16_t
4243 return make
<NameType
>("char16_t");
4244 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
4247 return make
<NameType
>("char8_t");
4248 // ::= Da # auto (in dependent new-expressions)
4251 return make
<NameType
>("auto");
4252 // ::= Dc # decltype(auto)
4255 return make
<NameType
>("decltype(auto)");
4256 // ::= Dk <type-constraint> # constrained auto
4257 // ::= DK <type-constraint> # constrained decltype(auto)
4260 std::string_view Kind
= look(1) == 'k' ? " auto" : " decltype(auto)";
4262 Node
*Constraint
= getDerived().parseName();
4265 return make
<PostfixQualifiedType
>(Constraint
, Kind
);
4267 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
4270 return make
<NameType
>("std::nullptr_t");
4275 Result
= getDerived().parseDecltype();
4278 // extension ::= <vector-type> # <vector-type> starts with Dv
4280 Result
= getDerived().parseVectorType();
4283 // ::= Dp <type> # pack expansion (C++0x)
4286 Node
*Child
= getDerived().parseType();
4289 Result
= make
<ParameterPackExpansion
>(Child
);
4292 // Exception specifier on a function type.
4296 // Transaction safe function type.
4298 Result
= getDerived().parseFunctionType();
4302 // ::= <function-type>
4304 Result
= getDerived().parseFunctionType();
4309 Result
= getDerived().parseArrayType();
4312 // ::= <pointer-to-member-type>
4314 Result
= getDerived().parsePointerToMemberType();
4317 // ::= <template-param>
4319 // This could be an elaborate type specifier on a <class-enum-type>.
4320 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
4321 Result
= getDerived().parseClassEnumType();
4325 Result
= getDerived().parseTemplateParam();
4326 if (Result
== nullptr)
4329 // Result could be either of:
4330 // <type> ::= <template-param>
4331 // <type> ::= <template-template-param> <template-args>
4333 // <template-template-param> ::= <template-param>
4334 // ::= <substitution>
4336 // If this is followed by some <template-args>, and we're permitted to
4337 // parse them, take the second production.
4339 if (TryToParseTemplateArgs
&& look() == 'I') {
4340 Node
*TA
= getDerived().parseTemplateArgs();
4343 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
4347 // ::= P <type> # pointer
4350 Node
*Ptr
= getDerived().parseType();
4353 Result
= make
<PointerType
>(Ptr
);
4356 // ::= R <type> # l-value reference
4359 Node
*Ref
= getDerived().parseType();
4362 Result
= make
<ReferenceType
>(Ref
, ReferenceKind::LValue
);
4365 // ::= O <type> # r-value reference (C++11)
4368 Node
*Ref
= getDerived().parseType();
4371 Result
= make
<ReferenceType
>(Ref
, ReferenceKind::RValue
);
4374 // ::= C <type> # complex pair (C99)
4377 Node
*P
= getDerived().parseType();
4380 Result
= make
<PostfixQualifiedType
>(P
, " complex");
4383 // ::= G <type> # imaginary (C99)
4386 Node
*P
= getDerived().parseType();
4389 Result
= make
<PostfixQualifiedType
>(P
, " imaginary");
4392 // ::= <substitution> # See Compression below
4394 if (look(1) != 't') {
4395 bool IsSubst
= false;
4396 Result
= getDerived().parseUnscopedName(nullptr, &IsSubst
);
4400 // Sub could be either of:
4401 // <type> ::= <substitution>
4402 // <type> ::= <template-template-param> <template-args>
4404 // <template-template-param> ::= <template-param>
4405 // ::= <substitution>
4407 // If this is followed by some <template-args>, and we're permitted to
4408 // parse them, take the second production.
4410 if (look() == 'I' && (!IsSubst
|| TryToParseTemplateArgs
)) {
4412 Subs
.push_back(Result
);
4413 Node
*TA
= getDerived().parseTemplateArgs();
4416 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
4417 } else if (IsSubst
) {
4418 // If all we parsed was a substitution, don't re-insert into the
4419 // substitution table.
4424 DEMANGLE_FALLTHROUGH
;
4426 // ::= <class-enum-type>
4428 Result
= getDerived().parseClassEnumType();
4433 // If we parsed a type, insert it into the substitution table. Note that all
4434 // <builtin-type>s and <substitution>s have already bailed out, because they
4435 // don't get substitutions.
4436 if (Result
!= nullptr)
4437 Subs
.push_back(Result
);
4441 template <typename Derived
, typename Alloc
>
4443 AbstractManglingParser
<Derived
, Alloc
>::parsePrefixExpr(std::string_view Kind
,
4445 Node
*E
= getDerived().parseExpr();
4448 return make
<PrefixExpr
>(Kind
, E
, Prec
);
4451 template <typename Derived
, typename Alloc
>
4453 AbstractManglingParser
<Derived
, Alloc
>::parseBinaryExpr(std::string_view Kind
,
4455 Node
*LHS
= getDerived().parseExpr();
4458 Node
*RHS
= getDerived().parseExpr();
4461 return make
<BinaryExpr
>(LHS
, Kind
, RHS
, Prec
);
4464 template <typename Derived
, typename Alloc
>
4465 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseIntegerLiteral(
4466 std::string_view Lit
) {
4467 std::string_view Tmp
= parseNumber(true);
4468 if (!Tmp
.empty() && consumeIf('E'))
4469 return make
<IntegerLiteral
>(Lit
, Tmp
);
4473 // <CV-Qualifiers> ::= [r] [V] [K]
4474 template <typename Alloc
, typename Derived
>
4475 Qualifiers AbstractManglingParser
<Alloc
, Derived
>::parseCVQualifiers() {
4476 Qualifiers CVR
= QualNone
;
4478 CVR
|= QualRestrict
;
4480 CVR
|= QualVolatile
;
4486 // <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4487 // ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4488 // ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4489 // ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
4490 // ::= fpT # 'this' expression (not part of standard?)
4491 template <typename Derived
, typename Alloc
>
4492 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFunctionParam() {
4493 if (consumeIf("fpT"))
4494 return make
<NameType
>("this");
4495 if (consumeIf("fp")) {
4496 parseCVQualifiers();
4497 std::string_view Num
= parseNumber();
4498 if (!consumeIf('_'))
4500 return make
<FunctionParam
>(Num
);
4502 if (consumeIf("fL")) {
4503 if (parseNumber().empty())
4505 if (!consumeIf('p'))
4507 parseCVQualifiers();
4508 std::string_view Num
= parseNumber();
4509 if (!consumeIf('_'))
4511 return make
<FunctionParam
>(Num
);
4516 // cv <type> <expression> # conversion with one argument
4517 // cv <type> _ <expression>* E # conversion with a different number of arguments
4518 template <typename Derived
, typename Alloc
>
4519 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseConversionExpr() {
4520 if (!consumeIf("cv"))
4524 ScopedOverride
<bool> SaveTemp(TryToParseTemplateArgs
, false);
4525 Ty
= getDerived().parseType();
4531 if (consumeIf('_')) {
4532 size_t ExprsBegin
= Names
.size();
4533 while (!consumeIf('E')) {
4534 Node
*E
= getDerived().parseExpr();
4539 NodeArray Exprs
= popTrailingNodeArray(ExprsBegin
);
4540 return make
<ConversionExpr
>(Ty
, Exprs
);
4543 Node
*E
[1] = {getDerived().parseExpr()};
4544 if (E
[0] == nullptr)
4546 return make
<ConversionExpr
>(Ty
, makeNodeArray(E
, E
+ 1));
4549 // <expr-primary> ::= L <type> <value number> E # integer literal
4550 // ::= L <type> <value float> E # floating literal
4551 // ::= L <string type> E # string literal
4552 // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
4553 // ::= L <lambda type> E # lambda expression
4554 // FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4555 // ::= L <mangled-name> E # external name
4556 template <typename Derived
, typename Alloc
>
4557 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseExprPrimary() {
4558 if (!consumeIf('L'))
4563 return getDerived().parseIntegerLiteral("wchar_t");
4565 if (consumeIf("b0E"))
4566 return make
<BoolExpr
>(0);
4567 if (consumeIf("b1E"))
4568 return make
<BoolExpr
>(1);
4572 return getDerived().parseIntegerLiteral("char");
4575 return getDerived().parseIntegerLiteral("signed char");
4578 return getDerived().parseIntegerLiteral("unsigned char");
4581 return getDerived().parseIntegerLiteral("short");
4584 return getDerived().parseIntegerLiteral("unsigned short");
4587 return getDerived().parseIntegerLiteral("");
4590 return getDerived().parseIntegerLiteral("u");
4593 return getDerived().parseIntegerLiteral("l");
4596 return getDerived().parseIntegerLiteral("ul");
4599 return getDerived().parseIntegerLiteral("ll");
4602 return getDerived().parseIntegerLiteral("ull");
4605 return getDerived().parseIntegerLiteral("__int128");
4608 return getDerived().parseIntegerLiteral("unsigned __int128");
4611 return getDerived().template parseFloatingLiteral
<float>();
4614 return getDerived().template parseFloatingLiteral
<double>();
4617 #if defined(__powerpc__) || defined(__s390__)
4618 // Handle cases where long doubles encoded with e have the same size
4619 // and representation as doubles.
4620 return getDerived().template parseFloatingLiteral
<double>();
4622 return getDerived().template parseFloatingLiteral
<long double>();
4625 if (consumeIf("_Z")) {
4626 Node
*R
= getDerived().parseEncoding();
4627 if (R
!= nullptr && consumeIf('E'))
4632 Node
*T
= getDerived().parseType();
4635 // FIXME: We need to include the string contents in the mangling.
4637 return make
<StringLiteral
>(T
);
4641 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
4642 return make
<NameType
>("nullptr");
4645 // Invalid mangled name per
4646 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4649 // FIXME: Should we support LUb... for block literals?
4652 Node
*T
= parseUnnamedTypeName(nullptr);
4653 if (!T
|| !consumeIf('E'))
4655 return make
<LambdaExpr
>(T
);
4658 // might be named type
4659 Node
*T
= getDerived().parseType();
4662 std::string_view N
= parseNumber(/*AllowNegative=*/true);
4665 if (!consumeIf('E'))
4667 return make
<EnumLiteral
>(T
, N
);
4672 // <braced-expression> ::= <expression>
4673 // ::= di <field source-name> <braced-expression> # .name = expr
4674 // ::= dx <index expression> <braced-expression> # [expr] = expr
4675 // ::= dX <range begin expression> <range end expression> <braced-expression>
4676 template <typename Derived
, typename Alloc
>
4677 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseBracedExpr() {
4678 if (look() == 'd') {
4682 Node
*Field
= getDerived().parseSourceName(/*NameState=*/nullptr);
4683 if (Field
== nullptr)
4685 Node
*Init
= getDerived().parseBracedExpr();
4686 if (Init
== nullptr)
4688 return make
<BracedExpr
>(Field
, Init
, /*isArray=*/false);
4692 Node
*Index
= getDerived().parseExpr();
4693 if (Index
== nullptr)
4695 Node
*Init
= getDerived().parseBracedExpr();
4696 if (Init
== nullptr)
4698 return make
<BracedExpr
>(Index
, Init
, /*isArray=*/true);
4702 Node
*RangeBegin
= getDerived().parseExpr();
4703 if (RangeBegin
== nullptr)
4705 Node
*RangeEnd
= getDerived().parseExpr();
4706 if (RangeEnd
== nullptr)
4708 Node
*Init
= getDerived().parseBracedExpr();
4709 if (Init
== nullptr)
4711 return make
<BracedRangeExpr
>(RangeBegin
, RangeEnd
, Init
);
4715 return getDerived().parseExpr();
4718 // (not yet in the spec)
4719 // <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4720 // ::= fR <binary-operator-name> <expression> <expression>
4721 // ::= fl <binary-operator-name> <expression>
4722 // ::= fr <binary-operator-name> <expression>
4723 template <typename Derived
, typename Alloc
>
4724 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFoldExpr() {
4725 if (!consumeIf('f'))
4728 bool IsLeftFold
= false, HasInitializer
= false;
4734 HasInitializer
= true;
4737 HasInitializer
= true;
4747 const auto *Op
= parseOperatorEncoding();
4750 if (!(Op
->getKind() == OperatorInfo::Binary
4751 || (Op
->getKind() == OperatorInfo::Member
4752 && Op
->getName().back() == '*')))
4755 Node
*Pack
= getDerived().parseExpr();
4756 if (Pack
== nullptr)
4759 Node
*Init
= nullptr;
4760 if (HasInitializer
) {
4761 Init
= getDerived().parseExpr();
4762 if (Init
== nullptr)
4766 if (IsLeftFold
&& Init
)
4767 std::swap(Pack
, Init
);
4769 return make
<FoldExpr
>(IsLeftFold
, Op
->getSymbol(), Pack
, Init
);
4772 // <expression> ::= mc <parameter type> <expr> [<offset number>] E
4774 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4775 template <typename Derived
, typename Alloc
>
4777 AbstractManglingParser
<Derived
, Alloc
>::parsePointerToMemberConversionExpr(
4779 Node
*Ty
= getDerived().parseType();
4782 Node
*Expr
= getDerived().parseExpr();
4785 std::string_view Offset
= getDerived().parseNumber(true);
4786 if (!consumeIf('E'))
4788 return make
<PointerToMemberConversionExpr
>(Ty
, Expr
, Offset
, Prec
);
4791 // <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4792 // <union-selector> ::= _ [<number>]
4794 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4795 template <typename Derived
, typename Alloc
>
4796 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSubobjectExpr() {
4797 Node
*Ty
= getDerived().parseType();
4800 Node
*Expr
= getDerived().parseExpr();
4803 std::string_view Offset
= getDerived().parseNumber(true);
4804 size_t SelectorsBegin
= Names
.size();
4805 while (consumeIf('_')) {
4806 Node
*Selector
= make
<NameType
>(parseNumber());
4809 Names
.push_back(Selector
);
4811 bool OnePastTheEnd
= consumeIf('p');
4812 if (!consumeIf('E'))
4814 return make
<SubobjectExpr
>(
4815 Ty
, Expr
, Offset
, popTrailingNodeArray(SelectorsBegin
), OnePastTheEnd
);
4818 template <typename Derived
, typename Alloc
>
4819 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseConstraintExpr() {
4820 // Within this expression, all enclosing template parameter lists are in
4822 ScopedOverride
<bool> SaveInConstraintExpr(InConstraintExpr
, true);
4823 return getDerived().parseExpr();
4826 template <typename Derived
, typename Alloc
>
4827 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseRequiresExpr() {
4829 if (consumeIf("rQ")) {
4830 // <expression> ::= rQ <bare-function-type> _ <requirement>+ E
4831 size_t ParamsBegin
= Names
.size();
4832 while (!consumeIf('_')) {
4833 Node
*Type
= getDerived().parseType();
4834 if (Type
== nullptr)
4836 Names
.push_back(Type
);
4838 Params
= popTrailingNodeArray(ParamsBegin
);
4839 } else if (!consumeIf("rq")) {
4840 // <expression> ::= rq <requirement>+ E
4844 size_t ReqsBegin
= Names
.size();
4846 Node
*Constraint
= nullptr;
4847 if (consumeIf('X')) {
4848 // <requirement> ::= X <expression> [N] [R <type-constraint>]
4849 Node
*Expr
= getDerived().parseExpr();
4850 if (Expr
== nullptr)
4852 bool Noexcept
= consumeIf('N');
4853 Node
*TypeReq
= nullptr;
4854 if (consumeIf('R')) {
4855 TypeReq
= getDerived().parseName();
4856 if (TypeReq
== nullptr)
4859 Constraint
= make
<ExprRequirement
>(Expr
, Noexcept
, TypeReq
);
4860 } else if (consumeIf('T')) {
4861 // <requirement> ::= T <type>
4862 Node
*Type
= getDerived().parseType();
4863 if (Type
== nullptr)
4865 Constraint
= make
<TypeRequirement
>(Type
);
4866 } else if (consumeIf('Q')) {
4867 // <requirement> ::= Q <constraint-expression>
4869 // FIXME: We use <expression> instead of <constraint-expression>. Either
4870 // the requires expression is already inside a constraint expression, in
4871 // which case it makes no difference, or we're in a requires-expression
4872 // that might be partially-substituted, where the language behavior is
4873 // not yet settled and clang mangles after substitution.
4874 Node
*NestedReq
= getDerived().parseExpr();
4875 if (NestedReq
== nullptr)
4877 Constraint
= make
<NestedRequirement
>(NestedReq
);
4879 if (Constraint
== nullptr)
4881 Names
.push_back(Constraint
);
4882 } while (!consumeIf('E'));
4884 return make
<RequiresExpr
>(Params
, popTrailingNodeArray(ReqsBegin
));
4887 // <expression> ::= <unary operator-name> <expression>
4888 // ::= <binary operator-name> <expression> <expression>
4889 // ::= <ternary operator-name> <expression> <expression> <expression>
4890 // ::= cl <expression>+ E # call
4891 // ::= cv <type> <expression> # conversion with one argument
4892 // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4893 // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4894 // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4895 // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4896 // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4897 // ::= [gs] dl <expression> # delete expression
4898 // ::= [gs] da <expression> # delete[] expression
4899 // ::= pp_ <expression> # prefix ++
4900 // ::= mm_ <expression> # prefix --
4901 // ::= ti <type> # typeid (type)
4902 // ::= te <expression> # typeid (expression)
4903 // ::= dc <type> <expression> # dynamic_cast<type> (expression)
4904 // ::= sc <type> <expression> # static_cast<type> (expression)
4905 // ::= cc <type> <expression> # const_cast<type> (expression)
4906 // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4907 // ::= st <type> # sizeof (a type)
4908 // ::= sz <expression> # sizeof (an expression)
4909 // ::= at <type> # alignof (a type)
4910 // ::= az <expression> # alignof (an expression)
4911 // ::= nx <expression> # noexcept (expression)
4912 // ::= <template-param>
4913 // ::= <function-param>
4914 // ::= dt <expression> <unresolved-name> # expr.name
4915 // ::= pt <expression> <unresolved-name> # expr->name
4916 // ::= ds <expression> <expression> # expr.*expr
4917 // ::= sZ <template-param> # size of a parameter pack
4918 // ::= sZ <function-param> # size of a function parameter pack
4919 // ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4920 // ::= sp <expression> # pack expansion
4921 // ::= tw <expression> # throw expression
4922 // ::= tr # throw with no operand (rethrow)
4923 // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4924 // # freestanding dependent name (e.g., T::x),
4925 // # objectless nonstatic member reference
4926 // ::= fL <binary-operator-name> <expression> <expression>
4927 // ::= fR <binary-operator-name> <expression> <expression>
4928 // ::= fl <binary-operator-name> <expression>
4929 // ::= fr <binary-operator-name> <expression>
4930 // ::= <expr-primary>
4931 template <typename Derived
, typename Alloc
>
4932 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseExpr() {
4933 bool Global
= consumeIf("gs");
4935 const auto *Op
= parseOperatorEncoding();
4937 auto Sym
= Op
->getSymbol();
4938 switch (Op
->getKind()) {
4939 case OperatorInfo::Binary
:
4940 // Binary operator: lhs @ rhs
4941 return getDerived().parseBinaryExpr(Sym
, Op
->getPrecedence());
4942 case OperatorInfo::Prefix
:
4943 // Prefix unary operator: @ expr
4944 return getDerived().parsePrefixExpr(Sym
, Op
->getPrecedence());
4945 case OperatorInfo::Postfix
: {
4946 // Postfix unary operator: expr @
4948 return getDerived().parsePrefixExpr(Sym
, Op
->getPrecedence());
4949 Node
*Ex
= getDerived().parseExpr();
4952 return make
<PostfixExpr
>(Ex
, Sym
, Op
->getPrecedence());
4954 case OperatorInfo::Array
: {
4955 // Array Index: lhs [ rhs ]
4956 Node
*Base
= getDerived().parseExpr();
4957 if (Base
== nullptr)
4959 Node
*Index
= getDerived().parseExpr();
4960 if (Index
== nullptr)
4962 return make
<ArraySubscriptExpr
>(Base
, Index
, Op
->getPrecedence());
4964 case OperatorInfo::Member
: {
4965 // Member access lhs @ rhs
4966 Node
*LHS
= getDerived().parseExpr();
4969 Node
*RHS
= getDerived().parseExpr();
4972 return make
<MemberExpr
>(LHS
, Sym
, RHS
, Op
->getPrecedence());
4974 case OperatorInfo::New
: {
4976 // # new (expr-list) type [(init)]
4977 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4978 // # new[] (expr-list) type [(init)]
4979 // [gs] na <expression>* _ <type> [pi <expression>*] E
4980 size_t Exprs
= Names
.size();
4981 while (!consumeIf('_')) {
4982 Node
*Ex
= getDerived().parseExpr();
4985 Names
.push_back(Ex
);
4987 NodeArray ExprList
= popTrailingNodeArray(Exprs
);
4988 Node
*Ty
= getDerived().parseType();
4991 bool HaveInits
= consumeIf("pi");
4992 size_t InitsBegin
= Names
.size();
4993 while (!consumeIf('E')) {
4996 Node
*Init
= getDerived().parseExpr();
4997 if (Init
== nullptr)
4999 Names
.push_back(Init
);
5001 NodeArray Inits
= popTrailingNodeArray(InitsBegin
);
5002 return make
<NewExpr
>(ExprList
, Ty
, Inits
, Global
,
5003 /*IsArray=*/Op
->getFlag(), Op
->getPrecedence());
5005 case OperatorInfo::Del
: {
5007 Node
*Ex
= getDerived().parseExpr();
5010 return make
<DeleteExpr
>(Ex
, Global
, /*IsArray=*/Op
->getFlag(),
5011 Op
->getPrecedence());
5013 case OperatorInfo::Call
: {
5015 Node
*Callee
= getDerived().parseExpr();
5016 if (Callee
== nullptr)
5018 size_t ExprsBegin
= Names
.size();
5019 while (!consumeIf('E')) {
5020 Node
*E
= getDerived().parseExpr();
5025 return make
<CallExpr
>(Callee
, popTrailingNodeArray(ExprsBegin
),
5026 Op
->getPrecedence());
5028 case OperatorInfo::CCast
: {
5029 // C Cast: (type)expr
5032 ScopedOverride
<bool> SaveTemp(TryToParseTemplateArgs
, false);
5033 Ty
= getDerived().parseType();
5038 size_t ExprsBegin
= Names
.size();
5039 bool IsMany
= consumeIf('_');
5040 while (!consumeIf('E')) {
5041 Node
*E
= getDerived().parseExpr();
5048 NodeArray Exprs
= popTrailingNodeArray(ExprsBegin
);
5049 if (!IsMany
&& Exprs
.size() != 1)
5051 return make
<ConversionExpr
>(Ty
, Exprs
, Op
->getPrecedence());
5053 case OperatorInfo::Conditional
: {
5054 // Conditional operator: expr ? expr : expr
5055 Node
*Cond
= getDerived().parseExpr();
5056 if (Cond
== nullptr)
5058 Node
*LHS
= getDerived().parseExpr();
5061 Node
*RHS
= getDerived().parseExpr();
5064 return make
<ConditionalExpr
>(Cond
, LHS
, RHS
, Op
->getPrecedence());
5066 case OperatorInfo::NamedCast
: {
5067 // Named cast operation, @<type>(expr)
5068 Node
*Ty
= getDerived().parseType();
5071 Node
*Ex
= getDerived().parseExpr();
5074 return make
<CastExpr
>(Sym
, Ty
, Ex
, Op
->getPrecedence());
5076 case OperatorInfo::OfIdOp
: {
5077 // [sizeof/alignof/typeid] ( <type>|<expr> )
5079 Op
->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
5082 return make
<EnclosingExpr
>(Sym
, Arg
, Op
->getPrecedence());
5084 case OperatorInfo::NameOnly
: {
5085 // Not valid as an expression operand.
5089 DEMANGLE_UNREACHABLE
;
5096 return getDerived().parseExprPrimary();
5098 return getDerived().parseTemplateParam();
5099 if (look() == 'f') {
5100 // Disambiguate a fold expression from a <function-param>.
5101 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
5102 return getDerived().parseFunctionParam();
5103 return getDerived().parseFoldExpr();
5105 if (consumeIf("il")) {
5106 size_t InitsBegin
= Names
.size();
5107 while (!consumeIf('E')) {
5108 Node
*E
= getDerived().parseBracedExpr();
5113 return make
<InitListExpr
>(nullptr, popTrailingNodeArray(InitsBegin
));
5115 if (consumeIf("mc"))
5116 return parsePointerToMemberConversionExpr(Node::Prec::Unary
);
5117 if (consumeIf("nx")) {
5118 Node
*Ex
= getDerived().parseExpr();
5121 return make
<EnclosingExpr
>("noexcept ", Ex
, Node::Prec::Unary
);
5123 if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q'))
5124 return parseRequiresExpr();
5125 if (consumeIf("so"))
5126 return parseSubobjectExpr();
5127 if (consumeIf("sp")) {
5128 Node
*Child
= getDerived().parseExpr();
5129 if (Child
== nullptr)
5131 return make
<ParameterPackExpansion
>(Child
);
5133 if (consumeIf("sZ")) {
5134 if (look() == 'T') {
5135 Node
*R
= getDerived().parseTemplateParam();
5138 return make
<SizeofParamPackExpr
>(R
);
5140 Node
*FP
= getDerived().parseFunctionParam();
5143 return make
<EnclosingExpr
>("sizeof... ", FP
);
5145 if (consumeIf("sP")) {
5146 size_t ArgsBegin
= Names
.size();
5147 while (!consumeIf('E')) {
5148 Node
*Arg
= getDerived().parseTemplateArg();
5151 Names
.push_back(Arg
);
5153 auto *Pack
= make
<NodeArrayNode
>(popTrailingNodeArray(ArgsBegin
));
5156 return make
<EnclosingExpr
>("sizeof... ", Pack
);
5158 if (consumeIf("tl")) {
5159 Node
*Ty
= getDerived().parseType();
5162 size_t InitsBegin
= Names
.size();
5163 while (!consumeIf('E')) {
5164 Node
*E
= getDerived().parseBracedExpr();
5169 return make
<InitListExpr
>(Ty
, popTrailingNodeArray(InitsBegin
));
5171 if (consumeIf("tr"))
5172 return make
<NameType
>("throw");
5173 if (consumeIf("tw")) {
5174 Node
*Ex
= getDerived().parseExpr();
5177 return make
<ThrowExpr
>(Ex
);
5179 if (consumeIf('u')) {
5180 Node
*Name
= getDerived().parseSourceName(/*NameState=*/nullptr);
5183 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
5184 // standard encoding expects a <template-arg>, and would be otherwise be
5185 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
5186 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
5187 // actual conflict here.
5188 bool IsUUID
= false;
5189 Node
*UUID
= nullptr;
5190 if (Name
->getBaseName() == "__uuidof") {
5191 if (consumeIf('t')) {
5192 UUID
= getDerived().parseType();
5194 } else if (consumeIf('z')) {
5195 UUID
= getDerived().parseExpr();
5199 size_t ExprsBegin
= Names
.size();
5201 if (UUID
== nullptr)
5203 Names
.push_back(UUID
);
5205 while (!consumeIf('E')) {
5206 Node
*E
= getDerived().parseTemplateArg();
5212 return make
<CallExpr
>(Name
, popTrailingNodeArray(ExprsBegin
),
5213 Node::Prec::Postfix
);
5216 // Only unresolved names remain.
5217 return getDerived().parseUnresolvedName(Global
);
5220 // <call-offset> ::= h <nv-offset> _
5221 // ::= v <v-offset> _
5223 // <nv-offset> ::= <offset number>
5224 // # non-virtual base override
5226 // <v-offset> ::= <offset number> _ <virtual offset number>
5227 // # virtual base override, with vcall offset
5228 template <typename Alloc
, typename Derived
>
5229 bool AbstractManglingParser
<Alloc
, Derived
>::parseCallOffset() {
5230 // Just scan through the call offset, we never add this information into the
5233 return parseNumber(true).empty() || !consumeIf('_');
5235 return parseNumber(true).empty() || !consumeIf('_') ||
5236 parseNumber(true).empty() || !consumeIf('_');
5240 // <special-name> ::= TV <type> # virtual table
5241 // ::= TT <type> # VTT structure (construction vtable index)
5242 // ::= TI <type> # typeinfo structure
5243 // ::= TS <type> # typeinfo name (null-terminated byte string)
5244 // ::= Tc <call-offset> <call-offset> <base encoding>
5245 // # base is the nominal target function of thunk
5246 // # first call-offset is 'this' adjustment
5247 // # second call-offset is result adjustment
5248 // ::= T <call-offset> <base encoding>
5249 // # base is the nominal target function of thunk
5250 // # Guard variable for one-time initialization
5251 // ::= GV <object name>
5253 // ::= TW <object name> # Thread-local wrapper
5254 // ::= TH <object name> # Thread-local initialization
5255 // ::= GR <object name> _ # First temporary
5256 // ::= GR <object name> <seq-id> _ # Subsequent temporaries
5257 // # construction vtable for second-in-first
5258 // extension ::= TC <first type> <number> _ <second type>
5259 // extension ::= GR <object name> # reference temporary for object
5260 // extension ::= GI <module name> # module global initializer
5261 template <typename Derived
, typename Alloc
>
5262 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSpecialName() {
5266 // TA <template-arg> # template parameter object
5268 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
5271 Node
*Arg
= getDerived().parseTemplateArg();
5274 return make
<SpecialName
>("template parameter object for ", Arg
);
5276 // TV <type> # virtual table
5279 Node
*Ty
= getDerived().parseType();
5282 return make
<SpecialName
>("vtable for ", Ty
);
5284 // TT <type> # VTT structure (construction vtable index)
5287 Node
*Ty
= getDerived().parseType();
5290 return make
<SpecialName
>("VTT for ", Ty
);
5292 // TI <type> # typeinfo structure
5295 Node
*Ty
= getDerived().parseType();
5298 return make
<SpecialName
>("typeinfo for ", Ty
);
5300 // TS <type> # typeinfo name (null-terminated byte string)
5303 Node
*Ty
= getDerived().parseType();
5306 return make
<SpecialName
>("typeinfo name for ", Ty
);
5308 // Tc <call-offset> <call-offset> <base encoding>
5311 if (parseCallOffset() || parseCallOffset())
5313 Node
*Encoding
= getDerived().parseEncoding();
5314 if (Encoding
== nullptr)
5316 return make
<SpecialName
>("covariant return thunk to ", Encoding
);
5318 // extension ::= TC <first type> <number> _ <second type>
5319 // # construction vtable for second-in-first
5322 Node
*FirstType
= getDerived().parseType();
5323 if (FirstType
== nullptr)
5325 if (parseNumber(true).empty() || !consumeIf('_'))
5327 Node
*SecondType
= getDerived().parseType();
5328 if (SecondType
== nullptr)
5330 return make
<CtorVtableSpecialName
>(SecondType
, FirstType
);
5332 // TW <object name> # Thread-local wrapper
5335 Node
*Name
= getDerived().parseName();
5336 if (Name
== nullptr)
5338 return make
<SpecialName
>("thread-local wrapper routine for ", Name
);
5340 // TH <object name> # Thread-local initialization
5343 Node
*Name
= getDerived().parseName();
5344 if (Name
== nullptr)
5346 return make
<SpecialName
>("thread-local initialization routine for ", Name
);
5348 // T <call-offset> <base encoding>
5351 bool IsVirt
= look() == 'v';
5352 if (parseCallOffset())
5354 Node
*BaseEncoding
= getDerived().parseEncoding();
5355 if (BaseEncoding
== nullptr)
5358 return make
<SpecialName
>("virtual thunk to ", BaseEncoding
);
5360 return make
<SpecialName
>("non-virtual thunk to ", BaseEncoding
);
5365 // GV <object name> # Guard variable for one-time initialization
5368 Node
*Name
= getDerived().parseName();
5369 if (Name
== nullptr)
5371 return make
<SpecialName
>("guard variable for ", Name
);
5373 // GR <object name> # reference temporary for object
5374 // GR <object name> _ # First temporary
5375 // GR <object name> <seq-id> _ # Subsequent temporaries
5378 Node
*Name
= getDerived().parseName();
5379 if (Name
== nullptr)
5382 bool ParsedSeqId
= !parseSeqId(&Count
);
5383 if (!consumeIf('_') && ParsedSeqId
)
5385 return make
<SpecialName
>("reference temporary for ", Name
);
5387 // GI <module-name> v
5390 ModuleName
*Module
= nullptr;
5391 if (getDerived().parseModuleNameOpt(Module
))
5393 if (Module
== nullptr)
5395 return make
<SpecialName
>("initializer for module ", Module
);
5402 // <encoding> ::= <function name> <bare-function-type>
5403 // [`Q` <requires-clause expr>]
5405 // ::= <special-name>
5406 template <typename Derived
, typename Alloc
>
5407 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseEncoding(bool ParseParams
) {
5408 // The template parameters of an encoding are unrelated to those of the
5409 // enclosing context.
5410 SaveTemplateParams
SaveTemplateParamsScope(this);
5412 if (look() == 'G' || look() == 'T')
5413 return getDerived().parseSpecialName();
5415 auto IsEndOfEncoding
= [&] {
5416 // The set of chars that can potentially follow an <encoding> (none of which
5417 // can start a <type>). Enumerating these allows us to avoid speculative
5419 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5422 NameState
NameInfo(this);
5423 Node
*Name
= getDerived().parseName(&NameInfo
);
5424 if (Name
== nullptr)
5427 if (resolveForwardTemplateRefs(NameInfo
))
5430 if (IsEndOfEncoding())
5433 // ParseParams may be false at the top level only, when called from parse().
5434 // For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be
5435 // false when demangling 3fooILZ3BarEET_f but is always true when demangling
5443 Node
*Attrs
= nullptr;
5444 if (consumeIf("Ua9enable_ifI")) {
5445 size_t BeforeArgs
= Names
.size();
5446 while (!consumeIf('E')) {
5447 Node
*Arg
= getDerived().parseTemplateArg();
5450 Names
.push_back(Arg
);
5452 Attrs
= make
<EnableIfAttr
>(popTrailingNodeArray(BeforeArgs
));
5457 Node
*ReturnType
= nullptr;
5458 if (!NameInfo
.CtorDtorConversion
&& NameInfo
.EndsWithTemplateArgs
) {
5459 ReturnType
= getDerived().parseType();
5460 if (ReturnType
== nullptr)
5465 if (!consumeIf('v')) {
5466 size_t ParamsBegin
= Names
.size();
5468 Node
*Ty
= getDerived().parseType();
5472 const bool IsFirstParam
= ParamsBegin
== Names
.size();
5473 if (NameInfo
.HasExplicitObjectParameter
&& IsFirstParam
)
5474 Ty
= make
<ExplicitObjectParameter
>(Ty
);
5479 Names
.push_back(Ty
);
5480 } while (!IsEndOfEncoding() && look() != 'Q');
5481 Params
= popTrailingNodeArray(ParamsBegin
);
5484 Node
*Requires
= nullptr;
5485 if (consumeIf('Q')) {
5486 Requires
= getDerived().parseConstraintExpr();
5491 return make
<FunctionEncoding
>(ReturnType
, Name
, Params
, Attrs
, Requires
,
5492 NameInfo
.CVQualifiers
,
5493 NameInfo
.ReferenceQualifier
);
5496 template <class Float
>
5500 struct FloatData
<float>
5502 static const size_t mangled_size
= 8;
5503 static const size_t max_demangled_size
= 24;
5504 static constexpr const char* spec
= "%af";
5508 struct FloatData
<double>
5510 static const size_t mangled_size
= 16;
5511 static const size_t max_demangled_size
= 32;
5512 static constexpr const char* spec
= "%a";
5516 struct FloatData
<long double>
5518 #if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5519 defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \
5521 static const size_t mangled_size
= 32;
5522 #elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5523 static const size_t mangled_size
= 16;
5525 static const size_t mangled_size
= 20; // May need to be adjusted to 16 or 24 on other platforms
5527 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5528 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5529 // Negatives are one character longer than positives.
5530 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5531 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5532 static const size_t max_demangled_size
= 42;
5533 static constexpr const char *spec
= "%LaL";
5536 template <typename Alloc
, typename Derived
>
5537 template <class Float
>
5538 Node
*AbstractManglingParser
<Alloc
, Derived
>::parseFloatingLiteral() {
5539 const size_t N
= FloatData
<Float
>::mangled_size
;
5542 std::string_view
Data(First
, N
);
5544 if (!(C
>= '0' && C
<= '9') && !(C
>= 'a' && C
<= 'f'))
5547 if (!consumeIf('E'))
5549 return make
<FloatLiteralImpl
<Float
>>(Data
);
5552 // <seq-id> ::= <0-9A-Z>+
5553 template <typename Alloc
, typename Derived
>
5554 bool AbstractManglingParser
<Alloc
, Derived
>::parseSeqId(size_t *Out
) {
5555 if (!(look() >= '0' && look() <= '9') &&
5556 !(look() >= 'A' && look() <= 'Z'))
5561 if (look() >= '0' && look() <= '9') {
5563 Id
+= static_cast<size_t>(look() - '0');
5564 } else if (look() >= 'A' && look() <= 'Z') {
5566 Id
+= static_cast<size_t>(look() - 'A') + 10;
5575 // <substitution> ::= S <seq-id> _
5577 // <substitution> ::= Sa # ::std::allocator
5578 // <substitution> ::= Sb # ::std::basic_string
5579 // <substitution> ::= Ss # ::std::basic_string < char,
5580 // ::std::char_traits<char>,
5581 // ::std::allocator<char> >
5582 // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5583 // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5584 // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
5585 // The St case is handled specially in parseNestedName.
5586 template <typename Derived
, typename Alloc
>
5587 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSubstitution() {
5588 if (!consumeIf('S'))
5591 if (look() >= 'a' && look() <= 'z') {
5592 SpecialSubKind Kind
;
5595 Kind
= SpecialSubKind::allocator
;
5598 Kind
= SpecialSubKind::basic_string
;
5601 Kind
= SpecialSubKind::iostream
;
5604 Kind
= SpecialSubKind::istream
;
5607 Kind
= SpecialSubKind::ostream
;
5610 Kind
= SpecialSubKind::string
;
5616 auto *SpecialSub
= make
<SpecialSubstitution
>(Kind
);
5620 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5621 // has ABI tags, the tags are appended to the substitution; the result is a
5622 // substitutable component.
5623 Node
*WithTags
= getDerived().parseAbiTags(SpecialSub
);
5624 if (WithTags
!= SpecialSub
) {
5625 Subs
.push_back(WithTags
);
5626 SpecialSub
= WithTags
;
5632 if (consumeIf('_')) {
5640 if (parseSeqId(&Index
))
5643 if (!consumeIf('_') || Index
>= Subs
.size())
5648 // <template-param> ::= T_ # first template parameter
5649 // ::= T <parameter-2 non-negative number> _
5650 // ::= TL <level-1> __
5651 // ::= TL <level-1> _ <parameter-2 non-negative number> _
5652 template <typename Derived
, typename Alloc
>
5653 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateParam() {
5654 const char *Begin
= First
;
5655 if (!consumeIf('T'))
5659 if (consumeIf('L')) {
5660 if (parsePositiveInteger(&Level
))
5663 if (!consumeIf('_'))
5668 if (!consumeIf('_')) {
5669 if (parsePositiveInteger(&Index
))
5672 if (!consumeIf('_'))
5676 // We don't track enclosing template parameter levels well enough to reliably
5677 // substitute them all within a <constraint-expression>, so print the
5678 // parameter numbering instead for now.
5679 // TODO: Track all enclosing template parameters and substitute them here.
5680 if (InConstraintExpr
) {
5681 return make
<NameType
>(std::string_view(Begin
, First
- 1 - Begin
));
5684 // If we're in a context where this <template-param> refers to a
5685 // <template-arg> further ahead in the mangled name (currently just conversion
5686 // operator types), then we should only look it up in the right context.
5687 // This can only happen at the outermost level.
5688 if (PermitForwardTemplateReferences
&& Level
== 0) {
5689 Node
*ForwardRef
= make
<ForwardTemplateReference
>(Index
);
5692 DEMANGLE_ASSERT(ForwardRef
->getKind() == Node::KForwardTemplateReference
,
5694 ForwardTemplateRefs
.push_back(
5695 static_cast<ForwardTemplateReference
*>(ForwardRef
));
5699 if (Level
>= TemplateParams
.size() || !TemplateParams
[Level
] ||
5700 Index
>= TemplateParams
[Level
]->size()) {
5701 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5702 // list are mangled as the corresponding artificial template type parameter.
5703 if (ParsingLambdaParamsAtLevel
== Level
&& Level
<= TemplateParams
.size()) {
5704 // This will be popped by the ScopedTemplateParamList in
5705 // parseUnnamedTypeName.
5706 if (Level
== TemplateParams
.size())
5707 TemplateParams
.push_back(nullptr);
5708 return make
<NameType
>("auto");
5714 return (*TemplateParams
[Level
])[Index
];
5717 // <template-param-decl> ::= Ty # type parameter
5718 // ::= Tk <concept name> [<template-args>] # constrained type parameter
5719 // ::= Tn <type> # non-type parameter
5720 // ::= Tt <template-param-decl>* E # template parameter
5721 // ::= Tp <template-param-decl> # parameter pack
5722 template <typename Derived
, typename Alloc
>
5723 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateParamDecl(
5724 TemplateParamList
*Params
) {
5725 auto InventTemplateParamName
= [&](TemplateParamKind Kind
) {
5726 unsigned Index
= NumSyntheticTemplateParameters
[(int)Kind
]++;
5727 Node
*N
= make
<SyntheticTemplateParamName
>(Kind
, Index
);
5729 Params
->push_back(N
);
5733 if (consumeIf("Ty")) {
5734 Node
*Name
= InventTemplateParamName(TemplateParamKind::Type
);
5737 return make
<TypeTemplateParamDecl
>(Name
);
5740 if (consumeIf("Tk")) {
5741 Node
*Constraint
= getDerived().parseName();
5744 Node
*Name
= InventTemplateParamName(TemplateParamKind::Type
);
5747 return make
<ConstrainedTypeTemplateParamDecl
>(Constraint
, Name
);
5750 if (consumeIf("Tn")) {
5751 Node
*Name
= InventTemplateParamName(TemplateParamKind::NonType
);
5754 Node
*Type
= parseType();
5757 return make
<NonTypeTemplateParamDecl
>(Name
, Type
);
5760 if (consumeIf("Tt")) {
5761 Node
*Name
= InventTemplateParamName(TemplateParamKind::Template
);
5764 size_t ParamsBegin
= Names
.size();
5765 ScopedTemplateParamList
TemplateTemplateParamParams(this);
5766 Node
*Requires
= nullptr;
5767 while (!consumeIf('E')) {
5768 Node
*P
= parseTemplateParamDecl(TemplateTemplateParamParams
.params());
5772 if (consumeIf('Q')) {
5773 Requires
= getDerived().parseConstraintExpr();
5774 if (Requires
== nullptr || !consumeIf('E'))
5779 NodeArray InnerParams
= popTrailingNodeArray(ParamsBegin
);
5780 return make
<TemplateTemplateParamDecl
>(Name
, InnerParams
, Requires
);
5783 if (consumeIf("Tp")) {
5784 Node
*P
= parseTemplateParamDecl(Params
);
5787 return make
<TemplateParamPackDecl
>(P
);
5793 // <template-arg> ::= <type> # type or template
5794 // ::= X <expression> E # expression
5795 // ::= <expr-primary> # simple expressions
5796 // ::= J <template-arg>* E # argument pack
5797 // ::= LZ <encoding> E # extension
5798 // ::= <template-param-decl> <template-arg>
5799 template <typename Derived
, typename Alloc
>
5800 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateArg() {
5804 Node
*Arg
= getDerived().parseExpr();
5805 if (Arg
== nullptr || !consumeIf('E'))
5811 size_t ArgsBegin
= Names
.size();
5812 while (!consumeIf('E')) {
5813 Node
*Arg
= getDerived().parseTemplateArg();
5816 Names
.push_back(Arg
);
5818 NodeArray Args
= popTrailingNodeArray(ArgsBegin
);
5819 return make
<TemplateArgumentPack
>(Args
);
5822 // ::= LZ <encoding> E # extension
5823 if (look(1) == 'Z') {
5825 Node
*Arg
= getDerived().parseEncoding();
5826 if (Arg
== nullptr || !consumeIf('E'))
5830 // ::= <expr-primary> # simple expressions
5831 return getDerived().parseExprPrimary();
5834 // Either <template-param> or a <template-param-decl> <template-arg>.
5835 if (!getDerived().isTemplateParamDecl())
5836 return getDerived().parseType();
5837 Node
*Param
= getDerived().parseTemplateParamDecl(nullptr);
5840 Node
*Arg
= getDerived().parseTemplateArg();
5843 return make
<TemplateParamQualifiedArg
>(Param
, Arg
);
5846 return getDerived().parseType();
5850 // <template-args> ::= I <template-arg>* [Q <requires-clause expr>] E
5851 // extension, the abi says <template-arg>+
5852 template <typename Derived
, typename Alloc
>
5854 AbstractManglingParser
<Derived
, Alloc
>::parseTemplateArgs(bool TagTemplates
) {
5855 if (!consumeIf('I'))
5858 // <template-params> refer to the innermost <template-args>. Clear out any
5859 // outer args that we may have inserted into TemplateParams.
5861 TemplateParams
.clear();
5862 TemplateParams
.push_back(&OuterTemplateParams
);
5863 OuterTemplateParams
.clear();
5866 size_t ArgsBegin
= Names
.size();
5867 Node
*Requires
= nullptr;
5868 while (!consumeIf('E')) {
5870 Node
*Arg
= getDerived().parseTemplateArg();
5873 Names
.push_back(Arg
);
5874 Node
*TableEntry
= Arg
;
5875 if (Arg
->getKind() == Node::KTemplateParamQualifiedArg
) {
5877 static_cast<TemplateParamQualifiedArg
*>(TableEntry
)->getArg();
5879 if (Arg
->getKind() == Node::KTemplateArgumentPack
) {
5880 TableEntry
= make
<ParameterPack
>(
5881 static_cast<TemplateArgumentPack
*>(TableEntry
)->getElements());
5885 OuterTemplateParams
.push_back(TableEntry
);
5887 Node
*Arg
= getDerived().parseTemplateArg();
5890 Names
.push_back(Arg
);
5892 if (consumeIf('Q')) {
5893 Requires
= getDerived().parseConstraintExpr();
5894 if (!Requires
|| !consumeIf('E'))
5899 return make
<TemplateArgs
>(popTrailingNodeArray(ArgsBegin
), Requires
);
5902 // <mangled-name> ::= _Z <encoding>
5904 // extension ::= ___Z <encoding> _block_invoke
5905 // extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5906 // extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
5907 template <typename Derived
, typename Alloc
>
5908 Node
*AbstractManglingParser
<Derived
, Alloc
>::parse(bool ParseParams
) {
5909 if (consumeIf("_Z") || consumeIf("__Z")) {
5910 Node
*Encoding
= getDerived().parseEncoding(ParseParams
);
5911 if (Encoding
== nullptr)
5913 if (look() == '.') {
5915 make
<DotSuffix
>(Encoding
, std::string_view(First
, Last
- First
));
5923 if (consumeIf("___Z") || consumeIf("____Z")) {
5924 Node
*Encoding
= getDerived().parseEncoding(ParseParams
);
5925 if (Encoding
== nullptr || !consumeIf("_block_invoke"))
5927 bool RequireNumber
= consumeIf('_');
5928 if (parseNumber().empty() && RequireNumber
)
5934 return make
<SpecialName
>("invocation function for block in ", Encoding
);
5937 Node
*Ty
= getDerived().parseType();
5943 template <typename Alloc
>
5944 struct ManglingParser
: AbstractManglingParser
<ManglingParser
<Alloc
>, Alloc
> {
5945 using AbstractManglingParser
<ManglingParser
<Alloc
>,
5946 Alloc
>::AbstractManglingParser
;
5949 DEMANGLE_NAMESPACE_END
5951 #ifdef _LIBCXXABI_COMPILER_CLANG
5952 #pragma clang diagnostic pop
5955 #endif // DEMANGLE_ITANIUMDEMANGLE_H