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>
31 #include <string_view>
32 #include <type_traits>
35 #ifdef _LIBCXXABI_COMPILER_CLANG
36 #pragma clang diagnostic push
37 #pragma clang diagnostic ignored "-Wunused-template"
40 DEMANGLE_NAMESPACE_BEGIN
42 template <class T
, size_t N
> class PODSmallVector
{
43 static_assert(std::is_pod
<T
>::value
,
44 "T is required to be a plain old data type");
51 bool isInline() const { return First
== Inline
; }
59 void reserve(size_t NewCap
) {
62 auto *Tmp
= static_cast<T
*>(std::malloc(NewCap
* sizeof(T
)));
65 std::copy(First
, Last
, Tmp
);
68 First
= static_cast<T
*>(std::realloc(First
, NewCap
* sizeof(T
)));
77 PODSmallVector() : First(Inline
), Last(First
), Cap(Inline
+ N
) {}
79 PODSmallVector(const PODSmallVector
&) = delete;
80 PODSmallVector
&operator=(const PODSmallVector
&) = delete;
82 PODSmallVector(PODSmallVector
&&Other
) : PODSmallVector() {
83 if (Other
.isInline()) {
84 std::copy(Other
.begin(), Other
.end(), First
);
85 Last
= First
+ Other
.size();
96 PODSmallVector
&operator=(PODSmallVector
&&Other
) {
97 if (Other
.isInline()) {
102 std::copy(Other
.begin(), Other
.end(), First
);
103 Last
= First
+ Other
.size();
116 std::swap(First
, Other
.First
);
117 std::swap(Last
, Other
.Last
);
118 std::swap(Cap
, Other
.Cap
);
123 // NOLINTNEXTLINE(readability-identifier-naming)
124 void push_back(const T
&Elem
) {
130 // NOLINTNEXTLINE(readability-identifier-naming)
132 assert(Last
!= First
&& "Popping empty vector!");
136 void shrinkToSize(size_t Index
) {
137 assert(Index
<= size() && "shrinkToSize() can't expand!");
138 Last
= First
+ Index
;
141 T
*begin() { return First
; }
142 T
*end() { return Last
; }
144 bool empty() const { return First
== Last
; }
145 size_t size() const { return static_cast<size_t>(Last
- First
); }
147 assert(Last
!= First
&& "Calling back() on empty vector!");
150 T
&operator[](size_t Index
) {
151 assert(Index
< size() && "Invalid access!");
152 return *(begin() + Index
);
154 void clear() { Last
= First
; }
162 // Base class of all AST nodes. The AST is built by the parser, then is
163 // traversed by the printLeft/Right functions to produce a demangled string.
166 enum Kind
: unsigned char {
167 #define NODE(NodeKind) K##NodeKind,
168 #include "ItaniumNodes.def"
171 /// Three-way bool to track a cached value. Unknown is possible if this node
172 /// has an unexpanded parameter pack below it that may affect this cache.
173 enum class Cache
: unsigned char { Yes
, No
, Unknown
, };
175 /// Operator precedence for expression nodes. Used to determine required
176 /// parens in expression emission.
205 // FIXME: Make these protected.
207 /// Tracks if this node has a component on its right side, in which case we
208 /// need to call printRight.
209 Cache RHSComponentCache
: 2;
211 /// Track if this node is a (possibly qualified) array type. This can affect
212 /// how we format the output string.
213 Cache ArrayCache
: 2;
215 /// Track if this node is a (possibly qualified) function type. This can
216 /// affect how we format the output string.
217 Cache FunctionCache
: 2;
220 Node(Kind K_
, Prec Precedence_
= Prec::Primary
,
221 Cache RHSComponentCache_
= Cache::No
, Cache ArrayCache_
= Cache::No
,
222 Cache FunctionCache_
= Cache::No
)
223 : K(K_
), Precedence(Precedence_
), RHSComponentCache(RHSComponentCache_
),
224 ArrayCache(ArrayCache_
), FunctionCache(FunctionCache_
) {}
225 Node(Kind K_
, Cache RHSComponentCache_
, Cache ArrayCache_
= Cache::No
,
226 Cache FunctionCache_
= Cache::No
)
227 : Node(K_
, Prec::Primary
, RHSComponentCache_
, ArrayCache_
,
230 /// Visit the most-derived object corresponding to this object.
231 template<typename Fn
> void visit(Fn F
) const;
233 // The following function is provided by all derived classes:
235 // Call F with arguments that, when passed to the constructor of this node,
236 // would construct an equivalent node.
237 //template<typename Fn> void match(Fn F) const;
239 bool hasRHSComponent(OutputBuffer
&OB
) const {
240 if (RHSComponentCache
!= Cache::Unknown
)
241 return RHSComponentCache
== Cache::Yes
;
242 return hasRHSComponentSlow(OB
);
245 bool hasArray(OutputBuffer
&OB
) const {
246 if (ArrayCache
!= Cache::Unknown
)
247 return ArrayCache
== Cache::Yes
;
248 return hasArraySlow(OB
);
251 bool hasFunction(OutputBuffer
&OB
) const {
252 if (FunctionCache
!= Cache::Unknown
)
253 return FunctionCache
== Cache::Yes
;
254 return hasFunctionSlow(OB
);
257 Kind
getKind() const { return K
; }
259 Prec
getPrecedence() const { return Precedence
; }
261 virtual bool hasRHSComponentSlow(OutputBuffer
&) const { return false; }
262 virtual bool hasArraySlow(OutputBuffer
&) const { return false; }
263 virtual bool hasFunctionSlow(OutputBuffer
&) const { return false; }
265 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
266 // get at a node that actually represents some concrete syntax.
267 virtual const Node
*getSyntaxNode(OutputBuffer
&) const { return this; }
269 // Print this node as an expression operand, surrounding it in parentheses if
270 // its precedence is [Strictly] weaker than P.
271 void printAsOperand(OutputBuffer
&OB
, Prec P
= Prec::Default
,
272 bool StrictlyWorse
= false) const {
274 unsigned(getPrecedence()) >= unsigned(P
) + unsigned(StrictlyWorse
);
282 void print(OutputBuffer
&OB
) const {
284 if (RHSComponentCache
!= Cache::No
)
288 // Print the "left" side of this Node into OutputBuffer.
289 virtual void printLeft(OutputBuffer
&) const = 0;
291 // Print the "right". This distinction is necessary to represent C++ types
292 // that appear on the RHS of their subtype, such as arrays or functions.
293 // Since most types don't have such a component, provide a default
295 virtual void printRight(OutputBuffer
&) const {}
297 virtual std::string_view
getBaseName() const { return {}; }
299 // Silence compiler warnings, this dtor will never be called.
300 virtual ~Node() = default;
303 DEMANGLE_DUMP_METHOD
void dump() const;
312 NodeArray() : Elements(nullptr), NumElements(0) {}
313 NodeArray(Node
**Elements_
, size_t NumElements_
)
314 : Elements(Elements_
), NumElements(NumElements_
) {}
316 bool empty() const { return NumElements
== 0; }
317 size_t size() const { return NumElements
; }
319 Node
**begin() const { return Elements
; }
320 Node
**end() const { return Elements
+ NumElements
; }
322 Node
*operator[](size_t Idx
) const { return Elements
[Idx
]; }
324 void printWithComma(OutputBuffer
&OB
) const {
325 bool FirstElement
= true;
326 for (size_t Idx
= 0; Idx
!= NumElements
; ++Idx
) {
327 size_t BeforeComma
= OB
.getCurrentPosition();
330 size_t AfterComma
= OB
.getCurrentPosition();
331 Elements
[Idx
]->printAsOperand(OB
, Node::Prec::Comma
);
333 // Elements[Idx] is an empty parameter pack expansion, we should erase the
334 // comma we just printed.
335 if (AfterComma
== OB
.getCurrentPosition()) {
336 OB
.setCurrentPosition(BeforeComma
);
340 FirstElement
= false;
345 struct NodeArrayNode
: Node
{
347 NodeArrayNode(NodeArray Array_
) : Node(KNodeArrayNode
), Array(Array_
) {}
349 template<typename Fn
> void match(Fn F
) const { F(Array
); }
351 void printLeft(OutputBuffer
&OB
) const override
{ Array
.printWithComma(OB
); }
354 class DotSuffix final
: public Node
{
356 const std::string_view Suffix
;
359 DotSuffix(const Node
*Prefix_
, std::string_view Suffix_
)
360 : Node(KDotSuffix
), Prefix(Prefix_
), Suffix(Suffix_
) {}
362 template<typename Fn
> void match(Fn F
) const { F(Prefix
, Suffix
); }
364 void printLeft(OutputBuffer
&OB
) const override
{
372 class VendorExtQualType final
: public Node
{
374 std::string_view Ext
;
378 VendorExtQualType(const Node
*Ty_
, std::string_view Ext_
, const Node
*TA_
)
379 : Node(KVendorExtQualType
), Ty(Ty_
), Ext(Ext_
), TA(TA_
) {}
381 const Node
*getTy() const { return Ty
; }
382 std::string_view
getExt() const { return Ext
; }
383 const Node
*getTA() const { return TA
; }
385 template <typename Fn
> void match(Fn F
) const { F(Ty
, Ext
, TA
); }
387 void printLeft(OutputBuffer
&OB
) const override
{
396 enum FunctionRefQual
: unsigned char {
409 inline Qualifiers
operator|=(Qualifiers
&Q1
, Qualifiers Q2
) {
410 return Q1
= static_cast<Qualifiers
>(Q1
| Q2
);
413 class QualType final
: public Node
{
415 const Qualifiers Quals
;
418 void printQuals(OutputBuffer
&OB
) const {
419 if (Quals
& QualConst
)
421 if (Quals
& QualVolatile
)
423 if (Quals
& QualRestrict
)
428 QualType(const Node
*Child_
, Qualifiers Quals_
)
429 : Node(KQualType
, Child_
->RHSComponentCache
,
430 Child_
->ArrayCache
, Child_
->FunctionCache
),
431 Quals(Quals_
), Child(Child_
) {}
433 Qualifiers
getQuals() const { return Quals
; }
434 const Node
*getChild() const { return Child
; }
436 template<typename Fn
> void match(Fn F
) const { F(Child
, Quals
); }
438 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
439 return Child
->hasRHSComponent(OB
);
441 bool hasArraySlow(OutputBuffer
&OB
) const override
{
442 return Child
->hasArray(OB
);
444 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
445 return Child
->hasFunction(OB
);
448 void printLeft(OutputBuffer
&OB
) const override
{
449 Child
->printLeft(OB
);
453 void printRight(OutputBuffer
&OB
) const override
{ Child
->printRight(OB
); }
456 class ConversionOperatorType final
: public Node
{
460 ConversionOperatorType(const Node
*Ty_
)
461 : Node(KConversionOperatorType
), Ty(Ty_
) {}
463 template<typename Fn
> void match(Fn F
) const { F(Ty
); }
465 void printLeft(OutputBuffer
&OB
) const override
{
471 class PostfixQualifiedType final
: public Node
{
473 const std::string_view Postfix
;
476 PostfixQualifiedType(const Node
*Ty_
, std::string_view Postfix_
)
477 : Node(KPostfixQualifiedType
), Ty(Ty_
), Postfix(Postfix_
) {}
479 template<typename Fn
> void match(Fn F
) const { F(Ty
, Postfix
); }
481 void printLeft(OutputBuffer
&OB
) const override
{
487 class NameType final
: public Node
{
488 const std::string_view Name
;
491 NameType(std::string_view Name_
) : Node(KNameType
), Name(Name_
) {}
493 template<typename Fn
> void match(Fn F
) const { F(Name
); }
495 std::string_view
getName() const { return Name
; }
496 std::string_view
getBaseName() const override
{ return Name
; }
498 void printLeft(OutputBuffer
&OB
) const override
{ OB
+= Name
; }
501 class BitIntType final
: public Node
{
506 BitIntType(const Node
*Size_
, bool Signed_
)
507 : Node(KBitIntType
), Size(Size_
), Signed(Signed_
) {}
509 template <typename Fn
> void match(Fn F
) const { F(Size
, Signed
); }
511 void printLeft(OutputBuffer
&OB
) const override
{
516 Size
->printAsOperand(OB
);
521 class ElaboratedTypeSpefType
: public Node
{
522 std::string_view Kind
;
525 ElaboratedTypeSpefType(std::string_view Kind_
, Node
*Child_
)
526 : Node(KElaboratedTypeSpefType
), Kind(Kind_
), Child(Child_
) {}
528 template<typename Fn
> void match(Fn F
) const { F(Kind
, Child
); }
530 void printLeft(OutputBuffer
&OB
) const override
{
537 class TransformedType
: public Node
{
538 std::string_view Transform
;
541 TransformedType(std::string_view Transform_
, Node
*BaseType_
)
542 : Node(KTransformedType
), Transform(Transform_
), BaseType(BaseType_
) {}
544 template<typename Fn
> void match(Fn F
) const { F(Transform
, BaseType
); }
546 void printLeft(OutputBuffer
&OB
) const override
{
554 struct AbiTagAttr
: Node
{
556 std::string_view Tag
;
558 AbiTagAttr(Node
*Base_
, std::string_view Tag_
)
559 : Node(KAbiTagAttr
, Base_
->RHSComponentCache
, Base_
->ArrayCache
,
560 Base_
->FunctionCache
),
561 Base(Base_
), Tag(Tag_
) {}
563 template<typename Fn
> void match(Fn F
) const { F(Base
, Tag
); }
565 std::string_view
getBaseName() const override
{ return Base
->getBaseName(); }
567 void printLeft(OutputBuffer
&OB
) const override
{
575 class EnableIfAttr
: public Node
{
576 NodeArray Conditions
;
578 EnableIfAttr(NodeArray Conditions_
)
579 : Node(KEnableIfAttr
), Conditions(Conditions_
) {}
581 template<typename Fn
> void match(Fn F
) const { F(Conditions
); }
583 void printLeft(OutputBuffer
&OB
) const override
{
584 OB
+= " [enable_if:";
585 Conditions
.printWithComma(OB
);
590 class ObjCProtoName
: public Node
{
592 std::string_view Protocol
;
594 friend class PointerType
;
597 ObjCProtoName(const Node
*Ty_
, std::string_view Protocol_
)
598 : Node(KObjCProtoName
), Ty(Ty_
), Protocol(Protocol_
) {}
600 template<typename Fn
> void match(Fn F
) const { F(Ty
, Protocol
); }
602 bool isObjCObject() const {
603 return Ty
->getKind() == KNameType
&&
604 static_cast<const NameType
*>(Ty
)->getName() == "objc_object";
607 void printLeft(OutputBuffer
&OB
) const override
{
615 class PointerType final
: public Node
{
619 PointerType(const Node
*Pointee_
)
620 : Node(KPointerType
, Pointee_
->RHSComponentCache
),
623 const Node
*getPointee() const { return Pointee
; }
625 template<typename Fn
> void match(Fn F
) const { F(Pointee
); }
627 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
628 return Pointee
->hasRHSComponent(OB
);
631 void printLeft(OutputBuffer
&OB
) const override
{
632 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
633 if (Pointee
->getKind() != KObjCProtoName
||
634 !static_cast<const ObjCProtoName
*>(Pointee
)->isObjCObject()) {
635 Pointee
->printLeft(OB
);
636 if (Pointee
->hasArray(OB
))
638 if (Pointee
->hasArray(OB
) || Pointee
->hasFunction(OB
))
642 const auto *objcProto
= static_cast<const ObjCProtoName
*>(Pointee
);
644 OB
+= objcProto
->Protocol
;
649 void printRight(OutputBuffer
&OB
) const override
{
650 if (Pointee
->getKind() != KObjCProtoName
||
651 !static_cast<const ObjCProtoName
*>(Pointee
)->isObjCObject()) {
652 if (Pointee
->hasArray(OB
) || Pointee
->hasFunction(OB
))
654 Pointee
->printRight(OB
);
659 enum class ReferenceKind
{
664 // Represents either a LValue or an RValue reference type.
665 class ReferenceType
: public Node
{
669 mutable bool Printing
= false;
671 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
672 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
673 // other combination collapses to a lvalue ref.
675 // A combination of a TemplateForwardReference and a back-ref Substitution
676 // from an ill-formed string may have created a cycle; use cycle detection to
677 // avoid looping forever.
678 std::pair
<ReferenceKind
, const Node
*> collapse(OutputBuffer
&OB
) const {
679 auto SoFar
= std::make_pair(RK
, Pointee
);
680 // Track the chain of nodes for the Floyd's 'tortoise and hare'
681 // cycle-detection algorithm, since getSyntaxNode(S) is impure
682 PODSmallVector
<const Node
*, 8> Prev
;
684 const Node
*SN
= SoFar
.second
->getSyntaxNode(OB
);
685 if (SN
->getKind() != KReferenceType
)
687 auto *RT
= static_cast<const ReferenceType
*>(SN
);
688 SoFar
.second
= RT
->Pointee
;
689 SoFar
.first
= std::min(SoFar
.first
, RT
->RK
);
691 // The middle of Prev is the 'slow' pointer moving at half speed
692 Prev
.push_back(SoFar
.second
);
693 if (Prev
.size() > 1 && SoFar
.second
== Prev
[(Prev
.size() - 1) / 2]) {
695 SoFar
.second
= nullptr;
703 ReferenceType(const Node
*Pointee_
, ReferenceKind RK_
)
704 : Node(KReferenceType
, Pointee_
->RHSComponentCache
),
705 Pointee(Pointee_
), RK(RK_
) {}
707 template<typename Fn
> void match(Fn F
) const { F(Pointee
, RK
); }
709 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
710 return Pointee
->hasRHSComponent(OB
);
713 void printLeft(OutputBuffer
&OB
) const override
{
716 ScopedOverride
<bool> SavePrinting(Printing
, true);
717 std::pair
<ReferenceKind
, const Node
*> Collapsed
= collapse(OB
);
718 if (!Collapsed
.second
)
720 Collapsed
.second
->printLeft(OB
);
721 if (Collapsed
.second
->hasArray(OB
))
723 if (Collapsed
.second
->hasArray(OB
) || Collapsed
.second
->hasFunction(OB
))
726 OB
+= (Collapsed
.first
== ReferenceKind::LValue
? "&" : "&&");
728 void printRight(OutputBuffer
&OB
) const override
{
731 ScopedOverride
<bool> SavePrinting(Printing
, true);
732 std::pair
<ReferenceKind
, const Node
*> Collapsed
= collapse(OB
);
733 if (!Collapsed
.second
)
735 if (Collapsed
.second
->hasArray(OB
) || Collapsed
.second
->hasFunction(OB
))
737 Collapsed
.second
->printRight(OB
);
741 class PointerToMemberType final
: public Node
{
742 const Node
*ClassType
;
743 const Node
*MemberType
;
746 PointerToMemberType(const Node
*ClassType_
, const Node
*MemberType_
)
747 : Node(KPointerToMemberType
, MemberType_
->RHSComponentCache
),
748 ClassType(ClassType_
), MemberType(MemberType_
) {}
750 template<typename Fn
> void match(Fn F
) const { F(ClassType
, MemberType
); }
752 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
753 return MemberType
->hasRHSComponent(OB
);
756 void printLeft(OutputBuffer
&OB
) const override
{
757 MemberType
->printLeft(OB
);
758 if (MemberType
->hasArray(OB
) || MemberType
->hasFunction(OB
))
762 ClassType
->print(OB
);
766 void printRight(OutputBuffer
&OB
) const override
{
767 if (MemberType
->hasArray(OB
) || MemberType
->hasFunction(OB
))
769 MemberType
->printRight(OB
);
773 class ArrayType final
: public Node
{
778 ArrayType(const Node
*Base_
, Node
*Dimension_
)
780 /*RHSComponentCache=*/Cache::Yes
,
781 /*ArrayCache=*/Cache::Yes
),
782 Base(Base_
), Dimension(Dimension_
) {}
784 template<typename Fn
> void match(Fn F
) const { F(Base
, Dimension
); }
786 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
787 bool hasArraySlow(OutputBuffer
&) const override
{ return true; }
789 void printLeft(OutputBuffer
&OB
) const override
{ Base
->printLeft(OB
); }
791 void printRight(OutputBuffer
&OB
) const override
{
792 if (OB
.back() != ']')
796 Dimension
->print(OB
);
798 Base
->printRight(OB
);
802 class FunctionType final
: public Node
{
806 FunctionRefQual RefQual
;
807 const Node
*ExceptionSpec
;
810 FunctionType(const Node
*Ret_
, NodeArray Params_
, Qualifiers CVQuals_
,
811 FunctionRefQual RefQual_
, const Node
*ExceptionSpec_
)
812 : Node(KFunctionType
,
813 /*RHSComponentCache=*/Cache::Yes
, /*ArrayCache=*/Cache::No
,
814 /*FunctionCache=*/Cache::Yes
),
815 Ret(Ret_
), Params(Params_
), CVQuals(CVQuals_
), RefQual(RefQual_
),
816 ExceptionSpec(ExceptionSpec_
) {}
818 template<typename Fn
> void match(Fn F
) const {
819 F(Ret
, Params
, CVQuals
, RefQual
, ExceptionSpec
);
822 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
823 bool hasFunctionSlow(OutputBuffer
&) const override
{ return true; }
825 // Handle C++'s ... quirky decl grammar by using the left & right
826 // distinction. Consider:
827 // int (*f(float))(char) {}
828 // f is a function that takes a float and returns a pointer to a function
829 // that takes a char and returns an int. If we're trying to print f, start
830 // by printing out the return types's left, then print our parameters, then
831 // finally print right of the return type.
832 void printLeft(OutputBuffer
&OB
) const override
{
837 void printRight(OutputBuffer
&OB
) const override
{
839 Params
.printWithComma(OB
);
843 if (CVQuals
& QualConst
)
845 if (CVQuals
& QualVolatile
)
847 if (CVQuals
& QualRestrict
)
850 if (RefQual
== FrefQualLValue
)
852 else if (RefQual
== FrefQualRValue
)
855 if (ExceptionSpec
!= nullptr) {
857 ExceptionSpec
->print(OB
);
862 class NoexceptSpec
: public Node
{
865 NoexceptSpec(const Node
*E_
) : Node(KNoexceptSpec
), E(E_
) {}
867 template<typename Fn
> void match(Fn F
) const { F(E
); }
869 void printLeft(OutputBuffer
&OB
) const override
{
872 E
->printAsOperand(OB
);
877 class DynamicExceptionSpec
: public Node
{
880 DynamicExceptionSpec(NodeArray Types_
)
881 : Node(KDynamicExceptionSpec
), Types(Types_
) {}
883 template<typename Fn
> void match(Fn F
) const { F(Types
); }
885 void printLeft(OutputBuffer
&OB
) const override
{
888 Types
.printWithComma(OB
);
893 class FunctionEncoding final
: public Node
{
898 const Node
*Requires
;
900 FunctionRefQual RefQual
;
903 FunctionEncoding(const Node
*Ret_
, const Node
*Name_
, NodeArray Params_
,
904 const Node
*Attrs_
, const Node
*Requires_
,
905 Qualifiers CVQuals_
, FunctionRefQual RefQual_
)
906 : Node(KFunctionEncoding
,
907 /*RHSComponentCache=*/Cache::Yes
, /*ArrayCache=*/Cache::No
,
908 /*FunctionCache=*/Cache::Yes
),
909 Ret(Ret_
), Name(Name_
), Params(Params_
), Attrs(Attrs_
),
910 Requires(Requires_
), CVQuals(CVQuals_
), RefQual(RefQual_
) {}
912 template<typename Fn
> void match(Fn F
) const {
913 F(Ret
, Name
, Params
, Attrs
, Requires
, CVQuals
, RefQual
);
916 Qualifiers
getCVQuals() const { return CVQuals
; }
917 FunctionRefQual
getRefQual() const { return RefQual
; }
918 NodeArray
getParams() const { return Params
; }
919 const Node
*getReturnType() const { return Ret
; }
921 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
922 bool hasFunctionSlow(OutputBuffer
&) const override
{ return true; }
924 const Node
*getName() const { return Name
; }
926 void printLeft(OutputBuffer
&OB
) const override
{
929 if (!Ret
->hasRHSComponent(OB
))
935 void printRight(OutputBuffer
&OB
) const override
{
937 Params
.printWithComma(OB
);
942 if (CVQuals
& QualConst
)
944 if (CVQuals
& QualVolatile
)
946 if (CVQuals
& QualRestrict
)
949 if (RefQual
== FrefQualLValue
)
951 else if (RefQual
== FrefQualRValue
)
954 if (Attrs
!= nullptr)
957 if (Requires
!= nullptr) {
964 class LiteralOperator
: public Node
{
968 LiteralOperator(const Node
*OpName_
)
969 : Node(KLiteralOperator
), OpName(OpName_
) {}
971 template<typename Fn
> void match(Fn F
) const { F(OpName
); }
973 void printLeft(OutputBuffer
&OB
) const override
{
974 OB
+= "operator\"\" ";
979 class SpecialName final
: public Node
{
980 const std::string_view Special
;
984 SpecialName(std::string_view Special_
, const Node
*Child_
)
985 : Node(KSpecialName
), Special(Special_
), Child(Child_
) {}
987 template<typename Fn
> void match(Fn F
) const { F(Special
, Child
); }
989 void printLeft(OutputBuffer
&OB
) const override
{
995 class CtorVtableSpecialName final
: public Node
{
996 const Node
*FirstType
;
997 const Node
*SecondType
;
1000 CtorVtableSpecialName(const Node
*FirstType_
, const Node
*SecondType_
)
1001 : Node(KCtorVtableSpecialName
),
1002 FirstType(FirstType_
), SecondType(SecondType_
) {}
1004 template<typename Fn
> void match(Fn F
) const { F(FirstType
, SecondType
); }
1006 void printLeft(OutputBuffer
&OB
) const override
{
1007 OB
+= "construction vtable for ";
1008 FirstType
->print(OB
);
1010 SecondType
->print(OB
);
1014 struct NestedName
: Node
{
1018 NestedName(Node
*Qual_
, Node
*Name_
)
1019 : Node(KNestedName
), Qual(Qual_
), Name(Name_
) {}
1021 template<typename Fn
> void match(Fn F
) const { F(Qual
, Name
); }
1023 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1025 void printLeft(OutputBuffer
&OB
) const override
{
1032 struct MemberLikeFriendName
: Node
{
1036 MemberLikeFriendName(Node
*Qual_
, Node
*Name_
)
1037 : Node(KMemberLikeFriendName
), Qual(Qual_
), Name(Name_
) {}
1039 template<typename Fn
> void match(Fn F
) const { F(Qual
, Name
); }
1041 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1043 void printLeft(OutputBuffer
&OB
) const override
{
1050 struct ModuleName
: Node
{
1055 ModuleName(ModuleName
*Parent_
, Node
*Name_
, bool IsPartition_
= false)
1056 : Node(KModuleName
), Parent(Parent_
), Name(Name_
),
1057 IsPartition(IsPartition_
) {}
1059 template <typename Fn
> void match(Fn F
) const {
1060 F(Parent
, Name
, IsPartition
);
1063 void printLeft(OutputBuffer
&OB
) const override
{
1066 if (Parent
|| IsPartition
)
1067 OB
+= IsPartition
? ':' : '.';
1072 struct ModuleEntity
: Node
{
1076 ModuleEntity(ModuleName
*Module_
, Node
*Name_
)
1077 : Node(KModuleEntity
), Module(Module_
), Name(Name_
) {}
1079 template <typename Fn
> void match(Fn F
) const { F(Module
, Name
); }
1081 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1083 void printLeft(OutputBuffer
&OB
) const override
{
1090 struct LocalName
: Node
{
1094 LocalName(Node
*Encoding_
, Node
*Entity_
)
1095 : Node(KLocalName
), Encoding(Encoding_
), Entity(Entity_
) {}
1097 template<typename Fn
> void match(Fn F
) const { F(Encoding
, Entity
); }
1099 void printLeft(OutputBuffer
&OB
) const override
{
1100 Encoding
->print(OB
);
1106 class QualifiedName final
: public Node
{
1108 const Node
*Qualifier
;
1112 QualifiedName(const Node
*Qualifier_
, const Node
*Name_
)
1113 : Node(KQualifiedName
), Qualifier(Qualifier_
), Name(Name_
) {}
1115 template<typename Fn
> void match(Fn F
) const { F(Qualifier
, Name
); }
1117 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1119 void printLeft(OutputBuffer
&OB
) const override
{
1120 Qualifier
->print(OB
);
1126 class VectorType final
: public Node
{
1127 const Node
*BaseType
;
1128 const Node
*Dimension
;
1131 VectorType(const Node
*BaseType_
, const Node
*Dimension_
)
1132 : Node(KVectorType
), BaseType(BaseType_
), Dimension(Dimension_
) {}
1134 const Node
*getBaseType() const { return BaseType
; }
1135 const Node
*getDimension() const { return Dimension
; }
1137 template<typename Fn
> void match(Fn F
) const { F(BaseType
, Dimension
); }
1139 void printLeft(OutputBuffer
&OB
) const override
{
1140 BaseType
->print(OB
);
1143 Dimension
->print(OB
);
1148 class PixelVectorType final
: public Node
{
1149 const Node
*Dimension
;
1152 PixelVectorType(const Node
*Dimension_
)
1153 : Node(KPixelVectorType
), Dimension(Dimension_
) {}
1155 template<typename Fn
> void match(Fn F
) const { F(Dimension
); }
1157 void printLeft(OutputBuffer
&OB
) const override
{
1158 // FIXME: This should demangle as "vector pixel".
1159 OB
+= "pixel vector[";
1160 Dimension
->print(OB
);
1165 class BinaryFPType final
: public Node
{
1166 const Node
*Dimension
;
1169 BinaryFPType(const Node
*Dimension_
)
1170 : Node(KBinaryFPType
), Dimension(Dimension_
) {}
1172 template<typename Fn
> void match(Fn F
) const { F(Dimension
); }
1174 void printLeft(OutputBuffer
&OB
) const override
{
1176 Dimension
->print(OB
);
1180 enum class TemplateParamKind
{ Type
, NonType
, Template
};
1182 /// An invented name for a template parameter for which we don't have a
1183 /// corresponding template argument.
1185 /// This node is created when parsing the <lambda-sig> for a lambda with
1186 /// explicit template arguments, which might be referenced in the parameter
1187 /// types appearing later in the <lambda-sig>.
1188 class SyntheticTemplateParamName final
: public Node
{
1189 TemplateParamKind Kind
;
1193 SyntheticTemplateParamName(TemplateParamKind Kind_
, unsigned Index_
)
1194 : Node(KSyntheticTemplateParamName
), Kind(Kind_
), Index(Index_
) {}
1196 template<typename Fn
> void match(Fn F
) const { F(Kind
, Index
); }
1198 void printLeft(OutputBuffer
&OB
) const override
{
1200 case TemplateParamKind::Type
:
1203 case TemplateParamKind::NonType
:
1206 case TemplateParamKind::Template
:
1215 class TemplateParamQualifiedArg final
: public Node
{
1220 TemplateParamQualifiedArg(Node
*Param_
, Node
*Arg_
)
1221 : Node(KTemplateParamQualifiedArg
), Param(Param_
), Arg(Arg_
) {}
1223 template <typename Fn
> void match(Fn F
) const { F(Param
, Arg
); }
1225 Node
*getArg() { return Arg
; }
1227 void printLeft(OutputBuffer
&OB
) const override
{
1228 // Don't print Param to keep the output consistent.
1233 /// A template type parameter declaration, 'typename T'.
1234 class TypeTemplateParamDecl final
: public Node
{
1238 TypeTemplateParamDecl(Node
*Name_
)
1239 : Node(KTypeTemplateParamDecl
, Cache::Yes
), Name(Name_
) {}
1241 template<typename Fn
> void match(Fn F
) const { F(Name
); }
1243 void printLeft(OutputBuffer
&OB
) const override
{ OB
+= "typename "; }
1245 void printRight(OutputBuffer
&OB
) const override
{ Name
->print(OB
); }
1248 /// A constrained template type parameter declaration, 'C<U> T'.
1249 class ConstrainedTypeTemplateParamDecl final
: public Node
{
1254 ConstrainedTypeTemplateParamDecl(Node
*Constraint_
, Node
*Name_
)
1255 : Node(KConstrainedTypeTemplateParamDecl
, Cache::Yes
),
1256 Constraint(Constraint_
), Name(Name_
) {}
1258 template<typename Fn
> void match(Fn F
) const { F(Constraint
, Name
); }
1260 void printLeft(OutputBuffer
&OB
) const override
{
1261 Constraint
->print(OB
);
1265 void printRight(OutputBuffer
&OB
) const override
{ Name
->print(OB
); }
1268 /// A non-type template parameter declaration, 'int N'.
1269 class NonTypeTemplateParamDecl final
: public Node
{
1274 NonTypeTemplateParamDecl(Node
*Name_
, Node
*Type_
)
1275 : Node(KNonTypeTemplateParamDecl
, Cache::Yes
), Name(Name_
), Type(Type_
) {}
1277 template<typename Fn
> void match(Fn F
) const { F(Name
, Type
); }
1279 void printLeft(OutputBuffer
&OB
) const override
{
1280 Type
->printLeft(OB
);
1281 if (!Type
->hasRHSComponent(OB
))
1285 void printRight(OutputBuffer
&OB
) const override
{
1287 Type
->printRight(OB
);
1291 /// A template template parameter declaration,
1292 /// 'template<typename T> typename N'.
1293 class TemplateTemplateParamDecl final
: public Node
{
1299 TemplateTemplateParamDecl(Node
*Name_
, NodeArray Params_
, Node
*Requires_
)
1300 : Node(KTemplateTemplateParamDecl
, Cache::Yes
), Name(Name_
),
1301 Params(Params_
), Requires(Requires_
) {}
1303 template <typename Fn
> void match(Fn F
) const { F(Name
, Params
, Requires
); }
1305 void printLeft(OutputBuffer
&OB
) const override
{
1306 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1308 Params
.printWithComma(OB
);
1309 OB
+= "> typename ";
1312 void printRight(OutputBuffer
&OB
) const override
{
1314 if (Requires
!= nullptr) {
1316 Requires
->print(OB
);
1321 /// A template parameter pack declaration, 'typename ...T'.
1322 class TemplateParamPackDecl final
: public Node
{
1326 TemplateParamPackDecl(Node
*Param_
)
1327 : Node(KTemplateParamPackDecl
, Cache::Yes
), Param(Param_
) {}
1329 template<typename Fn
> void match(Fn F
) const { F(Param
); }
1331 void printLeft(OutputBuffer
&OB
) const override
{
1332 Param
->printLeft(OB
);
1336 void printRight(OutputBuffer
&OB
) const override
{ Param
->printRight(OB
); }
1339 /// An unexpanded parameter pack (either in the expression or type context). If
1340 /// this AST is correct, this node will have a ParameterPackExpansion node above
1343 /// This node is created when some <template-args> are found that apply to an
1344 /// <encoding>, and is stored in the TemplateParams table. In order for this to
1345 /// appear in the final AST, it has to referenced via a <template-param> (ie,
1347 class ParameterPack final
: public Node
{
1350 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1352 void initializePackExpansion(OutputBuffer
&OB
) const {
1353 if (OB
.CurrentPackMax
== std::numeric_limits
<unsigned>::max()) {
1354 OB
.CurrentPackMax
= static_cast<unsigned>(Data
.size());
1355 OB
.CurrentPackIndex
= 0;
1360 ParameterPack(NodeArray Data_
) : Node(KParameterPack
), Data(Data_
) {
1361 ArrayCache
= FunctionCache
= RHSComponentCache
= Cache::Unknown
;
1362 if (std::all_of(Data
.begin(), Data
.end(), [](Node
* P
) {
1363 return P
->ArrayCache
== Cache::No
;
1365 ArrayCache
= Cache::No
;
1366 if (std::all_of(Data
.begin(), Data
.end(), [](Node
* P
) {
1367 return P
->FunctionCache
== Cache::No
;
1369 FunctionCache
= Cache::No
;
1370 if (std::all_of(Data
.begin(), Data
.end(), [](Node
* P
) {
1371 return P
->RHSComponentCache
== Cache::No
;
1373 RHSComponentCache
= Cache::No
;
1376 template<typename Fn
> void match(Fn F
) const { F(Data
); }
1378 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
1379 initializePackExpansion(OB
);
1380 size_t Idx
= OB
.CurrentPackIndex
;
1381 return Idx
< Data
.size() && Data
[Idx
]->hasRHSComponent(OB
);
1383 bool hasArraySlow(OutputBuffer
&OB
) const override
{
1384 initializePackExpansion(OB
);
1385 size_t Idx
= OB
.CurrentPackIndex
;
1386 return Idx
< Data
.size() && Data
[Idx
]->hasArray(OB
);
1388 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
1389 initializePackExpansion(OB
);
1390 size_t Idx
= OB
.CurrentPackIndex
;
1391 return Idx
< Data
.size() && Data
[Idx
]->hasFunction(OB
);
1393 const Node
*getSyntaxNode(OutputBuffer
&OB
) const override
{
1394 initializePackExpansion(OB
);
1395 size_t Idx
= OB
.CurrentPackIndex
;
1396 return Idx
< Data
.size() ? Data
[Idx
]->getSyntaxNode(OB
) : this;
1399 void printLeft(OutputBuffer
&OB
) const override
{
1400 initializePackExpansion(OB
);
1401 size_t Idx
= OB
.CurrentPackIndex
;
1402 if (Idx
< Data
.size())
1403 Data
[Idx
]->printLeft(OB
);
1405 void printRight(OutputBuffer
&OB
) const override
{
1406 initializePackExpansion(OB
);
1407 size_t Idx
= OB
.CurrentPackIndex
;
1408 if (Idx
< Data
.size())
1409 Data
[Idx
]->printRight(OB
);
1413 /// A variadic template argument. This node represents an occurrence of
1414 /// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1415 /// one of its Elements is. The parser inserts a ParameterPack into the
1416 /// TemplateParams table if the <template-args> this pack belongs to apply to an
1418 class TemplateArgumentPack final
: public Node
{
1421 TemplateArgumentPack(NodeArray Elements_
)
1422 : Node(KTemplateArgumentPack
), Elements(Elements_
) {}
1424 template<typename Fn
> void match(Fn F
) const { F(Elements
); }
1426 NodeArray
getElements() const { return Elements
; }
1428 void printLeft(OutputBuffer
&OB
) const override
{
1429 Elements
.printWithComma(OB
);
1433 /// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1434 /// which each have Child->ParameterPackSize elements.
1435 class ParameterPackExpansion final
: public Node
{
1439 ParameterPackExpansion(const Node
*Child_
)
1440 : Node(KParameterPackExpansion
), Child(Child_
) {}
1442 template<typename Fn
> void match(Fn F
) const { F(Child
); }
1444 const Node
*getChild() const { return Child
; }
1446 void printLeft(OutputBuffer
&OB
) const override
{
1447 constexpr unsigned Max
= std::numeric_limits
<unsigned>::max();
1448 ScopedOverride
<unsigned> SavePackIdx(OB
.CurrentPackIndex
, Max
);
1449 ScopedOverride
<unsigned> SavePackMax(OB
.CurrentPackMax
, Max
);
1450 size_t StreamPos
= OB
.getCurrentPosition();
1452 // Print the first element in the pack. If Child contains a ParameterPack,
1453 // it will set up S.CurrentPackMax and print the first element.
1456 // No ParameterPack was found in Child. This can occur if we've found a pack
1457 // expansion on a <function-param>.
1458 if (OB
.CurrentPackMax
== Max
) {
1463 // We found a ParameterPack, but it has no elements. Erase whatever we may
1465 if (OB
.CurrentPackMax
== 0) {
1466 OB
.setCurrentPosition(StreamPos
);
1470 // Else, iterate through the rest of the elements in the pack.
1471 for (unsigned I
= 1, E
= OB
.CurrentPackMax
; I
< E
; ++I
) {
1473 OB
.CurrentPackIndex
= I
;
1479 class TemplateArgs final
: public Node
{
1484 TemplateArgs(NodeArray Params_
, Node
*Requires_
)
1485 : Node(KTemplateArgs
), Params(Params_
), Requires(Requires_
) {}
1487 template<typename Fn
> void match(Fn F
) const { F(Params
, Requires
); }
1489 NodeArray
getParams() { return Params
; }
1491 void printLeft(OutputBuffer
&OB
) const override
{
1492 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1494 Params
.printWithComma(OB
);
1496 // Don't print the requires clause to keep the output simple.
1500 /// A forward-reference to a template argument that was not known at the point
1501 /// where the template parameter name was parsed in a mangling.
1503 /// This is created when demangling the name of a specialization of a
1504 /// conversion function template:
1508 /// template<typename T> operator T*();
1512 /// When demangling a specialization of the conversion function template, we
1513 /// encounter the name of the template (including the \c T) before we reach
1514 /// the template argument list, so we cannot substitute the parameter name
1515 /// for the corresponding argument while parsing. Instead, we create a
1516 /// \c ForwardTemplateReference node that is resolved after we parse the
1517 /// template arguments.
1518 struct ForwardTemplateReference
: Node
{
1520 Node
*Ref
= nullptr;
1522 // If we're currently printing this node. It is possible (though invalid) for
1523 // a forward template reference to refer to itself via a substitution. This
1524 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1525 // out if more than one print* function is active.
1526 mutable bool Printing
= false;
1528 ForwardTemplateReference(size_t Index_
)
1529 : Node(KForwardTemplateReference
, Cache::Unknown
, Cache::Unknown
,
1533 // We don't provide a matcher for these, because the value of the node is
1534 // not determined by its construction parameters, and it generally needs
1535 // special handling.
1536 template<typename Fn
> void match(Fn F
) const = delete;
1538 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
1541 ScopedOverride
<bool> SavePrinting(Printing
, true);
1542 return Ref
->hasRHSComponent(OB
);
1544 bool hasArraySlow(OutputBuffer
&OB
) const override
{
1547 ScopedOverride
<bool> SavePrinting(Printing
, true);
1548 return Ref
->hasArray(OB
);
1550 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
1553 ScopedOverride
<bool> SavePrinting(Printing
, true);
1554 return Ref
->hasFunction(OB
);
1556 const Node
*getSyntaxNode(OutputBuffer
&OB
) const override
{
1559 ScopedOverride
<bool> SavePrinting(Printing
, true);
1560 return Ref
->getSyntaxNode(OB
);
1563 void printLeft(OutputBuffer
&OB
) const override
{
1566 ScopedOverride
<bool> SavePrinting(Printing
, true);
1569 void printRight(OutputBuffer
&OB
) const override
{
1572 ScopedOverride
<bool> SavePrinting(Printing
, true);
1573 Ref
->printRight(OB
);
1577 struct NameWithTemplateArgs
: Node
{
1578 // name<template_args>
1582 NameWithTemplateArgs(Node
*Name_
, Node
*TemplateArgs_
)
1583 : Node(KNameWithTemplateArgs
), Name(Name_
), TemplateArgs(TemplateArgs_
) {}
1585 template<typename Fn
> void match(Fn F
) const { F(Name
, TemplateArgs
); }
1587 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1589 void printLeft(OutputBuffer
&OB
) const override
{
1591 TemplateArgs
->print(OB
);
1595 class GlobalQualifiedName final
: public Node
{
1599 GlobalQualifiedName(Node
* Child_
)
1600 : Node(KGlobalQualifiedName
), Child(Child_
) {}
1602 template<typename Fn
> void match(Fn F
) const { F(Child
); }
1604 std::string_view
getBaseName() const override
{ return Child
->getBaseName(); }
1606 void printLeft(OutputBuffer
&OB
) const override
{
1612 enum class SpecialSubKind
{
1621 class SpecialSubstitution
;
1622 class ExpandedSpecialSubstitution
: public Node
{
1626 ExpandedSpecialSubstitution(SpecialSubKind SSK_
, Kind K_
)
1627 : Node(K_
), SSK(SSK_
) {}
1629 ExpandedSpecialSubstitution(SpecialSubKind SSK_
)
1630 : ExpandedSpecialSubstitution(SSK_
, KExpandedSpecialSubstitution
) {}
1631 inline ExpandedSpecialSubstitution(SpecialSubstitution
const *);
1633 template<typename Fn
> void match(Fn F
) const { F(SSK
); }
1636 bool isInstantiation() const {
1637 return unsigned(SSK
) >= unsigned(SpecialSubKind::string
);
1640 std::string_view
getBaseName() const override
{
1642 case SpecialSubKind::allocator
:
1643 return {"allocator"};
1644 case SpecialSubKind::basic_string
:
1645 return {"basic_string"};
1646 case SpecialSubKind::string
:
1647 return {"basic_string"};
1648 case SpecialSubKind::istream
:
1649 return {"basic_istream"};
1650 case SpecialSubKind::ostream
:
1651 return {"basic_ostream"};
1652 case SpecialSubKind::iostream
:
1653 return {"basic_iostream"};
1655 DEMANGLE_UNREACHABLE
;
1659 void printLeft(OutputBuffer
&OB
) const override
{
1660 OB
<< "std::" << getBaseName();
1661 if (isInstantiation()) {
1662 OB
<< "<char, std::char_traits<char>";
1663 if (SSK
== SpecialSubKind::string
)
1664 OB
<< ", std::allocator<char>";
1670 class SpecialSubstitution final
: public ExpandedSpecialSubstitution
{
1672 SpecialSubstitution(SpecialSubKind SSK_
)
1673 : ExpandedSpecialSubstitution(SSK_
, KSpecialSubstitution
) {}
1675 template<typename Fn
> void match(Fn F
) const { F(SSK
); }
1677 std::string_view
getBaseName() const override
{
1678 std::string_view SV
= ExpandedSpecialSubstitution::getBaseName();
1679 if (isInstantiation()) {
1680 // The instantiations are typedefs that drop the "basic_" prefix.
1681 assert(starts_with(SV
, "basic_"));
1682 SV
.remove_prefix(sizeof("basic_") - 1);
1687 void printLeft(OutputBuffer
&OB
) const override
{
1688 OB
<< "std::" << getBaseName();
1692 inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(
1693 SpecialSubstitution
const *SS
)
1694 : ExpandedSpecialSubstitution(SS
->SSK
) {}
1696 class CtorDtorName final
: public Node
{
1697 const Node
*Basename
;
1702 CtorDtorName(const Node
*Basename_
, bool IsDtor_
, int Variant_
)
1703 : Node(KCtorDtorName
), Basename(Basename_
), IsDtor(IsDtor_
),
1704 Variant(Variant_
) {}
1706 template<typename Fn
> void match(Fn F
) const { F(Basename
, IsDtor
, Variant
); }
1708 void printLeft(OutputBuffer
&OB
) const override
{
1711 OB
+= Basename
->getBaseName();
1715 class DtorName
: public Node
{
1719 DtorName(const Node
*Base_
) : Node(KDtorName
), Base(Base_
) {}
1721 template<typename Fn
> void match(Fn F
) const { F(Base
); }
1723 void printLeft(OutputBuffer
&OB
) const override
{
1725 Base
->printLeft(OB
);
1729 class UnnamedTypeName
: public Node
{
1730 const std::string_view Count
;
1733 UnnamedTypeName(std::string_view Count_
)
1734 : Node(KUnnamedTypeName
), Count(Count_
) {}
1736 template<typename Fn
> void match(Fn F
) const { F(Count
); }
1738 void printLeft(OutputBuffer
&OB
) const override
{
1745 class ClosureTypeName
: public Node
{
1746 NodeArray TemplateParams
;
1747 const Node
*Requires1
;
1749 const Node
*Requires2
;
1750 std::string_view Count
;
1753 ClosureTypeName(NodeArray TemplateParams_
, const Node
*Requires1_
,
1754 NodeArray Params_
, const Node
*Requires2_
,
1755 std::string_view Count_
)
1756 : Node(KClosureTypeName
), TemplateParams(TemplateParams_
),
1757 Requires1(Requires1_
), Params(Params_
), Requires2(Requires2_
),
1760 template<typename Fn
> void match(Fn F
) const {
1761 F(TemplateParams
, Requires1
, Params
, Requires2
, Count
);
1764 void printDeclarator(OutputBuffer
&OB
) const {
1765 if (!TemplateParams
.empty()) {
1766 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1768 TemplateParams
.printWithComma(OB
);
1771 if (Requires1
!= nullptr) {
1773 Requires1
->print(OB
);
1777 Params
.printWithComma(OB
);
1779 if (Requires2
!= nullptr) {
1781 Requires2
->print(OB
);
1785 void printLeft(OutputBuffer
&OB
) const override
{
1786 // FIXME: This demangling is not particularly readable.
1790 printDeclarator(OB
);
1794 class StructuredBindingName
: public Node
{
1797 StructuredBindingName(NodeArray Bindings_
)
1798 : Node(KStructuredBindingName
), Bindings(Bindings_
) {}
1800 template<typename Fn
> void match(Fn F
) const { F(Bindings
); }
1802 void printLeft(OutputBuffer
&OB
) const override
{
1804 Bindings
.printWithComma(OB
);
1809 // -- Expression Nodes --
1811 class BinaryExpr
: public Node
{
1813 const std::string_view InfixOperator
;
1817 BinaryExpr(const Node
*LHS_
, std::string_view InfixOperator_
,
1818 const Node
*RHS_
, Prec Prec_
)
1819 : Node(KBinaryExpr
, Prec_
), LHS(LHS_
), InfixOperator(InfixOperator_
),
1822 template <typename Fn
> void match(Fn F
) const {
1823 F(LHS
, InfixOperator
, RHS
, getPrecedence());
1826 void printLeft(OutputBuffer
&OB
) const override
{
1827 bool ParenAll
= OB
.isGtInsideTemplateArgs() &&
1828 (InfixOperator
== ">" || InfixOperator
== ">>");
1831 // Assignment is right associative, with special LHS precedence.
1832 bool IsAssign
= getPrecedence() == Prec::Assign
;
1833 LHS
->printAsOperand(OB
, IsAssign
? Prec::OrIf
: getPrecedence(), !IsAssign
);
1834 // No space before comma operator
1835 if (!(InfixOperator
== ","))
1837 OB
+= InfixOperator
;
1839 RHS
->printAsOperand(OB
, getPrecedence(), IsAssign
);
1845 class ArraySubscriptExpr
: public Node
{
1850 ArraySubscriptExpr(const Node
*Op1_
, const Node
*Op2_
, Prec Prec_
)
1851 : Node(KArraySubscriptExpr
, Prec_
), Op1(Op1_
), Op2(Op2_
) {}
1853 template <typename Fn
> void match(Fn F
) const {
1854 F(Op1
, Op2
, getPrecedence());
1857 void printLeft(OutputBuffer
&OB
) const override
{
1858 Op1
->printAsOperand(OB
, getPrecedence());
1860 Op2
->printAsOperand(OB
);
1865 class PostfixExpr
: public Node
{
1867 const std::string_view Operator
;
1870 PostfixExpr(const Node
*Child_
, std::string_view Operator_
, Prec Prec_
)
1871 : Node(KPostfixExpr
, Prec_
), Child(Child_
), Operator(Operator_
) {}
1873 template <typename Fn
> void match(Fn F
) const {
1874 F(Child
, Operator
, getPrecedence());
1877 void printLeft(OutputBuffer
&OB
) const override
{
1878 Child
->printAsOperand(OB
, getPrecedence(), true);
1883 class ConditionalExpr
: public Node
{
1889 ConditionalExpr(const Node
*Cond_
, const Node
*Then_
, const Node
*Else_
,
1891 : Node(KConditionalExpr
, Prec_
), Cond(Cond_
), Then(Then_
), Else(Else_
) {}
1893 template <typename Fn
> void match(Fn F
) const {
1894 F(Cond
, Then
, Else
, getPrecedence());
1897 void printLeft(OutputBuffer
&OB
) const override
{
1898 Cond
->printAsOperand(OB
, getPrecedence());
1900 Then
->printAsOperand(OB
);
1902 Else
->printAsOperand(OB
, Prec::Assign
, true);
1906 class MemberExpr
: public Node
{
1908 const std::string_view Kind
;
1912 MemberExpr(const Node
*LHS_
, std::string_view Kind_
, const Node
*RHS_
,
1914 : Node(KMemberExpr
, Prec_
), LHS(LHS_
), Kind(Kind_
), RHS(RHS_
) {}
1916 template <typename Fn
> void match(Fn F
) const {
1917 F(LHS
, Kind
, RHS
, getPrecedence());
1920 void printLeft(OutputBuffer
&OB
) const override
{
1921 LHS
->printAsOperand(OB
, getPrecedence(), true);
1923 RHS
->printAsOperand(OB
, getPrecedence(), false);
1927 class SubobjectExpr
: public Node
{
1929 const Node
*SubExpr
;
1930 std::string_view Offset
;
1931 NodeArray UnionSelectors
;
1935 SubobjectExpr(const Node
*Type_
, const Node
*SubExpr_
,
1936 std::string_view Offset_
, NodeArray UnionSelectors_
,
1937 bool OnePastTheEnd_
)
1938 : Node(KSubobjectExpr
), Type(Type_
), SubExpr(SubExpr_
), Offset(Offset_
),
1939 UnionSelectors(UnionSelectors_
), OnePastTheEnd(OnePastTheEnd_
) {}
1941 template<typename Fn
> void match(Fn F
) const {
1942 F(Type
, SubExpr
, Offset
, UnionSelectors
, OnePastTheEnd
);
1945 void printLeft(OutputBuffer
&OB
) const override
{
1949 OB
+= " at offset ";
1950 if (Offset
.empty()) {
1952 } else if (Offset
[0] == 'n') {
1954 OB
+= std::string_view(Offset
.data() + 1, Offset
.size() - 1);
1962 class EnclosingExpr
: public Node
{
1963 const std::string_view Prefix
;
1965 const std::string_view Postfix
;
1968 EnclosingExpr(std::string_view Prefix_
, const Node
*Infix_
,
1969 Prec Prec_
= Prec::Primary
)
1970 : Node(KEnclosingExpr
, Prec_
), Prefix(Prefix_
), Infix(Infix_
) {}
1972 template <typename Fn
> void match(Fn F
) const {
1973 F(Prefix
, Infix
, getPrecedence());
1976 void printLeft(OutputBuffer
&OB
) const override
{
1985 class CastExpr
: public Node
{
1986 // cast_kind<to>(from)
1987 const std::string_view CastKind
;
1992 CastExpr(std::string_view CastKind_
, const Node
*To_
, const Node
*From_
,
1994 : Node(KCastExpr
, Prec_
), CastKind(CastKind_
), To(To_
), From(From_
) {}
1996 template <typename Fn
> void match(Fn F
) const {
1997 F(CastKind
, To
, From
, getPrecedence());
2000 void printLeft(OutputBuffer
&OB
) const override
{
2003 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
2009 From
->printAsOperand(OB
);
2014 class SizeofParamPackExpr
: public Node
{
2018 SizeofParamPackExpr(const Node
*Pack_
)
2019 : Node(KSizeofParamPackExpr
), Pack(Pack_
) {}
2021 template<typename Fn
> void match(Fn F
) const { F(Pack
); }
2023 void printLeft(OutputBuffer
&OB
) const override
{
2026 ParameterPackExpansion
PPE(Pack
);
2032 class CallExpr
: public Node
{
2037 CallExpr(const Node
*Callee_
, NodeArray Args_
, Prec Prec_
)
2038 : Node(KCallExpr
, Prec_
), Callee(Callee_
), Args(Args_
) {}
2040 template <typename Fn
> void match(Fn F
) const {
2041 F(Callee
, Args
, getPrecedence());
2044 void printLeft(OutputBuffer
&OB
) const override
{
2047 Args
.printWithComma(OB
);
2052 class NewExpr
: public Node
{
2053 // new (expr_list) type(init_list)
2057 bool IsGlobal
; // ::operator new ?
2058 bool IsArray
; // new[] ?
2060 NewExpr(NodeArray ExprList_
, Node
*Type_
, NodeArray InitList_
, bool IsGlobal_
,
2061 bool IsArray_
, Prec Prec_
)
2062 : Node(KNewExpr
, Prec_
), ExprList(ExprList_
), Type(Type_
),
2063 InitList(InitList_
), IsGlobal(IsGlobal_
), IsArray(IsArray_
) {}
2065 template<typename Fn
> void match(Fn F
) const {
2066 F(ExprList
, Type
, InitList
, IsGlobal
, IsArray
, getPrecedence());
2069 void printLeft(OutputBuffer
&OB
) const override
{
2075 if (!ExprList
.empty()) {
2077 ExprList
.printWithComma(OB
);
2082 if (!InitList
.empty()) {
2084 InitList
.printWithComma(OB
);
2090 class DeleteExpr
: public Node
{
2096 DeleteExpr(Node
*Op_
, bool IsGlobal_
, bool IsArray_
, Prec Prec_
)
2097 : Node(KDeleteExpr
, Prec_
), Op(Op_
), IsGlobal(IsGlobal_
),
2098 IsArray(IsArray_
) {}
2100 template <typename Fn
> void match(Fn F
) const {
2101 F(Op
, IsGlobal
, IsArray
, getPrecedence());
2104 void printLeft(OutputBuffer
&OB
) const override
{
2115 class PrefixExpr
: public Node
{
2116 std::string_view Prefix
;
2120 PrefixExpr(std::string_view Prefix_
, Node
*Child_
, Prec Prec_
)
2121 : Node(KPrefixExpr
, Prec_
), Prefix(Prefix_
), Child(Child_
) {}
2123 template <typename Fn
> void match(Fn F
) const {
2124 F(Prefix
, Child
, getPrecedence());
2127 void printLeft(OutputBuffer
&OB
) const override
{
2129 Child
->printAsOperand(OB
, getPrecedence());
2133 class FunctionParam
: public Node
{
2134 std::string_view Number
;
2137 FunctionParam(std::string_view Number_
)
2138 : Node(KFunctionParam
), Number(Number_
) {}
2140 template<typename Fn
> void match(Fn F
) const { F(Number
); }
2142 void printLeft(OutputBuffer
&OB
) const override
{
2148 class ConversionExpr
: public Node
{
2150 NodeArray Expressions
;
2153 ConversionExpr(const Node
*Type_
, NodeArray Expressions_
, Prec Prec_
)
2154 : Node(KConversionExpr
, Prec_
), Type(Type_
), Expressions(Expressions_
) {}
2156 template <typename Fn
> void match(Fn F
) const {
2157 F(Type
, Expressions
, getPrecedence());
2160 void printLeft(OutputBuffer
&OB
) const override
{
2165 Expressions
.printWithComma(OB
);
2170 class PointerToMemberConversionExpr
: public Node
{
2172 const Node
*SubExpr
;
2173 std::string_view Offset
;
2176 PointerToMemberConversionExpr(const Node
*Type_
, const Node
*SubExpr_
,
2177 std::string_view Offset_
, Prec Prec_
)
2178 : Node(KPointerToMemberConversionExpr
, Prec_
), Type(Type_
),
2179 SubExpr(SubExpr_
), Offset(Offset_
) {}
2181 template <typename Fn
> void match(Fn F
) const {
2182 F(Type
, SubExpr
, Offset
, getPrecedence());
2185 void printLeft(OutputBuffer
&OB
) const override
{
2195 class InitListExpr
: public Node
{
2199 InitListExpr(const Node
*Ty_
, NodeArray Inits_
)
2200 : Node(KInitListExpr
), Ty(Ty_
), Inits(Inits_
) {}
2202 template<typename Fn
> void match(Fn F
) const { F(Ty
, Inits
); }
2204 void printLeft(OutputBuffer
&OB
) const override
{
2208 Inits
.printWithComma(OB
);
2213 class BracedExpr
: public Node
{
2218 BracedExpr(const Node
*Elem_
, const Node
*Init_
, bool IsArray_
)
2219 : Node(KBracedExpr
), Elem(Elem_
), Init(Init_
), IsArray(IsArray_
) {}
2221 template<typename Fn
> void match(Fn F
) const { F(Elem
, Init
, IsArray
); }
2223 void printLeft(OutputBuffer
&OB
) const override
{
2232 if (Init
->getKind() != KBracedExpr
&& Init
->getKind() != KBracedRangeExpr
)
2238 class BracedRangeExpr
: public Node
{
2243 BracedRangeExpr(const Node
*First_
, const Node
*Last_
, const Node
*Init_
)
2244 : Node(KBracedRangeExpr
), First(First_
), Last(Last_
), Init(Init_
) {}
2246 template<typename Fn
> void match(Fn F
) const { F(First
, Last
, Init
); }
2248 void printLeft(OutputBuffer
&OB
) const override
{
2254 if (Init
->getKind() != KBracedExpr
&& Init
->getKind() != KBracedRangeExpr
)
2260 class FoldExpr
: public Node
{
2261 const Node
*Pack
, *Init
;
2262 std::string_view OperatorName
;
2266 FoldExpr(bool IsLeftFold_
, std::string_view OperatorName_
, const Node
*Pack_
,
2268 : Node(KFoldExpr
), Pack(Pack_
), Init(Init_
), OperatorName(OperatorName_
),
2269 IsLeftFold(IsLeftFold_
) {}
2271 template<typename Fn
> void match(Fn F
) const {
2272 F(IsLeftFold
, OperatorName
, Pack
, Init
);
2275 void printLeft(OutputBuffer
&OB
) const override
{
2276 auto PrintPack
= [&] {
2278 ParameterPackExpansion(Pack
).print(OB
);
2283 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2284 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2285 // Fold expr operands are cast-expressions
2286 if (!IsLeftFold
|| Init
!= nullptr) {
2287 // '(init|pack) op '
2289 Init
->printAsOperand(OB
, Prec::Cast
, true);
2292 OB
<< " " << OperatorName
<< " ";
2295 if (IsLeftFold
|| Init
!= nullptr) {
2296 // ' op (init|pack)'
2297 OB
<< " " << OperatorName
<< " ";
2301 Init
->printAsOperand(OB
, Prec::Cast
, true);
2307 class ThrowExpr
: public Node
{
2311 ThrowExpr(const Node
*Op_
) : Node(KThrowExpr
), Op(Op_
) {}
2313 template<typename Fn
> void match(Fn F
) const { F(Op
); }
2315 void printLeft(OutputBuffer
&OB
) const override
{
2321 class BoolExpr
: public Node
{
2325 BoolExpr(bool Value_
) : Node(KBoolExpr
), Value(Value_
) {}
2327 template<typename Fn
> void match(Fn F
) const { F(Value
); }
2329 void printLeft(OutputBuffer
&OB
) const override
{
2330 OB
+= Value
? std::string_view("true") : std::string_view("false");
2334 class StringLiteral
: public Node
{
2338 StringLiteral(const Node
*Type_
) : Node(KStringLiteral
), Type(Type_
) {}
2340 template<typename Fn
> void match(Fn F
) const { F(Type
); }
2342 void printLeft(OutputBuffer
&OB
) const override
{
2349 class LambdaExpr
: public Node
{
2353 LambdaExpr(const Node
*Type_
) : Node(KLambdaExpr
), Type(Type_
) {}
2355 template<typename Fn
> void match(Fn F
) const { F(Type
); }
2357 void printLeft(OutputBuffer
&OB
) const override
{
2359 if (Type
->getKind() == KClosureTypeName
)
2360 static_cast<const ClosureTypeName
*>(Type
)->printDeclarator(OB
);
2365 class EnumLiteral
: public Node
{
2368 std::string_view Integer
;
2371 EnumLiteral(const Node
*Ty_
, std::string_view Integer_
)
2372 : Node(KEnumLiteral
), Ty(Ty_
), Integer(Integer_
) {}
2374 template<typename Fn
> void match(Fn F
) const { F(Ty
, Integer
); }
2376 void printLeft(OutputBuffer
&OB
) const override
{
2381 if (Integer
[0] == 'n')
2382 OB
<< '-' << std::string_view(Integer
.data() + 1, Integer
.size() - 1);
2388 class IntegerLiteral
: public Node
{
2389 std::string_view Type
;
2390 std::string_view Value
;
2393 IntegerLiteral(std::string_view Type_
, std::string_view Value_
)
2394 : Node(KIntegerLiteral
), Type(Type_
), Value(Value_
) {}
2396 template<typename Fn
> void match(Fn F
) const { F(Type
, Value
); }
2398 void printLeft(OutputBuffer
&OB
) const override
{
2399 if (Type
.size() > 3) {
2405 if (Value
[0] == 'n')
2406 OB
<< '-' << std::string_view(Value
.data() + 1, Value
.size() - 1);
2410 if (Type
.size() <= 3)
2415 class RequiresExpr
: public Node
{
2416 NodeArray Parameters
;
2417 NodeArray Requirements
;
2419 RequiresExpr(NodeArray Parameters_
, NodeArray Requirements_
)
2420 : Node(KRequiresExpr
), Parameters(Parameters_
),
2421 Requirements(Requirements_
) {}
2423 template<typename Fn
> void match(Fn F
) const { F(Parameters
, Requirements
); }
2425 void printLeft(OutputBuffer
&OB
) const override
{
2427 if (!Parameters
.empty()) {
2430 Parameters
.printWithComma(OB
);
2435 for (const Node
*Req
: Requirements
) {
2443 class ExprRequirement
: public Node
{
2446 const Node
*TypeConstraint
;
2448 ExprRequirement(const Node
*Expr_
, bool IsNoexcept_
,
2449 const Node
*TypeConstraint_
)
2450 : Node(KExprRequirement
), Expr(Expr_
), IsNoexcept(IsNoexcept_
),
2451 TypeConstraint(TypeConstraint_
) {}
2453 template <typename Fn
> void match(Fn F
) const {
2454 F(Expr
, IsNoexcept
, TypeConstraint
);
2457 void printLeft(OutputBuffer
&OB
) const override
{
2459 if (IsNoexcept
|| TypeConstraint
)
2462 if (IsNoexcept
|| TypeConstraint
)
2466 if (TypeConstraint
) {
2468 TypeConstraint
->print(OB
);
2474 class TypeRequirement
: public Node
{
2477 TypeRequirement(const Node
*Type_
)
2478 : Node(KTypeRequirement
), Type(Type_
) {}
2480 template <typename Fn
> void match(Fn F
) const { F(Type
); }
2482 void printLeft(OutputBuffer
&OB
) const override
{
2489 class NestedRequirement
: public Node
{
2490 const Node
*Constraint
;
2492 NestedRequirement(const Node
*Constraint_
)
2493 : Node(KNestedRequirement
), Constraint(Constraint_
) {}
2495 template <typename Fn
> void match(Fn F
) const { F(Constraint
); }
2497 void printLeft(OutputBuffer
&OB
) const override
{
2499 Constraint
->print(OB
);
2504 template <class Float
> struct FloatData
;
2506 namespace float_literal_impl
{
2507 constexpr Node::Kind
getFloatLiteralKind(float *) {
2508 return Node::KFloatLiteral
;
2510 constexpr Node::Kind
getFloatLiteralKind(double *) {
2511 return Node::KDoubleLiteral
;
2513 constexpr Node::Kind
getFloatLiteralKind(long double *) {
2514 return Node::KLongDoubleLiteral
;
2518 template <class Float
> class FloatLiteralImpl
: public Node
{
2519 const std::string_view Contents
;
2521 static constexpr Kind KindForClass
=
2522 float_literal_impl::getFloatLiteralKind((Float
*)nullptr);
2525 FloatLiteralImpl(std::string_view Contents_
)
2526 : Node(KindForClass
), Contents(Contents_
) {}
2528 template<typename Fn
> void match(Fn F
) const { F(Contents
); }
2530 void printLeft(OutputBuffer
&OB
) const override
{
2531 const size_t N
= FloatData
<Float
>::mangled_size
;
2532 if (Contents
.size() >= N
) {
2535 char buf
[sizeof(Float
)];
2537 const char *t
= Contents
.data();
2538 const char *last
= t
+ N
;
2540 for (; t
!= last
; ++t
, ++e
) {
2541 unsigned d1
= isdigit(*t
) ? static_cast<unsigned>(*t
- '0')
2542 : static_cast<unsigned>(*t
- 'a' + 10);
2544 unsigned d0
= isdigit(*t
) ? static_cast<unsigned>(*t
- '0')
2545 : static_cast<unsigned>(*t
- 'a' + 10);
2546 *e
= static_cast<char>((d1
<< 4) + d0
);
2548 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2549 std::reverse(buf
, e
);
2551 char num
[FloatData
<Float
>::max_demangled_size
] = {0};
2552 int n
= snprintf(num
, sizeof(num
), FloatData
<Float
>::spec
, value
);
2553 OB
+= std::string_view(num
, n
);
2558 using FloatLiteral
= FloatLiteralImpl
<float>;
2559 using DoubleLiteral
= FloatLiteralImpl
<double>;
2560 using LongDoubleLiteral
= FloatLiteralImpl
<long double>;
2562 /// Visit the node. Calls \c F(P), where \c P is the node cast to the
2563 /// appropriate derived class.
2564 template<typename Fn
>
2565 void Node::visit(Fn F
) const {
2569 return F(static_cast<const X *>(this));
2570 #include "ItaniumNodes.def"
2572 assert(0 && "unknown mangling node kind");
2575 /// Determine the kind of a node from its type.
2576 template<typename NodeT
> struct NodeKind
;
2578 template <> struct NodeKind<X> { \
2579 static constexpr Node::Kind Kind = Node::K##X; \
2580 static constexpr const char *name() { return #X; } \
2582 #include "ItaniumNodes.def"
2584 template <typename Derived
, typename Alloc
> struct AbstractManglingParser
{
2588 // Name stack, this is used by the parser to hold temporary names that were
2589 // parsed. The parser collapses multiple names into new nodes to construct
2590 // the AST. Once the parser is finished, names.size() == 1.
2591 PODSmallVector
<Node
*, 32> Names
;
2593 // Substitution table. Itanium supports name substitutions as a means of
2594 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2596 PODSmallVector
<Node
*, 32> Subs
;
2598 // A list of template argument values corresponding to a template parameter
2600 using TemplateParamList
= PODSmallVector
<Node
*, 8>;
2602 class ScopedTemplateParamList
{
2603 AbstractManglingParser
*Parser
;
2604 size_t OldNumTemplateParamLists
;
2605 TemplateParamList Params
;
2608 ScopedTemplateParamList(AbstractManglingParser
*TheParser
)
2609 : Parser(TheParser
),
2610 OldNumTemplateParamLists(TheParser
->TemplateParams
.size()) {
2611 Parser
->TemplateParams
.push_back(&Params
);
2613 ~ScopedTemplateParamList() {
2614 assert(Parser
->TemplateParams
.size() >= OldNumTemplateParamLists
);
2615 Parser
->TemplateParams
.shrinkToSize(OldNumTemplateParamLists
);
2617 TemplateParamList
*params() { return &Params
; }
2620 // Template parameter table. Like the above, but referenced like "T42_".
2621 // This has a smaller size compared to Subs and Names because it can be
2622 // stored on the stack.
2623 TemplateParamList OuterTemplateParams
;
2625 // Lists of template parameters indexed by template parameter depth,
2626 // referenced like "TL2_4_". If nonempty, element 0 is always
2627 // OuterTemplateParams; inner elements are always template parameter lists of
2628 // lambda expressions. For a generic lambda with no explicit template
2629 // parameter list, the corresponding parameter list pointer will be null.
2630 PODSmallVector
<TemplateParamList
*, 4> TemplateParams
;
2632 class SaveTemplateParams
{
2633 AbstractManglingParser
*Parser
;
2634 decltype(TemplateParams
) OldParams
;
2635 decltype(OuterTemplateParams
) OldOuterParams
;
2638 SaveTemplateParams(AbstractManglingParser
*TheParser
) : Parser(TheParser
) {
2639 OldParams
= std::move(Parser
->TemplateParams
);
2640 OldOuterParams
= std::move(Parser
->OuterTemplateParams
);
2641 Parser
->TemplateParams
.clear();
2642 Parser
->OuterTemplateParams
.clear();
2644 ~SaveTemplateParams() {
2645 Parser
->TemplateParams
= std::move(OldParams
);
2646 Parser
->OuterTemplateParams
= std::move(OldOuterParams
);
2650 // Set of unresolved forward <template-param> references. These can occur in a
2651 // conversion operator's type, and are resolved in the enclosing <encoding>.
2652 PODSmallVector
<ForwardTemplateReference
*, 4> ForwardTemplateRefs
;
2654 bool TryToParseTemplateArgs
= true;
2655 bool PermitForwardTemplateReferences
= false;
2656 bool InConstraintExpr
= false;
2657 size_t ParsingLambdaParamsAtLevel
= (size_t)-1;
2659 unsigned NumSyntheticTemplateParameters
[3] = {};
2663 AbstractManglingParser(const char *First_
, const char *Last_
)
2664 : First(First_
), Last(Last_
) {}
2666 Derived
&getDerived() { return static_cast<Derived
&>(*this); }
2668 void reset(const char *First_
, const char *Last_
) {
2673 TemplateParams
.clear();
2674 ParsingLambdaParamsAtLevel
= (size_t)-1;
2675 TryToParseTemplateArgs
= true;
2676 PermitForwardTemplateReferences
= false;
2677 for (int I
= 0; I
!= 3; ++I
)
2678 NumSyntheticTemplateParameters
[I
] = 0;
2679 ASTAllocator
.reset();
2682 template <class T
, class... Args
> Node
*make(Args
&&... args
) {
2683 return ASTAllocator
.template makeNode
<T
>(std::forward
<Args
>(args
)...);
2686 template <class It
> NodeArray
makeNodeArray(It begin
, It end
) {
2687 size_t sz
= static_cast<size_t>(end
- begin
);
2688 void *mem
= ASTAllocator
.allocateNodeArray(sz
);
2689 Node
**data
= new (mem
) Node
*[sz
];
2690 std::copy(begin
, end
, data
);
2691 return NodeArray(data
, sz
);
2694 NodeArray
popTrailingNodeArray(size_t FromPosition
) {
2695 assert(FromPosition
<= Names
.size());
2697 makeNodeArray(Names
.begin() + (long)FromPosition
, Names
.end());
2698 Names
.shrinkToSize(FromPosition
);
2702 bool consumeIf(std::string_view S
) {
2703 if (starts_with(std::string_view(First
, Last
- First
), S
)) {
2710 bool consumeIf(char C
) {
2711 if (First
!= Last
&& *First
== C
) {
2718 char consume() { return First
!= Last
? *First
++ : '\0'; }
2720 char look(unsigned Lookahead
= 0) const {
2721 if (static_cast<size_t>(Last
- First
) <= Lookahead
)
2723 return First
[Lookahead
];
2726 size_t numLeft() const { return static_cast<size_t>(Last
- First
); }
2728 std::string_view
parseNumber(bool AllowNegative
= false);
2729 Qualifiers
parseCVQualifiers();
2730 bool parsePositiveInteger(size_t *Out
);
2731 std::string_view
parseBareSourceName();
2733 bool parseSeqId(size_t *Out
);
2734 Node
*parseSubstitution();
2735 Node
*parseTemplateParam();
2736 Node
*parseTemplateParamDecl(TemplateParamList
*Params
);
2737 Node
*parseTemplateArgs(bool TagTemplates
= false);
2738 Node
*parseTemplateArg();
2740 bool isTemplateParamDecl() {
2741 return look() == 'T' &&
2742 std::string_view("yptnk").find(look(1)) != std::string_view::npos
;
2745 /// Parse the <expression> production.
2747 Node
*parsePrefixExpr(std::string_view Kind
, Node::Prec Prec
);
2748 Node
*parseBinaryExpr(std::string_view Kind
, Node::Prec Prec
);
2749 Node
*parseIntegerLiteral(std::string_view Lit
);
2750 Node
*parseExprPrimary();
2751 template <class Float
> Node
*parseFloatingLiteral();
2752 Node
*parseFunctionParam();
2753 Node
*parseConversionExpr();
2754 Node
*parseBracedExpr();
2755 Node
*parseFoldExpr();
2756 Node
*parsePointerToMemberConversionExpr(Node::Prec Prec
);
2757 Node
*parseSubobjectExpr();
2758 Node
*parseConstraintExpr();
2759 Node
*parseRequiresExpr();
2761 /// Parse the <type> production.
2763 Node
*parseFunctionType();
2764 Node
*parseVectorType();
2765 Node
*parseDecltype();
2766 Node
*parseArrayType();
2767 Node
*parsePointerToMemberType();
2768 Node
*parseClassEnumType();
2769 Node
*parseQualifiedType();
2771 Node
*parseEncoding();
2772 bool parseCallOffset();
2773 Node
*parseSpecialName();
2775 /// Holds some extra information about a <name> that is being parsed. This
2776 /// information is only pertinent if the <name> refers to an <encoding>.
2778 bool CtorDtorConversion
= false;
2779 bool EndsWithTemplateArgs
= false;
2780 Qualifiers CVQualifiers
= QualNone
;
2781 FunctionRefQual ReferenceQualifier
= FrefQualNone
;
2782 size_t ForwardTemplateRefsBegin
;
2784 NameState(AbstractManglingParser
*Enclosing
)
2785 : ForwardTemplateRefsBegin(Enclosing
->ForwardTemplateRefs
.size()) {}
2788 bool resolveForwardTemplateRefs(NameState
&State
) {
2789 size_t I
= State
.ForwardTemplateRefsBegin
;
2790 size_t E
= ForwardTemplateRefs
.size();
2791 for (; I
< E
; ++I
) {
2792 size_t Idx
= ForwardTemplateRefs
[I
]->Index
;
2793 if (TemplateParams
.empty() || !TemplateParams
[0] ||
2794 Idx
>= TemplateParams
[0]->size())
2796 ForwardTemplateRefs
[I
]->Ref
= (*TemplateParams
[0])[Idx
];
2798 ForwardTemplateRefs
.shrinkToSize(State
.ForwardTemplateRefsBegin
);
2802 /// Parse the <name> production>
2803 Node
*parseName(NameState
*State
= nullptr);
2804 Node
*parseLocalName(NameState
*State
);
2805 Node
*parseOperatorName(NameState
*State
);
2806 bool parseModuleNameOpt(ModuleName
*&Module
);
2807 Node
*parseUnqualifiedName(NameState
*State
, Node
*Scope
, ModuleName
*Module
);
2808 Node
*parseUnnamedTypeName(NameState
*State
);
2809 Node
*parseSourceName(NameState
*State
);
2810 Node
*parseUnscopedName(NameState
*State
, bool *isSubstName
);
2811 Node
*parseNestedName(NameState
*State
);
2812 Node
*parseCtorDtorName(Node
*&SoFar
, NameState
*State
);
2814 Node
*parseAbiTags(Node
*N
);
2816 struct OperatorInfo
{
2817 enum OIKind
: unsigned char {
2818 Prefix
, // Prefix unary: @ expr
2819 Postfix
, // Postfix unary: expr @
2820 Binary
, // Binary: lhs @ rhs
2821 Array
, // Array index: lhs [ rhs ]
2822 Member
, // Member access: lhs @ rhs
2825 Call
, // Function call: expr (expr*)
2826 CCast
, // C cast: (type)expr
2827 Conditional
, // Conditional: expr ? expr : expr
2828 NameOnly
, // Overload only, not allowed in expression.
2829 // Below do not have operator names
2830 NamedCast
, // Named cast, @<type>(expr)
2831 OfIdOp
, // alignof, sizeof, typeid
2833 Unnameable
= NamedCast
,
2835 char Enc
[2]; // Encoding
2836 OIKind Kind
; // Kind of operator
2837 bool Flag
: 1; // Entry-specific flag
2838 Node::Prec Prec
: 7; // Precedence
2839 const char *Name
; // Spelling
2842 constexpr OperatorInfo(const char (&E
)[3], OIKind K
, bool F
, Node::Prec P
,
2844 : Enc
{E
[0], E
[1]}, Kind
{K
}, Flag
{F
}, Prec
{P
}, Name
{N
} {}
2847 bool operator<(const OperatorInfo
&Other
) const {
2848 return *this < Other
.Enc
;
2850 bool operator<(const char *Peek
) const {
2851 return Enc
[0] < Peek
[0] || (Enc
[0] == Peek
[0] && Enc
[1] < Peek
[1]);
2853 bool operator==(const char *Peek
) const {
2854 return Enc
[0] == Peek
[0] && Enc
[1] == Peek
[1];
2856 bool operator!=(const char *Peek
) const { return !this->operator==(Peek
); }
2859 std::string_view
getSymbol() const {
2860 std::string_view Res
= Name
;
2861 if (Kind
< Unnameable
) {
2862 assert(starts_with(Res
, "operator") &&
2863 "operator name does not start with 'operator'");
2864 Res
.remove_prefix(sizeof("operator") - 1);
2865 if (starts_with(Res
, ' '))
2866 Res
.remove_prefix(1);
2870 std::string_view
getName() const { return Name
; }
2871 OIKind
getKind() const { return Kind
; }
2872 bool getFlag() const { return Flag
; }
2873 Node::Prec
getPrecedence() const { return Prec
; }
2875 static const OperatorInfo Ops
[];
2876 static const size_t NumOps
;
2877 const OperatorInfo
*parseOperatorEncoding();
2879 /// Parse the <unresolved-name> production.
2880 Node
*parseUnresolvedName(bool Global
);
2881 Node
*parseSimpleId();
2882 Node
*parseBaseUnresolvedName();
2883 Node
*parseUnresolvedType();
2884 Node
*parseDestructorName();
2886 /// Top-level entry point into the parser.
2890 const char* parse_discriminator(const char* first
, const char* last
);
2892 // <name> ::= <nested-name> // N
2893 // ::= <local-name> # See Scope Encoding below // Z
2894 // ::= <unscoped-template-name> <template-args>
2895 // ::= <unscoped-name>
2897 // <unscoped-template-name> ::= <unscoped-name>
2898 // ::= <substitution>
2899 template <typename Derived
, typename Alloc
>
2900 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseName(NameState
*State
) {
2902 return getDerived().parseNestedName(State
);
2904 return getDerived().parseLocalName(State
);
2906 Node
*Result
= nullptr;
2907 bool IsSubst
= false;
2909 Result
= getDerived().parseUnscopedName(State
, &IsSubst
);
2913 if (look() == 'I') {
2914 // ::= <unscoped-template-name> <template-args>
2916 // An unscoped-template-name is substitutable.
2917 Subs
.push_back(Result
);
2918 Node
*TA
= getDerived().parseTemplateArgs(State
!= nullptr);
2922 State
->EndsWithTemplateArgs
= true;
2923 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
2924 } else if (IsSubst
) {
2925 // The substitution case must be followed by <template-args>.
2932 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2933 // := Z <function encoding> E s [<discriminator>]
2934 // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
2935 template <typename Derived
, typename Alloc
>
2936 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseLocalName(NameState
*State
) {
2937 if (!consumeIf('Z'))
2939 Node
*Encoding
= getDerived().parseEncoding();
2940 if (Encoding
== nullptr || !consumeIf('E'))
2943 if (consumeIf('s')) {
2944 First
= parse_discriminator(First
, Last
);
2945 auto *StringLitName
= make
<NameType
>("string literal");
2948 return make
<LocalName
>(Encoding
, StringLitName
);
2951 // The template parameters of the inner name are unrelated to those of the
2952 // enclosing context.
2953 SaveTemplateParams
SaveTemplateParamsScope(this);
2955 if (consumeIf('d')) {
2957 if (!consumeIf('_'))
2959 Node
*N
= getDerived().parseName(State
);
2962 return make
<LocalName
>(Encoding
, N
);
2965 Node
*Entity
= getDerived().parseName(State
);
2966 if (Entity
== nullptr)
2968 First
= parse_discriminator(First
, Last
);
2969 return make
<LocalName
>(Encoding
, Entity
);
2972 // <unscoped-name> ::= <unqualified-name>
2973 // ::= St <unqualified-name> # ::std::
2975 template <typename Derived
, typename Alloc
>
2977 AbstractManglingParser
<Derived
, Alloc
>::parseUnscopedName(NameState
*State
,
2980 Node
*Std
= nullptr;
2981 if (consumeIf("St")) {
2982 Std
= make
<NameType
>("std");
2987 Node
*Res
= nullptr;
2988 ModuleName
*Module
= nullptr;
2989 if (look() == 'S') {
2990 Node
*S
= getDerived().parseSubstitution();
2993 if (S
->getKind() == Node::KModuleName
)
2994 Module
= static_cast<ModuleName
*>(S
);
2995 else if (IsSubst
&& Std
== nullptr) {
3003 if (Res
== nullptr || Std
!= nullptr) {
3004 Res
= getDerived().parseUnqualifiedName(State
, Std
, Module
);
3010 // <unqualified-name> ::= [<module-name>] F? L? <operator-name> [<abi-tags>]
3011 // ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
3012 // ::= [<module-name>] F? L? <source-name> [<abi-tags>]
3013 // ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
3014 // # structured binding declaration
3015 // ::= [<module-name>] L? DC <source-name>+ E
3016 template <typename Derived
, typename Alloc
>
3017 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnqualifiedName(
3018 NameState
*State
, Node
*Scope
, ModuleName
*Module
) {
3019 if (getDerived().parseModuleNameOpt(Module
))
3022 bool IsMemberLikeFriend
= Scope
&& consumeIf('F');
3027 if (look() >= '1' && look() <= '9') {
3028 Result
= getDerived().parseSourceName(State
);
3029 } else if (look() == 'U') {
3030 Result
= getDerived().parseUnnamedTypeName(State
);
3031 } else if (consumeIf("DC")) {
3032 // Structured binding
3033 size_t BindingsBegin
= Names
.size();
3035 Node
*Binding
= getDerived().parseSourceName(State
);
3036 if (Binding
== nullptr)
3038 Names
.push_back(Binding
);
3039 } while (!consumeIf('E'));
3040 Result
= make
<StructuredBindingName
>(popTrailingNodeArray(BindingsBegin
));
3041 } else if (look() == 'C' || look() == 'D') {
3042 // A <ctor-dtor-name>.
3043 if (Scope
== nullptr || Module
!= nullptr)
3045 Result
= getDerived().parseCtorDtorName(Scope
, State
);
3047 Result
= getDerived().parseOperatorName(State
);
3050 if (Result
!= nullptr && Module
!= nullptr)
3051 Result
= make
<ModuleEntity
>(Module
, Result
);
3052 if (Result
!= nullptr)
3053 Result
= getDerived().parseAbiTags(Result
);
3054 if (Result
!= nullptr && IsMemberLikeFriend
)
3055 Result
= make
<MemberLikeFriendName
>(Scope
, Result
);
3056 else if (Result
!= nullptr && Scope
!= nullptr)
3057 Result
= make
<NestedName
>(Scope
, Result
);
3062 // <module-name> ::= <module-subname>
3063 // ::= <module-name> <module-subname>
3064 // ::= <substitution> # passed in by caller
3065 // <module-subname> ::= W <source-name>
3066 // ::= W P <source-name>
3067 template <typename Derived
, typename Alloc
>
3068 bool AbstractManglingParser
<Derived
, Alloc
>::parseModuleNameOpt(
3069 ModuleName
*&Module
) {
3070 while (consumeIf('W')) {
3071 bool IsPartition
= consumeIf('P');
3072 Node
*Sub
= getDerived().parseSourceName(nullptr);
3076 static_cast<ModuleName
*>(make
<ModuleName
>(Module
, Sub
, IsPartition
));
3077 Subs
.push_back(Module
);
3083 // <unnamed-type-name> ::= Ut [<nonnegative number>] _
3084 // ::= <closure-type-name>
3086 // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
3088 // <lambda-sig> ::= <template-param-decl>* [Q <requires-clause expression>]
3089 // <parameter type>+ # or "v" if the lambda has no parameters
3090 template <typename Derived
, typename Alloc
>
3092 AbstractManglingParser
<Derived
, Alloc
>::parseUnnamedTypeName(NameState
*State
) {
3093 // <template-params> refer to the innermost <template-args>. Clear out any
3094 // outer args that we may have inserted into TemplateParams.
3095 if (State
!= nullptr)
3096 TemplateParams
.clear();
3098 if (consumeIf("Ut")) {
3099 std::string_view Count
= parseNumber();
3100 if (!consumeIf('_'))
3102 return make
<UnnamedTypeName
>(Count
);
3104 if (consumeIf("Ul")) {
3105 ScopedOverride
<size_t> SwapParams(ParsingLambdaParamsAtLevel
,
3106 TemplateParams
.size());
3107 ScopedTemplateParamList
LambdaTemplateParams(this);
3109 size_t ParamsBegin
= Names
.size();
3110 while (getDerived().isTemplateParamDecl()) {
3112 getDerived().parseTemplateParamDecl(LambdaTemplateParams
.params());
3117 NodeArray TempParams
= popTrailingNodeArray(ParamsBegin
);
3119 // FIXME: If TempParams is empty and none of the function parameters
3120 // includes 'auto', we should remove LambdaTemplateParams from the
3121 // TemplateParams list. Unfortunately, we don't find out whether there are
3122 // any 'auto' parameters until too late in an example such as:
3124 // template<typename T> void f(
3125 // decltype([](decltype([]<typename T>(T v) {}),
3127 // template<typename T> void f(
3128 // decltype([](decltype([]<typename T>(T w) {}),
3131 // Here, the type of v is at level 2 but the type of w is at level 1. We
3132 // don't find this out until we encounter the type of the next parameter.
3134 // However, compilers can't actually cope with the former example in
3135 // practice, and it's likely to be made ill-formed in future, so we don't
3136 // need to support it here.
3138 // If we encounter an 'auto' in the function parameter types, we will
3139 // recreate a template parameter scope for it, but any intervening lambdas
3140 // will be parsed in the 'wrong' template parameter depth.
3141 if (TempParams
.empty())
3142 TemplateParams
.pop_back();
3144 Node
*Requires1
= nullptr;
3145 if (consumeIf('Q')) {
3146 Requires1
= getDerived().parseConstraintExpr();
3147 if (Requires1
== nullptr)
3151 if (!consumeIf("v")) {
3153 Node
*P
= getDerived().parseType();
3157 } while (look() != 'E' && look() != 'Q');
3159 NodeArray Params
= popTrailingNodeArray(ParamsBegin
);
3161 Node
*Requires2
= nullptr;
3162 if (consumeIf('Q')) {
3163 Requires2
= getDerived().parseConstraintExpr();
3164 if (Requires2
== nullptr)
3168 if (!consumeIf('E'))
3171 std::string_view Count
= parseNumber();
3172 if (!consumeIf('_'))
3174 return make
<ClosureTypeName
>(TempParams
, Requires1
, Params
, Requires2
,
3177 if (consumeIf("Ub")) {
3178 (void)parseNumber();
3179 if (!consumeIf('_'))
3181 return make
<NameType
>("'block-literal'");
3186 // <source-name> ::= <positive length number> <identifier>
3187 template <typename Derived
, typename Alloc
>
3188 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSourceName(NameState
*) {
3190 if (parsePositiveInteger(&Length
))
3192 if (numLeft() < Length
|| Length
== 0)
3194 std::string_view
Name(First
, Length
);
3196 if (starts_with(Name
, "_GLOBAL__N"))
3197 return make
<NameType
>("(anonymous namespace)");
3198 return make
<NameType
>(Name
);
3201 // Operator encodings
3202 template <typename Derived
, typename Alloc
>
3203 const typename AbstractManglingParser
<
3204 Derived
, Alloc
>::OperatorInfo AbstractManglingParser
<Derived
,
3206 // Keep ordered by encoding
3207 {"aN", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator&="},
3208 {"aS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator="},
3209 {"aa", OperatorInfo::Binary
, false, Node::Prec::AndIf
, "operator&&"},
3210 {"ad", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator&"},
3211 {"an", OperatorInfo::Binary
, false, Node::Prec::And
, "operator&"},
3212 {"at", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Unary
, "alignof "},
3213 {"aw", OperatorInfo::NameOnly
, false, Node::Prec::Primary
,
3214 "operator co_await"},
3215 {"az", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Unary
, "alignof "},
3216 {"cc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "const_cast"},
3217 {"cl", OperatorInfo::Call
, false, Node::Prec::Postfix
, "operator()"},
3218 {"cm", OperatorInfo::Binary
, false, Node::Prec::Comma
, "operator,"},
3219 {"co", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator~"},
3220 {"cv", OperatorInfo::CCast
, false, Node::Prec::Cast
, "operator"}, // C Cast
3221 {"dV", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator/="},
3222 {"da", OperatorInfo::Del
, /*Ary*/ true, Node::Prec::Unary
,
3223 "operator delete[]"},
3224 {"dc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "dynamic_cast"},
3225 {"de", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator*"},
3226 {"dl", OperatorInfo::Del
, /*Ary*/ false, Node::Prec::Unary
,
3228 {"ds", OperatorInfo::Member
, /*Named*/ false, Node::Prec::PtrMem
,
3230 {"dt", OperatorInfo::Member
, /*Named*/ false, Node::Prec::Postfix
,
3232 {"dv", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator/"},
3233 {"eO", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator^="},
3234 {"eo", OperatorInfo::Binary
, false, Node::Prec::Xor
, "operator^"},
3235 {"eq", OperatorInfo::Binary
, false, Node::Prec::Equality
, "operator=="},
3236 {"ge", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator>="},
3237 {"gt", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator>"},
3238 {"ix", OperatorInfo::Array
, false, Node::Prec::Postfix
, "operator[]"},
3239 {"lS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator<<="},
3240 {"le", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator<="},
3241 {"ls", OperatorInfo::Binary
, false, Node::Prec::Shift
, "operator<<"},
3242 {"lt", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator<"},
3243 {"mI", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator-="},
3244 {"mL", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator*="},
3245 {"mi", OperatorInfo::Binary
, false, Node::Prec::Additive
, "operator-"},
3246 {"ml", OperatorInfo::Binary
, false, Node::Prec::Multiplicative
,
3248 {"mm", OperatorInfo::Postfix
, false, Node::Prec::Postfix
, "operator--"},
3249 {"na", OperatorInfo::New
, /*Ary*/ true, Node::Prec::Unary
,
3251 {"ne", OperatorInfo::Binary
, false, Node::Prec::Equality
, "operator!="},
3252 {"ng", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator-"},
3253 {"nt", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator!"},
3254 {"nw", OperatorInfo::New
, /*Ary*/ false, Node::Prec::Unary
, "operator new"},
3255 {"oR", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator|="},
3256 {"oo", OperatorInfo::Binary
, false, Node::Prec::OrIf
, "operator||"},
3257 {"or", OperatorInfo::Binary
, false, Node::Prec::Ior
, "operator|"},
3258 {"pL", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator+="},
3259 {"pl", OperatorInfo::Binary
, false, Node::Prec::Additive
, "operator+"},
3260 {"pm", OperatorInfo::Member
, /*Named*/ false, Node::Prec::PtrMem
,
3262 {"pp", OperatorInfo::Postfix
, false, Node::Prec::Postfix
, "operator++"},
3263 {"ps", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator+"},
3264 {"pt", OperatorInfo::Member
, /*Named*/ true, Node::Prec::Postfix
,
3266 {"qu", OperatorInfo::Conditional
, false, Node::Prec::Conditional
,
3268 {"rM", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator%="},
3269 {"rS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator>>="},
3270 {"rc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
,
3271 "reinterpret_cast"},
3272 {"rm", OperatorInfo::Binary
, false, Node::Prec::Multiplicative
,
3274 {"rs", OperatorInfo::Binary
, false, Node::Prec::Shift
, "operator>>"},
3275 {"sc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "static_cast"},
3276 {"ss", OperatorInfo::Binary
, false, Node::Prec::Spaceship
, "operator<=>"},
3277 {"st", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Unary
, "sizeof "},
3278 {"sz", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Unary
, "sizeof "},
3279 {"te", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Postfix
,
3281 {"ti", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Postfix
, "typeid "},
3283 template <typename Derived
, typename Alloc
>
3284 const size_t AbstractManglingParser
<Derived
, Alloc
>::NumOps
= sizeof(Ops
) /
3287 // If the next 2 chars are an operator encoding, consume them and return their
3288 // OperatorInfo. Otherwise return nullptr.
3289 template <typename Derived
, typename Alloc
>
3290 const typename AbstractManglingParser
<Derived
, Alloc
>::OperatorInfo
*
3291 AbstractManglingParser
<Derived
, Alloc
>::parseOperatorEncoding() {
3295 // We can't use lower_bound as that can link to symbols in the C++ library,
3296 // and this must remain independant of that.
3297 size_t lower
= 0u, upper
= NumOps
- 1; // Inclusive bounds.
3298 while (upper
!= lower
) {
3299 size_t middle
= (upper
+ lower
) / 2;
3300 if (Ops
[middle
] < First
)
3305 if (Ops
[lower
] != First
)
3312 // <operator-name> ::= See parseOperatorEncoding()
3313 // ::= li <source-name> # operator ""
3314 // ::= v <digit> <source-name> # vendor extended operator
3315 template <typename Derived
, typename Alloc
>
3317 AbstractManglingParser
<Derived
, Alloc
>::parseOperatorName(NameState
*State
) {
3318 if (const auto *Op
= parseOperatorEncoding()) {
3319 if (Op
->getKind() == OperatorInfo::CCast
) {
3320 // ::= cv <type> # (cast)
3321 ScopedOverride
<bool> SaveTemplate(TryToParseTemplateArgs
, false);
3322 // If we're parsing an encoding, State != nullptr and the conversion
3323 // operators' <type> could have a <template-param> that refers to some
3324 // <template-arg>s further ahead in the mangled name.
3325 ScopedOverride
<bool> SavePermit(PermitForwardTemplateReferences
,
3326 PermitForwardTemplateReferences
||
3328 Node
*Ty
= getDerived().parseType();
3331 if (State
) State
->CtorDtorConversion
= true;
3332 return make
<ConversionOperatorType
>(Ty
);
3335 if (Op
->getKind() >= OperatorInfo::Unnameable
)
3336 /* Not a nameable operator. */
3338 if (Op
->getKind() == OperatorInfo::Member
&& !Op
->getFlag())
3339 /* Not a nameable MemberExpr */
3342 return make
<NameType
>(Op
->getName());
3345 if (consumeIf("li")) {
3346 // ::= li <source-name> # operator ""
3347 Node
*SN
= getDerived().parseSourceName(State
);
3350 return make
<LiteralOperator
>(SN
);
3353 if (consumeIf('v')) {
3354 // ::= v <digit> <source-name> # vendor extended operator
3355 if (look() >= '0' && look() <= '9') {
3357 Node
*SN
= getDerived().parseSourceName(State
);
3360 return make
<ConversionOperatorType
>(SN
);
3368 // <ctor-dtor-name> ::= C1 # complete object constructor
3369 // ::= C2 # base object constructor
3370 // ::= C3 # complete object allocating constructor
3371 // extension ::= C4 # gcc old-style "[unified]" constructor
3372 // extension ::= C5 # the COMDAT used for ctors
3373 // ::= D0 # deleting destructor
3374 // ::= D1 # complete object destructor
3375 // ::= D2 # base object destructor
3376 // extension ::= D4 # gcc old-style "[unified]" destructor
3377 // extension ::= D5 # the COMDAT used for dtors
3378 template <typename Derived
, typename Alloc
>
3380 AbstractManglingParser
<Derived
, Alloc
>::parseCtorDtorName(Node
*&SoFar
,
3382 if (SoFar
->getKind() == Node::KSpecialSubstitution
) {
3383 // Expand the special substitution.
3384 SoFar
= make
<ExpandedSpecialSubstitution
>(
3385 static_cast<SpecialSubstitution
*>(SoFar
));
3390 if (consumeIf('C')) {
3391 bool IsInherited
= consumeIf('I');
3392 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3395 int Variant
= look() - '0';
3397 if (State
) State
->CtorDtorConversion
= true;
3399 if (getDerived().parseName(State
) == nullptr)
3402 return make
<CtorDtorName
>(SoFar
, /*IsDtor=*/false, Variant
);
3405 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3406 look(1) == '4' || look(1) == '5')) {
3407 int Variant
= look(1) - '0';
3409 if (State
) State
->CtorDtorConversion
= true;
3410 return make
<CtorDtorName
>(SoFar
, /*IsDtor=*/true, Variant
);
3416 // <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3417 // <unqualified-name> E
3418 // ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3419 // <template-args> E
3421 // <prefix> ::= <prefix> <unqualified-name>
3422 // ::= <template-prefix> <template-args>
3423 // ::= <template-param>
3426 // ::= <substitution>
3427 // ::= <prefix> <data-member-prefix>
3430 // <data-member-prefix> := <member source-name> [<template-args>] M
3432 // <template-prefix> ::= <prefix> <template unqualified-name>
3433 // ::= <template-param>
3434 // ::= <substitution>
3435 template <typename Derived
, typename Alloc
>
3437 AbstractManglingParser
<Derived
, Alloc
>::parseNestedName(NameState
*State
) {
3438 if (!consumeIf('N'))
3441 Qualifiers CVTmp
= parseCVQualifiers();
3442 if (State
) State
->CVQualifiers
= CVTmp
;
3444 if (consumeIf('O')) {
3445 if (State
) State
->ReferenceQualifier
= FrefQualRValue
;
3446 } else if (consumeIf('R')) {
3447 if (State
) State
->ReferenceQualifier
= FrefQualLValue
;
3449 if (State
) State
->ReferenceQualifier
= FrefQualNone
;
3452 Node
*SoFar
= nullptr;
3453 while (!consumeIf('E')) {
3455 // Only set end-with-template on the case that does that.
3456 State
->EndsWithTemplateArgs
= false;
3458 if (look() == 'T') {
3459 // ::= <template-param>
3460 if (SoFar
!= nullptr)
3461 return nullptr; // Cannot have a prefix.
3462 SoFar
= getDerived().parseTemplateParam();
3463 } else if (look() == 'I') {
3464 // ::= <template-prefix> <template-args>
3465 if (SoFar
== nullptr)
3466 return nullptr; // Must have a prefix.
3467 Node
*TA
= getDerived().parseTemplateArgs(State
!= nullptr);
3470 if (SoFar
->getKind() == Node::KNameWithTemplateArgs
)
3471 // Semantically <template-args> <template-args> cannot be generated by a
3472 // C++ entity. There will always be [something like] a name between
3476 State
->EndsWithTemplateArgs
= true;
3477 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3478 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3480 if (SoFar
!= nullptr)
3481 return nullptr; // Cannot have a prefix.
3482 SoFar
= getDerived().parseDecltype();
3484 ModuleName
*Module
= nullptr;
3486 if (look() == 'S') {
3487 // ::= <substitution>
3489 if (look(1) == 't') {
3491 S
= make
<NameType
>("std");
3493 S
= getDerived().parseSubstitution();
3497 if (S
->getKind() == Node::KModuleName
) {
3498 Module
= static_cast<ModuleName
*>(S
);
3499 } else if (SoFar
!= nullptr) {
3500 return nullptr; // Cannot have a prefix.
3503 continue; // Do not push a new substitution.
3507 // ::= [<prefix>] <unqualified-name>
3508 SoFar
= getDerived().parseUnqualifiedName(State
, SoFar
, Module
);
3511 if (SoFar
== nullptr)
3513 Subs
.push_back(SoFar
);
3516 // <data-member-prefix> := <member source-name> [<template-args>] M
3520 if (SoFar
== nullptr || Subs
.empty())
3527 // <simple-id> ::= <source-name> [ <template-args> ]
3528 template <typename Derived
, typename Alloc
>
3529 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSimpleId() {
3530 Node
*SN
= getDerived().parseSourceName(/*NameState=*/nullptr);
3533 if (look() == 'I') {
3534 Node
*TA
= getDerived().parseTemplateArgs();
3537 return make
<NameWithTemplateArgs
>(SN
, TA
);
3542 // <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3543 // ::= <simple-id> # e.g., ~A<2*N>
3544 template <typename Derived
, typename Alloc
>
3545 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseDestructorName() {
3547 if (std::isdigit(look()))
3548 Result
= getDerived().parseSimpleId();
3550 Result
= getDerived().parseUnresolvedType();
3551 if (Result
== nullptr)
3553 return make
<DtorName
>(Result
);
3556 // <unresolved-type> ::= <template-param>
3558 // ::= <substitution>
3559 template <typename Derived
, typename Alloc
>
3560 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnresolvedType() {
3561 if (look() == 'T') {
3562 Node
*TP
= getDerived().parseTemplateParam();
3568 if (look() == 'D') {
3569 Node
*DT
= getDerived().parseDecltype();
3575 return getDerived().parseSubstitution();
3578 // <base-unresolved-name> ::= <simple-id> # unresolved name
3579 // extension ::= <operator-name> # unresolved operator-function-id
3580 // extension ::= <operator-name> <template-args> # unresolved operator template-id
3581 // ::= on <operator-name> # unresolved operator-function-id
3582 // ::= on <operator-name> <template-args> # unresolved operator template-id
3583 // ::= dn <destructor-name> # destructor or pseudo-destructor;
3584 // # e.g. ~X or ~X<N-1>
3585 template <typename Derived
, typename Alloc
>
3586 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseBaseUnresolvedName() {
3587 if (std::isdigit(look()))
3588 return getDerived().parseSimpleId();
3590 if (consumeIf("dn"))
3591 return getDerived().parseDestructorName();
3595 Node
*Oper
= getDerived().parseOperatorName(/*NameState=*/nullptr);
3596 if (Oper
== nullptr)
3598 if (look() == 'I') {
3599 Node
*TA
= getDerived().parseTemplateArgs();
3602 return make
<NameWithTemplateArgs
>(Oper
, TA
);
3607 // <unresolved-name>
3608 // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3609 // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3610 // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3611 // # A::x, N::y, A<T>::z; "gs" means leading "::"
3612 // [gs] has been parsed by caller.
3613 // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3614 // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3615 // # T::N::x /decltype(p)::N::x
3616 // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3618 // <unresolved-qualifier-level> ::= <simple-id>
3619 template <typename Derived
, typename Alloc
>
3620 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnresolvedName(bool Global
) {
3621 Node
*SoFar
= nullptr;
3623 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3624 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3625 if (consumeIf("srN")) {
3626 SoFar
= getDerived().parseUnresolvedType();
3627 if (SoFar
== nullptr)
3630 if (look() == 'I') {
3631 Node
*TA
= getDerived().parseTemplateArgs();
3634 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3639 while (!consumeIf('E')) {
3640 Node
*Qual
= getDerived().parseSimpleId();
3641 if (Qual
== nullptr)
3643 SoFar
= make
<QualifiedName
>(SoFar
, Qual
);
3648 Node
*Base
= getDerived().parseBaseUnresolvedName();
3649 if (Base
== nullptr)
3651 return make
<QualifiedName
>(SoFar
, Base
);
3654 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3655 if (!consumeIf("sr")) {
3656 SoFar
= getDerived().parseBaseUnresolvedName();
3657 if (SoFar
== nullptr)
3660 SoFar
= make
<GlobalQualifiedName
>(SoFar
);
3664 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3665 if (std::isdigit(look())) {
3667 Node
*Qual
= getDerived().parseSimpleId();
3668 if (Qual
== nullptr)
3671 SoFar
= make
<QualifiedName
>(SoFar
, Qual
);
3673 SoFar
= make
<GlobalQualifiedName
>(Qual
);
3678 } while (!consumeIf('E'));
3680 // sr <unresolved-type> <base-unresolved-name>
3681 // sr <unresolved-type> <template-args> <base-unresolved-name>
3683 SoFar
= getDerived().parseUnresolvedType();
3684 if (SoFar
== nullptr)
3687 if (look() == 'I') {
3688 Node
*TA
= getDerived().parseTemplateArgs();
3691 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3697 assert(SoFar
!= nullptr);
3699 Node
*Base
= getDerived().parseBaseUnresolvedName();
3700 if (Base
== nullptr)
3702 return make
<QualifiedName
>(SoFar
, Base
);
3705 // <abi-tags> ::= <abi-tag> [<abi-tags>]
3706 // <abi-tag> ::= B <source-name>
3707 template <typename Derived
, typename Alloc
>
3708 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseAbiTags(Node
*N
) {
3709 while (consumeIf('B')) {
3710 std::string_view SN
= parseBareSourceName();
3713 N
= make
<AbiTagAttr
>(N
, SN
);
3720 // <number> ::= [n] <non-negative decimal integer>
3721 template <typename Alloc
, typename Derived
>
3723 AbstractManglingParser
<Alloc
, Derived
>::parseNumber(bool AllowNegative
) {
3724 const char *Tmp
= First
;
3727 if (numLeft() == 0 || !std::isdigit(*First
))
3728 return std::string_view();
3729 while (numLeft() != 0 && std::isdigit(*First
))
3731 return std::string_view(Tmp
, First
- Tmp
);
3734 // <positive length number> ::= [0-9]*
3735 template <typename Alloc
, typename Derived
>
3736 bool AbstractManglingParser
<Alloc
, Derived
>::parsePositiveInteger(size_t *Out
) {
3738 if (look() < '0' || look() > '9')
3740 while (look() >= '0' && look() <= '9') {
3742 *Out
+= static_cast<size_t>(consume() - '0');
3747 template <typename Alloc
, typename Derived
>
3748 std::string_view AbstractManglingParser
<Alloc
, Derived
>::parseBareSourceName() {
3750 if (parsePositiveInteger(&Int
) || numLeft() < Int
)
3752 std::string_view
R(First
, Int
);
3757 // <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3759 // <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3760 // ::= DO <expression> E # computed (instantiation-dependent) noexcept
3761 // ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3763 // <ref-qualifier> ::= R # & ref-qualifier
3764 // <ref-qualifier> ::= O # && ref-qualifier
3765 template <typename Derived
, typename Alloc
>
3766 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFunctionType() {
3767 Qualifiers CVQuals
= parseCVQualifiers();
3769 Node
*ExceptionSpec
= nullptr;
3770 if (consumeIf("Do")) {
3771 ExceptionSpec
= make
<NameType
>("noexcept");
3774 } else if (consumeIf("DO")) {
3775 Node
*E
= getDerived().parseExpr();
3776 if (E
== nullptr || !consumeIf('E'))
3778 ExceptionSpec
= make
<NoexceptSpec
>(E
);
3781 } else if (consumeIf("Dw")) {
3782 size_t SpecsBegin
= Names
.size();
3783 while (!consumeIf('E')) {
3784 Node
*T
= getDerived().parseType();
3790 make
<DynamicExceptionSpec
>(popTrailingNodeArray(SpecsBegin
));
3795 consumeIf("Dx"); // transaction safe
3797 if (!consumeIf('F'))
3799 consumeIf('Y'); // extern "C"
3800 Node
*ReturnType
= getDerived().parseType();
3801 if (ReturnType
== nullptr)
3804 FunctionRefQual ReferenceQualifier
= FrefQualNone
;
3805 size_t ParamsBegin
= Names
.size();
3811 if (consumeIf("RE")) {
3812 ReferenceQualifier
= FrefQualLValue
;
3815 if (consumeIf("OE")) {
3816 ReferenceQualifier
= FrefQualRValue
;
3819 Node
*T
= getDerived().parseType();
3825 NodeArray Params
= popTrailingNodeArray(ParamsBegin
);
3826 return make
<FunctionType
>(ReturnType
, Params
, CVQuals
,
3827 ReferenceQualifier
, ExceptionSpec
);
3831 // <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3832 // ::= Dv [<dimension expression>] _ <element type>
3833 // <extended element type> ::= <element type>
3834 // ::= p # AltiVec vector pixel
3835 template <typename Derived
, typename Alloc
>
3836 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseVectorType() {
3837 if (!consumeIf("Dv"))
3839 if (look() >= '1' && look() <= '9') {
3840 Node
*DimensionNumber
= make
<NameType
>(parseNumber());
3841 if (!DimensionNumber
)
3843 if (!consumeIf('_'))
3846 return make
<PixelVectorType
>(DimensionNumber
);
3847 Node
*ElemType
= getDerived().parseType();
3848 if (ElemType
== nullptr)
3850 return make
<VectorType
>(ElemType
, DimensionNumber
);
3853 if (!consumeIf('_')) {
3854 Node
*DimExpr
= getDerived().parseExpr();
3857 if (!consumeIf('_'))
3859 Node
*ElemType
= getDerived().parseType();
3862 return make
<VectorType
>(ElemType
, DimExpr
);
3864 Node
*ElemType
= getDerived().parseType();
3867 return make
<VectorType
>(ElemType
, /*Dimension=*/nullptr);
3870 // <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3871 // ::= DT <expression> E # decltype of an expression (C++0x)
3872 template <typename Derived
, typename Alloc
>
3873 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseDecltype() {
3874 if (!consumeIf('D'))
3876 if (!consumeIf('t') && !consumeIf('T'))
3878 Node
*E
= getDerived().parseExpr();
3881 if (!consumeIf('E'))
3883 return make
<EnclosingExpr
>("decltype", E
);
3886 // <array-type> ::= A <positive dimension number> _ <element type>
3887 // ::= A [<dimension expression>] _ <element type>
3888 template <typename Derived
, typename Alloc
>
3889 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseArrayType() {
3890 if (!consumeIf('A'))
3893 Node
*Dimension
= nullptr;
3895 if (std::isdigit(look())) {
3896 Dimension
= make
<NameType
>(parseNumber());
3899 if (!consumeIf('_'))
3901 } else if (!consumeIf('_')) {
3902 Node
*DimExpr
= getDerived().parseExpr();
3903 if (DimExpr
== nullptr)
3905 if (!consumeIf('_'))
3907 Dimension
= DimExpr
;
3910 Node
*Ty
= getDerived().parseType();
3913 return make
<ArrayType
>(Ty
, Dimension
);
3916 // <pointer-to-member-type> ::= M <class type> <member type>
3917 template <typename Derived
, typename Alloc
>
3918 Node
*AbstractManglingParser
<Derived
, Alloc
>::parsePointerToMemberType() {
3919 if (!consumeIf('M'))
3921 Node
*ClassType
= getDerived().parseType();
3922 if (ClassType
== nullptr)
3924 Node
*MemberType
= getDerived().parseType();
3925 if (MemberType
== nullptr)
3927 return make
<PointerToMemberType
>(ClassType
, MemberType
);
3930 // <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3931 // ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3932 // ::= Tu <name> # dependent elaborated type specifier using 'union'
3933 // ::= Te <name> # dependent elaborated type specifier using 'enum'
3934 template <typename Derived
, typename Alloc
>
3935 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseClassEnumType() {
3936 std::string_view ElabSpef
;
3937 if (consumeIf("Ts"))
3938 ElabSpef
= "struct";
3939 else if (consumeIf("Tu"))
3941 else if (consumeIf("Te"))
3944 Node
*Name
= getDerived().parseName();
3945 if (Name
== nullptr)
3948 if (!ElabSpef
.empty())
3949 return make
<ElaboratedTypeSpefType
>(ElabSpef
, Name
);
3954 // <qualified-type> ::= <qualifiers> <type>
3955 // <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3956 // <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
3957 template <typename Derived
, typename Alloc
>
3958 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseQualifiedType() {
3959 if (consumeIf('U')) {
3960 std::string_view Qual
= parseBareSourceName();
3964 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3965 if (starts_with(Qual
, "objcproto")) {
3966 constexpr size_t Len
= sizeof("objcproto") - 1;
3967 std::string_view
ProtoSourceName(Qual
.data() + Len
, Qual
.size() - Len
);
3968 std::string_view Proto
;
3970 ScopedOverride
<const char *> SaveFirst(First
, ProtoSourceName
.data()),
3971 SaveLast(Last
, &*ProtoSourceName
.rbegin() + 1);
3972 Proto
= parseBareSourceName();
3976 Node
*Child
= getDerived().parseQualifiedType();
3977 if (Child
== nullptr)
3979 return make
<ObjCProtoName
>(Child
, Proto
);
3983 if (look() == 'I') {
3984 TA
= getDerived().parseTemplateArgs();
3989 Node
*Child
= getDerived().parseQualifiedType();
3990 if (Child
== nullptr)
3992 return make
<VendorExtQualType
>(Child
, Qual
, TA
);
3995 Qualifiers Quals
= parseCVQualifiers();
3996 Node
*Ty
= getDerived().parseType();
3999 if (Quals
!= QualNone
)
4000 Ty
= make
<QualType
>(Ty
, Quals
);
4004 // <type> ::= <builtin-type>
4005 // ::= <qualified-type>
4006 // ::= <function-type>
4007 // ::= <class-enum-type>
4009 // ::= <pointer-to-member-type>
4010 // ::= <template-param>
4011 // ::= <template-template-param> <template-args>
4013 // ::= P <type> # pointer
4014 // ::= R <type> # l-value reference
4015 // ::= O <type> # r-value reference (C++11)
4016 // ::= C <type> # complex pair (C99)
4017 // ::= G <type> # imaginary (C99)
4018 // ::= <substitution> # See Compression below
4019 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
4020 // extension ::= <vector-type> # <vector-type> starts with Dv
4022 // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
4023 // <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
4024 template <typename Derived
, typename Alloc
>
4025 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseType() {
4026 Node
*Result
= nullptr;
4029 // ::= <qualified-type>
4033 unsigned AfterQuals
= 0;
4034 if (look(AfterQuals
) == 'r') ++AfterQuals
;
4035 if (look(AfterQuals
) == 'V') ++AfterQuals
;
4036 if (look(AfterQuals
) == 'K') ++AfterQuals
;
4038 if (look(AfterQuals
) == 'F' ||
4039 (look(AfterQuals
) == 'D' &&
4040 (look(AfterQuals
+ 1) == 'o' || look(AfterQuals
+ 1) == 'O' ||
4041 look(AfterQuals
+ 1) == 'w' || look(AfterQuals
+ 1) == 'x'))) {
4042 Result
= getDerived().parseFunctionType();
4045 DEMANGLE_FALLTHROUGH
;
4048 Result
= getDerived().parseQualifiedType();
4051 // <builtin-type> ::= v # void
4054 return make
<NameType
>("void");
4058 return make
<NameType
>("wchar_t");
4062 return make
<NameType
>("bool");
4066 return make
<NameType
>("char");
4067 // ::= a # signed char
4070 return make
<NameType
>("signed char");
4071 // ::= h # unsigned char
4074 return make
<NameType
>("unsigned char");
4078 return make
<NameType
>("short");
4079 // ::= t # unsigned short
4082 return make
<NameType
>("unsigned short");
4086 return make
<NameType
>("int");
4087 // ::= j # unsigned int
4090 return make
<NameType
>("unsigned int");
4094 return make
<NameType
>("long");
4095 // ::= m # unsigned long
4098 return make
<NameType
>("unsigned long");
4099 // ::= x # long long, __int64
4102 return make
<NameType
>("long long");
4103 // ::= y # unsigned long long, __int64
4106 return make
<NameType
>("unsigned long long");
4110 return make
<NameType
>("__int128");
4111 // ::= o # unsigned __int128
4114 return make
<NameType
>("unsigned __int128");
4118 return make
<NameType
>("float");
4122 return make
<NameType
>("double");
4123 // ::= e # long double, __float80
4126 return make
<NameType
>("long double");
4127 // ::= g # __float128
4130 return make
<NameType
>("__float128");
4134 return make
<NameType
>("...");
4136 // <builtin-type> ::= u <source-name> # vendor extended type
4139 std::string_view Res
= parseBareSourceName();
4142 // Typically, <builtin-type>s are not considered substitution candidates,
4143 // but the exception to that exception is vendor extended types (Itanium C++
4145 if (consumeIf('I')) {
4146 Node
*BaseType
= parseType();
4147 if (BaseType
== nullptr)
4149 if (!consumeIf('E'))
4151 Result
= make
<TransformedType
>(Res
, BaseType
);
4153 Result
= make
<NameType
>(Res
);
4158 // ::= Dd # IEEE 754r decimal floating point (64 bits)
4161 return make
<NameType
>("decimal64");
4162 // ::= De # IEEE 754r decimal floating point (128 bits)
4165 return make
<NameType
>("decimal128");
4166 // ::= Df # IEEE 754r decimal floating point (32 bits)
4169 return make
<NameType
>("decimal32");
4170 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
4173 return make
<NameType
>("half");
4174 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
4177 Node
*DimensionNumber
= make
<NameType
>(parseNumber());
4178 if (!DimensionNumber
)
4180 if (!consumeIf('_'))
4182 return make
<BinaryFPType
>(DimensionNumber
);
4184 // ::= DB <number> _ # C23 signed _BitInt(N)
4185 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
4186 // ::= DU <number> _ # C23 unsigned _BitInt(N)
4187 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
4190 bool Signed
= look(1) == 'B';
4192 Node
*Size
= std::isdigit(look()) ? make
<NameType
>(parseNumber())
4193 : getDerived().parseExpr();
4196 if (!consumeIf('_'))
4198 return make
<BitIntType
>(Size
, Signed
);
4200 // ::= Di # char32_t
4203 return make
<NameType
>("char32_t");
4204 // ::= Ds # char16_t
4207 return make
<NameType
>("char16_t");
4208 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
4211 return make
<NameType
>("char8_t");
4212 // ::= Da # auto (in dependent new-expressions)
4215 return make
<NameType
>("auto");
4216 // ::= Dc # decltype(auto)
4219 return make
<NameType
>("decltype(auto)");
4220 // ::= Dk <type-constraint> # constrained auto
4221 // ::= DK <type-constraint> # constrained decltype(auto)
4224 std::string_view Kind
= look(1) == 'k' ? " auto" : " decltype(auto)";
4226 Node
*Constraint
= getDerived().parseName();
4229 return make
<PostfixQualifiedType
>(Constraint
, Kind
);
4231 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
4234 return make
<NameType
>("std::nullptr_t");
4239 Result
= getDerived().parseDecltype();
4242 // extension ::= <vector-type> # <vector-type> starts with Dv
4244 Result
= getDerived().parseVectorType();
4247 // ::= Dp <type> # pack expansion (C++0x)
4250 Node
*Child
= getDerived().parseType();
4253 Result
= make
<ParameterPackExpansion
>(Child
);
4256 // Exception specifier on a function type.
4260 // Transaction safe function type.
4262 Result
= getDerived().parseFunctionType();
4266 // ::= <function-type>
4268 Result
= getDerived().parseFunctionType();
4273 Result
= getDerived().parseArrayType();
4276 // ::= <pointer-to-member-type>
4278 Result
= getDerived().parsePointerToMemberType();
4281 // ::= <template-param>
4283 // This could be an elaborate type specifier on a <class-enum-type>.
4284 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
4285 Result
= getDerived().parseClassEnumType();
4289 Result
= getDerived().parseTemplateParam();
4290 if (Result
== nullptr)
4293 // Result could be either of:
4294 // <type> ::= <template-param>
4295 // <type> ::= <template-template-param> <template-args>
4297 // <template-template-param> ::= <template-param>
4298 // ::= <substitution>
4300 // If this is followed by some <template-args>, and we're permitted to
4301 // parse them, take the second production.
4303 if (TryToParseTemplateArgs
&& look() == 'I') {
4304 Node
*TA
= getDerived().parseTemplateArgs();
4307 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
4311 // ::= P <type> # pointer
4314 Node
*Ptr
= getDerived().parseType();
4317 Result
= make
<PointerType
>(Ptr
);
4320 // ::= R <type> # l-value reference
4323 Node
*Ref
= getDerived().parseType();
4326 Result
= make
<ReferenceType
>(Ref
, ReferenceKind::LValue
);
4329 // ::= O <type> # r-value reference (C++11)
4332 Node
*Ref
= getDerived().parseType();
4335 Result
= make
<ReferenceType
>(Ref
, ReferenceKind::RValue
);
4338 // ::= C <type> # complex pair (C99)
4341 Node
*P
= getDerived().parseType();
4344 Result
= make
<PostfixQualifiedType
>(P
, " complex");
4347 // ::= G <type> # imaginary (C99)
4350 Node
*P
= getDerived().parseType();
4353 Result
= make
<PostfixQualifiedType
>(P
, " imaginary");
4356 // ::= <substitution> # See Compression below
4358 if (look(1) != 't') {
4359 bool IsSubst
= false;
4360 Result
= getDerived().parseUnscopedName(nullptr, &IsSubst
);
4364 // Sub could be either of:
4365 // <type> ::= <substitution>
4366 // <type> ::= <template-template-param> <template-args>
4368 // <template-template-param> ::= <template-param>
4369 // ::= <substitution>
4371 // If this is followed by some <template-args>, and we're permitted to
4372 // parse them, take the second production.
4374 if (look() == 'I' && (!IsSubst
|| TryToParseTemplateArgs
)) {
4376 Subs
.push_back(Result
);
4377 Node
*TA
= getDerived().parseTemplateArgs();
4380 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
4381 } else if (IsSubst
) {
4382 // If all we parsed was a substitution, don't re-insert into the
4383 // substitution table.
4388 DEMANGLE_FALLTHROUGH
;
4390 // ::= <class-enum-type>
4392 Result
= getDerived().parseClassEnumType();
4397 // If we parsed a type, insert it into the substitution table. Note that all
4398 // <builtin-type>s and <substitution>s have already bailed out, because they
4399 // don't get substitutions.
4400 if (Result
!= nullptr)
4401 Subs
.push_back(Result
);
4405 template <typename Derived
, typename Alloc
>
4407 AbstractManglingParser
<Derived
, Alloc
>::parsePrefixExpr(std::string_view Kind
,
4409 Node
*E
= getDerived().parseExpr();
4412 return make
<PrefixExpr
>(Kind
, E
, Prec
);
4415 template <typename Derived
, typename Alloc
>
4417 AbstractManglingParser
<Derived
, Alloc
>::parseBinaryExpr(std::string_view Kind
,
4419 Node
*LHS
= getDerived().parseExpr();
4422 Node
*RHS
= getDerived().parseExpr();
4425 return make
<BinaryExpr
>(LHS
, Kind
, RHS
, Prec
);
4428 template <typename Derived
, typename Alloc
>
4429 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseIntegerLiteral(
4430 std::string_view Lit
) {
4431 std::string_view Tmp
= parseNumber(true);
4432 if (!Tmp
.empty() && consumeIf('E'))
4433 return make
<IntegerLiteral
>(Lit
, Tmp
);
4437 // <CV-Qualifiers> ::= [r] [V] [K]
4438 template <typename Alloc
, typename Derived
>
4439 Qualifiers AbstractManglingParser
<Alloc
, Derived
>::parseCVQualifiers() {
4440 Qualifiers CVR
= QualNone
;
4442 CVR
|= QualRestrict
;
4444 CVR
|= QualVolatile
;
4450 // <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4451 // ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4452 // ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4453 // ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
4454 // ::= fpT # 'this' expression (not part of standard?)
4455 template <typename Derived
, typename Alloc
>
4456 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFunctionParam() {
4457 if (consumeIf("fpT"))
4458 return make
<NameType
>("this");
4459 if (consumeIf("fp")) {
4460 parseCVQualifiers();
4461 std::string_view Num
= parseNumber();
4462 if (!consumeIf('_'))
4464 return make
<FunctionParam
>(Num
);
4466 if (consumeIf("fL")) {
4467 if (parseNumber().empty())
4469 if (!consumeIf('p'))
4471 parseCVQualifiers();
4472 std::string_view Num
= parseNumber();
4473 if (!consumeIf('_'))
4475 return make
<FunctionParam
>(Num
);
4480 // cv <type> <expression> # conversion with one argument
4481 // cv <type> _ <expression>* E # conversion with a different number of arguments
4482 template <typename Derived
, typename Alloc
>
4483 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseConversionExpr() {
4484 if (!consumeIf("cv"))
4488 ScopedOverride
<bool> SaveTemp(TryToParseTemplateArgs
, false);
4489 Ty
= getDerived().parseType();
4495 if (consumeIf('_')) {
4496 size_t ExprsBegin
= Names
.size();
4497 while (!consumeIf('E')) {
4498 Node
*E
= getDerived().parseExpr();
4503 NodeArray Exprs
= popTrailingNodeArray(ExprsBegin
);
4504 return make
<ConversionExpr
>(Ty
, Exprs
);
4507 Node
*E
[1] = {getDerived().parseExpr()};
4508 if (E
[0] == nullptr)
4510 return make
<ConversionExpr
>(Ty
, makeNodeArray(E
, E
+ 1));
4513 // <expr-primary> ::= L <type> <value number> E # integer literal
4514 // ::= L <type> <value float> E # floating literal
4515 // ::= L <string type> E # string literal
4516 // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
4517 // ::= L <lambda type> E # lambda expression
4518 // FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4519 // ::= L <mangled-name> E # external name
4520 template <typename Derived
, typename Alloc
>
4521 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseExprPrimary() {
4522 if (!consumeIf('L'))
4527 return getDerived().parseIntegerLiteral("wchar_t");
4529 if (consumeIf("b0E"))
4530 return make
<BoolExpr
>(0);
4531 if (consumeIf("b1E"))
4532 return make
<BoolExpr
>(1);
4536 return getDerived().parseIntegerLiteral("char");
4539 return getDerived().parseIntegerLiteral("signed char");
4542 return getDerived().parseIntegerLiteral("unsigned char");
4545 return getDerived().parseIntegerLiteral("short");
4548 return getDerived().parseIntegerLiteral("unsigned short");
4551 return getDerived().parseIntegerLiteral("");
4554 return getDerived().parseIntegerLiteral("u");
4557 return getDerived().parseIntegerLiteral("l");
4560 return getDerived().parseIntegerLiteral("ul");
4563 return getDerived().parseIntegerLiteral("ll");
4566 return getDerived().parseIntegerLiteral("ull");
4569 return getDerived().parseIntegerLiteral("__int128");
4572 return getDerived().parseIntegerLiteral("unsigned __int128");
4575 return getDerived().template parseFloatingLiteral
<float>();
4578 return getDerived().template parseFloatingLiteral
<double>();
4581 #if defined(__powerpc__) || defined(__s390__)
4582 // Handle cases where long doubles encoded with e have the same size
4583 // and representation as doubles.
4584 return getDerived().template parseFloatingLiteral
<double>();
4586 return getDerived().template parseFloatingLiteral
<long double>();
4589 if (consumeIf("_Z")) {
4590 Node
*R
= getDerived().parseEncoding();
4591 if (R
!= nullptr && consumeIf('E'))
4596 Node
*T
= getDerived().parseType();
4599 // FIXME: We need to include the string contents in the mangling.
4601 return make
<StringLiteral
>(T
);
4605 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
4606 return make
<NameType
>("nullptr");
4609 // Invalid mangled name per
4610 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4613 // FIXME: Should we support LUb... for block literals?
4616 Node
*T
= parseUnnamedTypeName(nullptr);
4617 if (!T
|| !consumeIf('E'))
4619 return make
<LambdaExpr
>(T
);
4622 // might be named type
4623 Node
*T
= getDerived().parseType();
4626 std::string_view N
= parseNumber(/*AllowNegative=*/true);
4629 if (!consumeIf('E'))
4631 return make
<EnumLiteral
>(T
, N
);
4636 // <braced-expression> ::= <expression>
4637 // ::= di <field source-name> <braced-expression> # .name = expr
4638 // ::= dx <index expression> <braced-expression> # [expr] = expr
4639 // ::= dX <range begin expression> <range end expression> <braced-expression>
4640 template <typename Derived
, typename Alloc
>
4641 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseBracedExpr() {
4642 if (look() == 'd') {
4646 Node
*Field
= getDerived().parseSourceName(/*NameState=*/nullptr);
4647 if (Field
== nullptr)
4649 Node
*Init
= getDerived().parseBracedExpr();
4650 if (Init
== nullptr)
4652 return make
<BracedExpr
>(Field
, Init
, /*isArray=*/false);
4656 Node
*Index
= getDerived().parseExpr();
4657 if (Index
== nullptr)
4659 Node
*Init
= getDerived().parseBracedExpr();
4660 if (Init
== nullptr)
4662 return make
<BracedExpr
>(Index
, Init
, /*isArray=*/true);
4666 Node
*RangeBegin
= getDerived().parseExpr();
4667 if (RangeBegin
== nullptr)
4669 Node
*RangeEnd
= getDerived().parseExpr();
4670 if (RangeEnd
== nullptr)
4672 Node
*Init
= getDerived().parseBracedExpr();
4673 if (Init
== nullptr)
4675 return make
<BracedRangeExpr
>(RangeBegin
, RangeEnd
, Init
);
4679 return getDerived().parseExpr();
4682 // (not yet in the spec)
4683 // <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4684 // ::= fR <binary-operator-name> <expression> <expression>
4685 // ::= fl <binary-operator-name> <expression>
4686 // ::= fr <binary-operator-name> <expression>
4687 template <typename Derived
, typename Alloc
>
4688 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFoldExpr() {
4689 if (!consumeIf('f'))
4692 bool IsLeftFold
= false, HasInitializer
= false;
4698 HasInitializer
= true;
4701 HasInitializer
= true;
4711 const auto *Op
= parseOperatorEncoding();
4714 if (!(Op
->getKind() == OperatorInfo::Binary
4715 || (Op
->getKind() == OperatorInfo::Member
4716 && Op
->getName().back() == '*')))
4719 Node
*Pack
= getDerived().parseExpr();
4720 if (Pack
== nullptr)
4723 Node
*Init
= nullptr;
4724 if (HasInitializer
) {
4725 Init
= getDerived().parseExpr();
4726 if (Init
== nullptr)
4730 if (IsLeftFold
&& Init
)
4731 std::swap(Pack
, Init
);
4733 return make
<FoldExpr
>(IsLeftFold
, Op
->getSymbol(), Pack
, Init
);
4736 // <expression> ::= mc <parameter type> <expr> [<offset number>] E
4738 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4739 template <typename Derived
, typename Alloc
>
4741 AbstractManglingParser
<Derived
, Alloc
>::parsePointerToMemberConversionExpr(
4743 Node
*Ty
= getDerived().parseType();
4746 Node
*Expr
= getDerived().parseExpr();
4749 std::string_view Offset
= getDerived().parseNumber(true);
4750 if (!consumeIf('E'))
4752 return make
<PointerToMemberConversionExpr
>(Ty
, Expr
, Offset
, Prec
);
4755 // <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4756 // <union-selector> ::= _ [<number>]
4758 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4759 template <typename Derived
, typename Alloc
>
4760 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSubobjectExpr() {
4761 Node
*Ty
= getDerived().parseType();
4764 Node
*Expr
= getDerived().parseExpr();
4767 std::string_view Offset
= getDerived().parseNumber(true);
4768 size_t SelectorsBegin
= Names
.size();
4769 while (consumeIf('_')) {
4770 Node
*Selector
= make
<NameType
>(parseNumber());
4773 Names
.push_back(Selector
);
4775 bool OnePastTheEnd
= consumeIf('p');
4776 if (!consumeIf('E'))
4778 return make
<SubobjectExpr
>(
4779 Ty
, Expr
, Offset
, popTrailingNodeArray(SelectorsBegin
), OnePastTheEnd
);
4782 template <typename Derived
, typename Alloc
>
4783 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseConstraintExpr() {
4784 // Within this expression, all enclosing template parameter lists are in
4786 ScopedOverride
<bool> SaveInConstraintExpr(InConstraintExpr
, true);
4787 return getDerived().parseExpr();
4790 template <typename Derived
, typename Alloc
>
4791 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseRequiresExpr() {
4793 if (consumeIf("rQ")) {
4794 // <expression> ::= rQ <bare-function-type> _ <requirement>+ E
4795 size_t ParamsBegin
= Names
.size();
4796 while (!consumeIf('_')) {
4797 Node
*Type
= getDerived().parseType();
4798 if (Type
== nullptr)
4800 Names
.push_back(Type
);
4802 Params
= popTrailingNodeArray(ParamsBegin
);
4803 } else if (!consumeIf("rq")) {
4804 // <expression> ::= rq <requirement>+ E
4808 size_t ReqsBegin
= Names
.size();
4810 Node
*Constraint
= nullptr;
4811 if (consumeIf('X')) {
4812 // <requirement> ::= X <expression> [N] [R <type-constraint>]
4813 Node
*Expr
= getDerived().parseExpr();
4814 if (Expr
== nullptr)
4816 bool Noexcept
= consumeIf('N');
4817 Node
*TypeReq
= nullptr;
4818 if (consumeIf('R')) {
4819 TypeReq
= getDerived().parseName();
4820 if (TypeReq
== nullptr)
4823 Constraint
= make
<ExprRequirement
>(Expr
, Noexcept
, TypeReq
);
4824 } else if (consumeIf('T')) {
4825 // <requirement> ::= T <type>
4826 Node
*Type
= getDerived().parseType();
4827 if (Type
== nullptr)
4829 Constraint
= make
<TypeRequirement
>(Type
);
4830 } else if (consumeIf('Q')) {
4831 // <requirement> ::= Q <constraint-expression>
4833 // FIXME: We use <expression> instead of <constraint-expression>. Either
4834 // the requires expression is already inside a constraint expression, in
4835 // which case it makes no difference, or we're in a requires-expression
4836 // that might be partially-substituted, where the language behavior is
4837 // not yet settled and clang mangles after substitution.
4838 Node
*NestedReq
= getDerived().parseExpr();
4839 if (NestedReq
== nullptr)
4841 Constraint
= make
<NestedRequirement
>(NestedReq
);
4843 if (Constraint
== nullptr)
4845 Names
.push_back(Constraint
);
4846 } while (!consumeIf('E'));
4848 return make
<RequiresExpr
>(Params
, popTrailingNodeArray(ReqsBegin
));
4851 // <expression> ::= <unary operator-name> <expression>
4852 // ::= <binary operator-name> <expression> <expression>
4853 // ::= <ternary operator-name> <expression> <expression> <expression>
4854 // ::= cl <expression>+ E # call
4855 // ::= cv <type> <expression> # conversion with one argument
4856 // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4857 // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4858 // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4859 // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4860 // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4861 // ::= [gs] dl <expression> # delete expression
4862 // ::= [gs] da <expression> # delete[] expression
4863 // ::= pp_ <expression> # prefix ++
4864 // ::= mm_ <expression> # prefix --
4865 // ::= ti <type> # typeid (type)
4866 // ::= te <expression> # typeid (expression)
4867 // ::= dc <type> <expression> # dynamic_cast<type> (expression)
4868 // ::= sc <type> <expression> # static_cast<type> (expression)
4869 // ::= cc <type> <expression> # const_cast<type> (expression)
4870 // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4871 // ::= st <type> # sizeof (a type)
4872 // ::= sz <expression> # sizeof (an expression)
4873 // ::= at <type> # alignof (a type)
4874 // ::= az <expression> # alignof (an expression)
4875 // ::= nx <expression> # noexcept (expression)
4876 // ::= <template-param>
4877 // ::= <function-param>
4878 // ::= dt <expression> <unresolved-name> # expr.name
4879 // ::= pt <expression> <unresolved-name> # expr->name
4880 // ::= ds <expression> <expression> # expr.*expr
4881 // ::= sZ <template-param> # size of a parameter pack
4882 // ::= sZ <function-param> # size of a function parameter pack
4883 // ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4884 // ::= sp <expression> # pack expansion
4885 // ::= tw <expression> # throw expression
4886 // ::= tr # throw with no operand (rethrow)
4887 // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4888 // # freestanding dependent name (e.g., T::x),
4889 // # objectless nonstatic member reference
4890 // ::= fL <binary-operator-name> <expression> <expression>
4891 // ::= fR <binary-operator-name> <expression> <expression>
4892 // ::= fl <binary-operator-name> <expression>
4893 // ::= fr <binary-operator-name> <expression>
4894 // ::= <expr-primary>
4895 template <typename Derived
, typename Alloc
>
4896 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseExpr() {
4897 bool Global
= consumeIf("gs");
4899 const auto *Op
= parseOperatorEncoding();
4901 auto Sym
= Op
->getSymbol();
4902 switch (Op
->getKind()) {
4903 case OperatorInfo::Binary
:
4904 // Binary operator: lhs @ rhs
4905 return getDerived().parseBinaryExpr(Sym
, Op
->getPrecedence());
4906 case OperatorInfo::Prefix
:
4907 // Prefix unary operator: @ expr
4908 return getDerived().parsePrefixExpr(Sym
, Op
->getPrecedence());
4909 case OperatorInfo::Postfix
: {
4910 // Postfix unary operator: expr @
4912 return getDerived().parsePrefixExpr(Sym
, Op
->getPrecedence());
4913 Node
*Ex
= getDerived().parseExpr();
4916 return make
<PostfixExpr
>(Ex
, Sym
, Op
->getPrecedence());
4918 case OperatorInfo::Array
: {
4919 // Array Index: lhs [ rhs ]
4920 Node
*Base
= getDerived().parseExpr();
4921 if (Base
== nullptr)
4923 Node
*Index
= getDerived().parseExpr();
4924 if (Index
== nullptr)
4926 return make
<ArraySubscriptExpr
>(Base
, Index
, Op
->getPrecedence());
4928 case OperatorInfo::Member
: {
4929 // Member access lhs @ rhs
4930 Node
*LHS
= getDerived().parseExpr();
4933 Node
*RHS
= getDerived().parseExpr();
4936 return make
<MemberExpr
>(LHS
, Sym
, RHS
, Op
->getPrecedence());
4938 case OperatorInfo::New
: {
4940 // # new (expr-list) type [(init)]
4941 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4942 // # new[] (expr-list) type [(init)]
4943 // [gs] na <expression>* _ <type> [pi <expression>*] E
4944 size_t Exprs
= Names
.size();
4945 while (!consumeIf('_')) {
4946 Node
*Ex
= getDerived().parseExpr();
4949 Names
.push_back(Ex
);
4951 NodeArray ExprList
= popTrailingNodeArray(Exprs
);
4952 Node
*Ty
= getDerived().parseType();
4955 bool HaveInits
= consumeIf("pi");
4956 size_t InitsBegin
= Names
.size();
4957 while (!consumeIf('E')) {
4960 Node
*Init
= getDerived().parseExpr();
4961 if (Init
== nullptr)
4963 Names
.push_back(Init
);
4965 NodeArray Inits
= popTrailingNodeArray(InitsBegin
);
4966 return make
<NewExpr
>(ExprList
, Ty
, Inits
, Global
,
4967 /*IsArray=*/Op
->getFlag(), Op
->getPrecedence());
4969 case OperatorInfo::Del
: {
4971 Node
*Ex
= getDerived().parseExpr();
4974 return make
<DeleteExpr
>(Ex
, Global
, /*IsArray=*/Op
->getFlag(),
4975 Op
->getPrecedence());
4977 case OperatorInfo::Call
: {
4979 Node
*Callee
= getDerived().parseExpr();
4980 if (Callee
== nullptr)
4982 size_t ExprsBegin
= Names
.size();
4983 while (!consumeIf('E')) {
4984 Node
*E
= getDerived().parseExpr();
4989 return make
<CallExpr
>(Callee
, popTrailingNodeArray(ExprsBegin
),
4990 Op
->getPrecedence());
4992 case OperatorInfo::CCast
: {
4993 // C Cast: (type)expr
4996 ScopedOverride
<bool> SaveTemp(TryToParseTemplateArgs
, false);
4997 Ty
= getDerived().parseType();
5002 size_t ExprsBegin
= Names
.size();
5003 bool IsMany
= consumeIf('_');
5004 while (!consumeIf('E')) {
5005 Node
*E
= getDerived().parseExpr();
5012 NodeArray Exprs
= popTrailingNodeArray(ExprsBegin
);
5013 if (!IsMany
&& Exprs
.size() != 1)
5015 return make
<ConversionExpr
>(Ty
, Exprs
, Op
->getPrecedence());
5017 case OperatorInfo::Conditional
: {
5018 // Conditional operator: expr ? expr : expr
5019 Node
*Cond
= getDerived().parseExpr();
5020 if (Cond
== nullptr)
5022 Node
*LHS
= getDerived().parseExpr();
5025 Node
*RHS
= getDerived().parseExpr();
5028 return make
<ConditionalExpr
>(Cond
, LHS
, RHS
, Op
->getPrecedence());
5030 case OperatorInfo::NamedCast
: {
5031 // Named cast operation, @<type>(expr)
5032 Node
*Ty
= getDerived().parseType();
5035 Node
*Ex
= getDerived().parseExpr();
5038 return make
<CastExpr
>(Sym
, Ty
, Ex
, Op
->getPrecedence());
5040 case OperatorInfo::OfIdOp
: {
5041 // [sizeof/alignof/typeid] ( <type>|<expr> )
5043 Op
->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
5046 return make
<EnclosingExpr
>(Sym
, Arg
, Op
->getPrecedence());
5048 case OperatorInfo::NameOnly
: {
5049 // Not valid as an expression operand.
5053 DEMANGLE_UNREACHABLE
;
5060 return getDerived().parseExprPrimary();
5062 return getDerived().parseTemplateParam();
5063 if (look() == 'f') {
5064 // Disambiguate a fold expression from a <function-param>.
5065 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
5066 return getDerived().parseFunctionParam();
5067 return getDerived().parseFoldExpr();
5069 if (consumeIf("il")) {
5070 size_t InitsBegin
= Names
.size();
5071 while (!consumeIf('E')) {
5072 Node
*E
= getDerived().parseBracedExpr();
5077 return make
<InitListExpr
>(nullptr, popTrailingNodeArray(InitsBegin
));
5079 if (consumeIf("mc"))
5080 return parsePointerToMemberConversionExpr(Node::Prec::Unary
);
5081 if (consumeIf("nx")) {
5082 Node
*Ex
= getDerived().parseExpr();
5085 return make
<EnclosingExpr
>("noexcept ", Ex
, Node::Prec::Unary
);
5087 if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q'))
5088 return parseRequiresExpr();
5089 if (consumeIf("so"))
5090 return parseSubobjectExpr();
5091 if (consumeIf("sp")) {
5092 Node
*Child
= getDerived().parseExpr();
5093 if (Child
== nullptr)
5095 return make
<ParameterPackExpansion
>(Child
);
5097 if (consumeIf("sZ")) {
5098 if (look() == 'T') {
5099 Node
*R
= getDerived().parseTemplateParam();
5102 return make
<SizeofParamPackExpr
>(R
);
5104 Node
*FP
= getDerived().parseFunctionParam();
5107 return make
<EnclosingExpr
>("sizeof... ", FP
);
5109 if (consumeIf("sP")) {
5110 size_t ArgsBegin
= Names
.size();
5111 while (!consumeIf('E')) {
5112 Node
*Arg
= getDerived().parseTemplateArg();
5115 Names
.push_back(Arg
);
5117 auto *Pack
= make
<NodeArrayNode
>(popTrailingNodeArray(ArgsBegin
));
5120 return make
<EnclosingExpr
>("sizeof... ", Pack
);
5122 if (consumeIf("tl")) {
5123 Node
*Ty
= getDerived().parseType();
5126 size_t InitsBegin
= Names
.size();
5127 while (!consumeIf('E')) {
5128 Node
*E
= getDerived().parseBracedExpr();
5133 return make
<InitListExpr
>(Ty
, popTrailingNodeArray(InitsBegin
));
5135 if (consumeIf("tr"))
5136 return make
<NameType
>("throw");
5137 if (consumeIf("tw")) {
5138 Node
*Ex
= getDerived().parseExpr();
5141 return make
<ThrowExpr
>(Ex
);
5143 if (consumeIf('u')) {
5144 Node
*Name
= getDerived().parseSourceName(/*NameState=*/nullptr);
5147 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
5148 // standard encoding expects a <template-arg>, and would be otherwise be
5149 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
5150 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
5151 // actual conflict here.
5152 bool IsUUID
= false;
5153 Node
*UUID
= nullptr;
5154 if (Name
->getBaseName() == "__uuidof") {
5155 if (consumeIf('t')) {
5156 UUID
= getDerived().parseType();
5158 } else if (consumeIf('z')) {
5159 UUID
= getDerived().parseExpr();
5163 size_t ExprsBegin
= Names
.size();
5165 if (UUID
== nullptr)
5167 Names
.push_back(UUID
);
5169 while (!consumeIf('E')) {
5170 Node
*E
= getDerived().parseTemplateArg();
5176 return make
<CallExpr
>(Name
, popTrailingNodeArray(ExprsBegin
),
5177 Node::Prec::Postfix
);
5180 // Only unresolved names remain.
5181 return getDerived().parseUnresolvedName(Global
);
5184 // <call-offset> ::= h <nv-offset> _
5185 // ::= v <v-offset> _
5187 // <nv-offset> ::= <offset number>
5188 // # non-virtual base override
5190 // <v-offset> ::= <offset number> _ <virtual offset number>
5191 // # virtual base override, with vcall offset
5192 template <typename Alloc
, typename Derived
>
5193 bool AbstractManglingParser
<Alloc
, Derived
>::parseCallOffset() {
5194 // Just scan through the call offset, we never add this information into the
5197 return parseNumber(true).empty() || !consumeIf('_');
5199 return parseNumber(true).empty() || !consumeIf('_') ||
5200 parseNumber(true).empty() || !consumeIf('_');
5204 // <special-name> ::= TV <type> # virtual table
5205 // ::= TT <type> # VTT structure (construction vtable index)
5206 // ::= TI <type> # typeinfo structure
5207 // ::= TS <type> # typeinfo name (null-terminated byte string)
5208 // ::= Tc <call-offset> <call-offset> <base encoding>
5209 // # base is the nominal target function of thunk
5210 // # first call-offset is 'this' adjustment
5211 // # second call-offset is result adjustment
5212 // ::= T <call-offset> <base encoding>
5213 // # base is the nominal target function of thunk
5214 // # Guard variable for one-time initialization
5215 // ::= GV <object name>
5217 // ::= TW <object name> # Thread-local wrapper
5218 // ::= TH <object name> # Thread-local initialization
5219 // ::= GR <object name> _ # First temporary
5220 // ::= GR <object name> <seq-id> _ # Subsequent temporaries
5221 // # construction vtable for second-in-first
5222 // extension ::= TC <first type> <number> _ <second type>
5223 // extension ::= GR <object name> # reference temporary for object
5224 // extension ::= GI <module name> # module global initializer
5225 template <typename Derived
, typename Alloc
>
5226 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSpecialName() {
5230 // TA <template-arg> # template parameter object
5232 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
5235 Node
*Arg
= getDerived().parseTemplateArg();
5238 return make
<SpecialName
>("template parameter object for ", Arg
);
5240 // TV <type> # virtual table
5243 Node
*Ty
= getDerived().parseType();
5246 return make
<SpecialName
>("vtable for ", Ty
);
5248 // TT <type> # VTT structure (construction vtable index)
5251 Node
*Ty
= getDerived().parseType();
5254 return make
<SpecialName
>("VTT for ", Ty
);
5256 // TI <type> # typeinfo structure
5259 Node
*Ty
= getDerived().parseType();
5262 return make
<SpecialName
>("typeinfo for ", Ty
);
5264 // TS <type> # typeinfo name (null-terminated byte string)
5267 Node
*Ty
= getDerived().parseType();
5270 return make
<SpecialName
>("typeinfo name for ", Ty
);
5272 // Tc <call-offset> <call-offset> <base encoding>
5275 if (parseCallOffset() || parseCallOffset())
5277 Node
*Encoding
= getDerived().parseEncoding();
5278 if (Encoding
== nullptr)
5280 return make
<SpecialName
>("covariant return thunk to ", Encoding
);
5282 // extension ::= TC <first type> <number> _ <second type>
5283 // # construction vtable for second-in-first
5286 Node
*FirstType
= getDerived().parseType();
5287 if (FirstType
== nullptr)
5289 if (parseNumber(true).empty() || !consumeIf('_'))
5291 Node
*SecondType
= getDerived().parseType();
5292 if (SecondType
== nullptr)
5294 return make
<CtorVtableSpecialName
>(SecondType
, FirstType
);
5296 // TW <object name> # Thread-local wrapper
5299 Node
*Name
= getDerived().parseName();
5300 if (Name
== nullptr)
5302 return make
<SpecialName
>("thread-local wrapper routine for ", Name
);
5304 // TH <object name> # Thread-local initialization
5307 Node
*Name
= getDerived().parseName();
5308 if (Name
== nullptr)
5310 return make
<SpecialName
>("thread-local initialization routine for ", Name
);
5312 // T <call-offset> <base encoding>
5315 bool IsVirt
= look() == 'v';
5316 if (parseCallOffset())
5318 Node
*BaseEncoding
= getDerived().parseEncoding();
5319 if (BaseEncoding
== nullptr)
5322 return make
<SpecialName
>("virtual thunk to ", BaseEncoding
);
5324 return make
<SpecialName
>("non-virtual thunk to ", BaseEncoding
);
5329 // GV <object name> # Guard variable for one-time initialization
5332 Node
*Name
= getDerived().parseName();
5333 if (Name
== nullptr)
5335 return make
<SpecialName
>("guard variable for ", Name
);
5337 // GR <object name> # reference temporary for object
5338 // GR <object name> _ # First temporary
5339 // GR <object name> <seq-id> _ # Subsequent temporaries
5342 Node
*Name
= getDerived().parseName();
5343 if (Name
== nullptr)
5346 bool ParsedSeqId
= !parseSeqId(&Count
);
5347 if (!consumeIf('_') && ParsedSeqId
)
5349 return make
<SpecialName
>("reference temporary for ", Name
);
5351 // GI <module-name> v
5354 ModuleName
*Module
= nullptr;
5355 if (getDerived().parseModuleNameOpt(Module
))
5357 if (Module
== nullptr)
5359 return make
<SpecialName
>("initializer for module ", Module
);
5366 // <encoding> ::= <function name> <bare-function-type>
5367 // [`Q` <requires-clause expr>]
5369 // ::= <special-name>
5370 template <typename Derived
, typename Alloc
>
5371 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseEncoding() {
5372 // The template parameters of an encoding are unrelated to those of the
5373 // enclosing context.
5374 SaveTemplateParams
SaveTemplateParamsScope(this);
5376 if (look() == 'G' || look() == 'T')
5377 return getDerived().parseSpecialName();
5379 auto IsEndOfEncoding
= [&] {
5380 // The set of chars that can potentially follow an <encoding> (none of which
5381 // can start a <type>). Enumerating these allows us to avoid speculative
5383 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5386 NameState
NameInfo(this);
5387 Node
*Name
= getDerived().parseName(&NameInfo
);
5388 if (Name
== nullptr)
5391 if (resolveForwardTemplateRefs(NameInfo
))
5394 if (IsEndOfEncoding())
5397 Node
*Attrs
= nullptr;
5398 if (consumeIf("Ua9enable_ifI")) {
5399 size_t BeforeArgs
= Names
.size();
5400 while (!consumeIf('E')) {
5401 Node
*Arg
= getDerived().parseTemplateArg();
5404 Names
.push_back(Arg
);
5406 Attrs
= make
<EnableIfAttr
>(popTrailingNodeArray(BeforeArgs
));
5411 Node
*ReturnType
= nullptr;
5412 if (!NameInfo
.CtorDtorConversion
&& NameInfo
.EndsWithTemplateArgs
) {
5413 ReturnType
= getDerived().parseType();
5414 if (ReturnType
== nullptr)
5419 if (!consumeIf('v')) {
5420 size_t ParamsBegin
= Names
.size();
5422 Node
*Ty
= getDerived().parseType();
5425 Names
.push_back(Ty
);
5426 } while (!IsEndOfEncoding() && look() != 'Q');
5427 Params
= popTrailingNodeArray(ParamsBegin
);
5430 Node
*Requires
= nullptr;
5431 if (consumeIf('Q')) {
5432 Requires
= getDerived().parseConstraintExpr();
5437 return make
<FunctionEncoding
>(ReturnType
, Name
, Params
, Attrs
, Requires
,
5438 NameInfo
.CVQualifiers
,
5439 NameInfo
.ReferenceQualifier
);
5442 template <class Float
>
5446 struct FloatData
<float>
5448 static const size_t mangled_size
= 8;
5449 static const size_t max_demangled_size
= 24;
5450 static constexpr const char* spec
= "%af";
5454 struct FloatData
<double>
5456 static const size_t mangled_size
= 16;
5457 static const size_t max_demangled_size
= 32;
5458 static constexpr const char* spec
= "%a";
5462 struct FloatData
<long double>
5464 #if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5465 defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \
5467 static const size_t mangled_size
= 32;
5468 #elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5469 static const size_t mangled_size
= 16;
5471 static const size_t mangled_size
= 20; // May need to be adjusted to 16 or 24 on other platforms
5473 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5474 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5475 // Negatives are one character longer than positives.
5476 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5477 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5478 static const size_t max_demangled_size
= 42;
5479 static constexpr const char *spec
= "%LaL";
5482 template <typename Alloc
, typename Derived
>
5483 template <class Float
>
5484 Node
*AbstractManglingParser
<Alloc
, Derived
>::parseFloatingLiteral() {
5485 const size_t N
= FloatData
<Float
>::mangled_size
;
5488 std::string_view
Data(First
, N
);
5490 if (!std::isxdigit(C
))
5493 if (!consumeIf('E'))
5495 return make
<FloatLiteralImpl
<Float
>>(Data
);
5498 // <seq-id> ::= <0-9A-Z>+
5499 template <typename Alloc
, typename Derived
>
5500 bool AbstractManglingParser
<Alloc
, Derived
>::parseSeqId(size_t *Out
) {
5501 if (!(look() >= '0' && look() <= '9') &&
5502 !(look() >= 'A' && look() <= 'Z'))
5507 if (look() >= '0' && look() <= '9') {
5509 Id
+= static_cast<size_t>(look() - '0');
5510 } else if (look() >= 'A' && look() <= 'Z') {
5512 Id
+= static_cast<size_t>(look() - 'A') + 10;
5521 // <substitution> ::= S <seq-id> _
5523 // <substitution> ::= Sa # ::std::allocator
5524 // <substitution> ::= Sb # ::std::basic_string
5525 // <substitution> ::= Ss # ::std::basic_string < char,
5526 // ::std::char_traits<char>,
5527 // ::std::allocator<char> >
5528 // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5529 // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5530 // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
5531 // The St case is handled specially in parseNestedName.
5532 template <typename Derived
, typename Alloc
>
5533 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSubstitution() {
5534 if (!consumeIf('S'))
5537 if (look() >= 'a' && look() <= 'z') {
5538 SpecialSubKind Kind
;
5541 Kind
= SpecialSubKind::allocator
;
5544 Kind
= SpecialSubKind::basic_string
;
5547 Kind
= SpecialSubKind::iostream
;
5550 Kind
= SpecialSubKind::istream
;
5553 Kind
= SpecialSubKind::ostream
;
5556 Kind
= SpecialSubKind::string
;
5562 auto *SpecialSub
= make
<SpecialSubstitution
>(Kind
);
5566 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5567 // has ABI tags, the tags are appended to the substitution; the result is a
5568 // substitutable component.
5569 Node
*WithTags
= getDerived().parseAbiTags(SpecialSub
);
5570 if (WithTags
!= SpecialSub
) {
5571 Subs
.push_back(WithTags
);
5572 SpecialSub
= WithTags
;
5578 if (consumeIf('_')) {
5586 if (parseSeqId(&Index
))
5589 if (!consumeIf('_') || Index
>= Subs
.size())
5594 // <template-param> ::= T_ # first template parameter
5595 // ::= T <parameter-2 non-negative number> _
5596 // ::= TL <level-1> __
5597 // ::= TL <level-1> _ <parameter-2 non-negative number> _
5598 template <typename Derived
, typename Alloc
>
5599 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateParam() {
5600 const char *Begin
= First
;
5601 if (!consumeIf('T'))
5605 if (consumeIf('L')) {
5606 if (parsePositiveInteger(&Level
))
5609 if (!consumeIf('_'))
5614 if (!consumeIf('_')) {
5615 if (parsePositiveInteger(&Index
))
5618 if (!consumeIf('_'))
5622 // We don't track enclosing template parameter levels well enough to reliably
5623 // substitute them all within a <constraint-expression>, so print the
5624 // parameter numbering instead for now.
5625 // TODO: Track all enclosing template parameters and substitute them here.
5626 if (InConstraintExpr
) {
5627 return make
<NameType
>(std::string_view(Begin
, First
- 1 - Begin
));
5630 // If we're in a context where this <template-param> refers to a
5631 // <template-arg> further ahead in the mangled name (currently just conversion
5632 // operator types), then we should only look it up in the right context.
5633 // This can only happen at the outermost level.
5634 if (PermitForwardTemplateReferences
&& Level
== 0) {
5635 Node
*ForwardRef
= make
<ForwardTemplateReference
>(Index
);
5638 assert(ForwardRef
->getKind() == Node::KForwardTemplateReference
);
5639 ForwardTemplateRefs
.push_back(
5640 static_cast<ForwardTemplateReference
*>(ForwardRef
));
5644 if (Level
>= TemplateParams
.size() || !TemplateParams
[Level
] ||
5645 Index
>= TemplateParams
[Level
]->size()) {
5646 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5647 // list are mangled as the corresponding artificial template type parameter.
5648 if (ParsingLambdaParamsAtLevel
== Level
&& Level
<= TemplateParams
.size()) {
5649 // This will be popped by the ScopedTemplateParamList in
5650 // parseUnnamedTypeName.
5651 if (Level
== TemplateParams
.size())
5652 TemplateParams
.push_back(nullptr);
5653 return make
<NameType
>("auto");
5659 return (*TemplateParams
[Level
])[Index
];
5662 // <template-param-decl> ::= Ty # type parameter
5663 // ::= Tn <type> # non-type parameter
5664 // ::= Tt <template-param-decl>* E # template parameter
5665 // ::= Tp <template-param-decl> # parameter pack
5666 template <typename Derived
, typename Alloc
>
5667 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateParamDecl(
5668 TemplateParamList
*Params
) {
5669 auto InventTemplateParamName
= [&](TemplateParamKind Kind
) {
5670 unsigned Index
= NumSyntheticTemplateParameters
[(int)Kind
]++;
5671 Node
*N
= make
<SyntheticTemplateParamName
>(Kind
, Index
);
5673 Params
->push_back(N
);
5677 if (consumeIf("Ty")) {
5678 Node
*Name
= InventTemplateParamName(TemplateParamKind::Type
);
5681 return make
<TypeTemplateParamDecl
>(Name
);
5684 if (consumeIf("Tk")) {
5685 Node
*Constraint
= getDerived().parseName();
5688 Node
*Name
= InventTemplateParamName(TemplateParamKind::Type
);
5691 return make
<ConstrainedTypeTemplateParamDecl
>(Constraint
, Name
);
5694 if (consumeIf("Tn")) {
5695 Node
*Name
= InventTemplateParamName(TemplateParamKind::NonType
);
5698 Node
*Type
= parseType();
5701 return make
<NonTypeTemplateParamDecl
>(Name
, Type
);
5704 if (consumeIf("Tt")) {
5705 Node
*Name
= InventTemplateParamName(TemplateParamKind::Template
);
5708 size_t ParamsBegin
= Names
.size();
5709 ScopedTemplateParamList
TemplateTemplateParamParams(this);
5710 Node
*Requires
= nullptr;
5711 while (!consumeIf('E')) {
5712 Node
*P
= parseTemplateParamDecl(TemplateTemplateParamParams
.params());
5716 if (consumeIf('Q')) {
5717 Requires
= getDerived().parseConstraintExpr();
5718 if (Requires
== nullptr || !consumeIf('E'))
5723 NodeArray InnerParams
= popTrailingNodeArray(ParamsBegin
);
5724 return make
<TemplateTemplateParamDecl
>(Name
, InnerParams
, Requires
);
5727 if (consumeIf("Tp")) {
5728 Node
*P
= parseTemplateParamDecl(Params
);
5731 return make
<TemplateParamPackDecl
>(P
);
5737 // <template-arg> ::= <type> # type or template
5738 // ::= X <expression> E # expression
5739 // ::= <expr-primary> # simple expressions
5740 // ::= J <template-arg>* E # argument pack
5741 // ::= LZ <encoding> E # extension
5742 // ::= <template-param-decl> <template-arg>
5743 template <typename Derived
, typename Alloc
>
5744 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateArg() {
5748 Node
*Arg
= getDerived().parseExpr();
5749 if (Arg
== nullptr || !consumeIf('E'))
5755 size_t ArgsBegin
= Names
.size();
5756 while (!consumeIf('E')) {
5757 Node
*Arg
= getDerived().parseTemplateArg();
5760 Names
.push_back(Arg
);
5762 NodeArray Args
= popTrailingNodeArray(ArgsBegin
);
5763 return make
<TemplateArgumentPack
>(Args
);
5766 // ::= LZ <encoding> E # extension
5767 if (look(1) == 'Z') {
5769 Node
*Arg
= getDerived().parseEncoding();
5770 if (Arg
== nullptr || !consumeIf('E'))
5774 // ::= <expr-primary> # simple expressions
5775 return getDerived().parseExprPrimary();
5778 // Either <template-param> or a <template-param-decl> <template-arg>.
5779 if (!getDerived().isTemplateParamDecl())
5780 return getDerived().parseType();
5781 Node
*Param
= getDerived().parseTemplateParamDecl(nullptr);
5784 Node
*Arg
= getDerived().parseTemplateArg();
5787 return make
<TemplateParamQualifiedArg
>(Param
, Arg
);
5790 return getDerived().parseType();
5794 // <template-args> ::= I <template-arg>* E
5795 // extension, the abi says <template-arg>+
5796 template <typename Derived
, typename Alloc
>
5798 AbstractManglingParser
<Derived
, Alloc
>::parseTemplateArgs(bool TagTemplates
) {
5799 if (!consumeIf('I'))
5802 // <template-params> refer to the innermost <template-args>. Clear out any
5803 // outer args that we may have inserted into TemplateParams.
5805 TemplateParams
.clear();
5806 TemplateParams
.push_back(&OuterTemplateParams
);
5807 OuterTemplateParams
.clear();
5810 size_t ArgsBegin
= Names
.size();
5811 Node
*Requires
= nullptr;
5812 while (!consumeIf('E')) {
5814 Node
*Arg
= getDerived().parseTemplateArg();
5817 Names
.push_back(Arg
);
5818 Node
*TableEntry
= Arg
;
5819 if (Arg
->getKind() == Node::KTemplateParamQualifiedArg
) {
5821 static_cast<TemplateParamQualifiedArg
*>(TableEntry
)->getArg();
5823 if (Arg
->getKind() == Node::KTemplateArgumentPack
) {
5824 TableEntry
= make
<ParameterPack
>(
5825 static_cast<TemplateArgumentPack
*>(TableEntry
)->getElements());
5829 OuterTemplateParams
.push_back(TableEntry
);
5831 Node
*Arg
= getDerived().parseTemplateArg();
5834 Names
.push_back(Arg
);
5836 if (consumeIf('Q')) {
5837 Requires
= getDerived().parseConstraintExpr();
5838 if (!Requires
|| !consumeIf('E'))
5843 return make
<TemplateArgs
>(popTrailingNodeArray(ArgsBegin
), Requires
);
5846 // <mangled-name> ::= _Z <encoding>
5848 // extension ::= ___Z <encoding> _block_invoke
5849 // extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5850 // extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
5851 template <typename Derived
, typename Alloc
>
5852 Node
*AbstractManglingParser
<Derived
, Alloc
>::parse() {
5853 if (consumeIf("_Z") || consumeIf("__Z")) {
5854 Node
*Encoding
= getDerived().parseEncoding();
5855 if (Encoding
== nullptr)
5857 if (look() == '.') {
5859 make
<DotSuffix
>(Encoding
, std::string_view(First
, Last
- First
));
5867 if (consumeIf("___Z") || consumeIf("____Z")) {
5868 Node
*Encoding
= getDerived().parseEncoding();
5869 if (Encoding
== nullptr || !consumeIf("_block_invoke"))
5871 bool RequireNumber
= consumeIf('_');
5872 if (parseNumber().empty() && RequireNumber
)
5878 return make
<SpecialName
>("invocation function for block in ", Encoding
);
5881 Node
*Ty
= getDerived().parseType();
5887 template <typename Alloc
>
5888 struct ManglingParser
: AbstractManglingParser
<ManglingParser
<Alloc
>, Alloc
> {
5889 using AbstractManglingParser
<ManglingParser
<Alloc
>,
5890 Alloc
>::AbstractManglingParser
;
5893 DEMANGLE_NAMESPACE_END
5895 #ifdef _LIBCXXABI_COMPILER_CLANG
5896 #pragma clang diagnostic pop
5899 #endif // DEMANGLE_ITANIUMDEMANGLE_H