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 dropBack(size_t Index
) {
137 assert(Index
<= size() && "dropBack() 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 struct AbiTagAttr
: Node
{
539 std::string_view Tag
;
541 AbiTagAttr(Node
*Base_
, std::string_view Tag_
)
542 : Node(KAbiTagAttr
, Base_
->RHSComponentCache
, Base_
->ArrayCache
,
543 Base_
->FunctionCache
),
544 Base(Base_
), Tag(Tag_
) {}
546 template<typename Fn
> void match(Fn F
) const { F(Base
, Tag
); }
548 std::string_view
getBaseName() const override
{ return Base
->getBaseName(); }
550 void printLeft(OutputBuffer
&OB
) const override
{
558 class EnableIfAttr
: public Node
{
559 NodeArray Conditions
;
561 EnableIfAttr(NodeArray Conditions_
)
562 : Node(KEnableIfAttr
), Conditions(Conditions_
) {}
564 template<typename Fn
> void match(Fn F
) const { F(Conditions
); }
566 void printLeft(OutputBuffer
&OB
) const override
{
567 OB
+= " [enable_if:";
568 Conditions
.printWithComma(OB
);
573 class ObjCProtoName
: public Node
{
575 std::string_view Protocol
;
577 friend class PointerType
;
580 ObjCProtoName(const Node
*Ty_
, std::string_view Protocol_
)
581 : Node(KObjCProtoName
), Ty(Ty_
), Protocol(Protocol_
) {}
583 template<typename Fn
> void match(Fn F
) const { F(Ty
, Protocol
); }
585 bool isObjCObject() const {
586 return Ty
->getKind() == KNameType
&&
587 static_cast<const NameType
*>(Ty
)->getName() == "objc_object";
590 void printLeft(OutputBuffer
&OB
) const override
{
598 class PointerType final
: public Node
{
602 PointerType(const Node
*Pointee_
)
603 : Node(KPointerType
, Pointee_
->RHSComponentCache
),
606 const Node
*getPointee() const { return Pointee
; }
608 template<typename Fn
> void match(Fn F
) const { F(Pointee
); }
610 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
611 return Pointee
->hasRHSComponent(OB
);
614 void printLeft(OutputBuffer
&OB
) const override
{
615 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
616 if (Pointee
->getKind() != KObjCProtoName
||
617 !static_cast<const ObjCProtoName
*>(Pointee
)->isObjCObject()) {
618 Pointee
->printLeft(OB
);
619 if (Pointee
->hasArray(OB
))
621 if (Pointee
->hasArray(OB
) || Pointee
->hasFunction(OB
))
625 const auto *objcProto
= static_cast<const ObjCProtoName
*>(Pointee
);
627 OB
+= objcProto
->Protocol
;
632 void printRight(OutputBuffer
&OB
) const override
{
633 if (Pointee
->getKind() != KObjCProtoName
||
634 !static_cast<const ObjCProtoName
*>(Pointee
)->isObjCObject()) {
635 if (Pointee
->hasArray(OB
) || Pointee
->hasFunction(OB
))
637 Pointee
->printRight(OB
);
642 enum class ReferenceKind
{
647 // Represents either a LValue or an RValue reference type.
648 class ReferenceType
: public Node
{
652 mutable bool Printing
= false;
654 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
655 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
656 // other combination collapses to a lvalue ref.
658 // A combination of a TemplateForwardReference and a back-ref Substitution
659 // from an ill-formed string may have created a cycle; use cycle detection to
660 // avoid looping forever.
661 std::pair
<ReferenceKind
, const Node
*> collapse(OutputBuffer
&OB
) const {
662 auto SoFar
= std::make_pair(RK
, Pointee
);
663 // Track the chain of nodes for the Floyd's 'tortoise and hare'
664 // cycle-detection algorithm, since getSyntaxNode(S) is impure
665 PODSmallVector
<const Node
*, 8> Prev
;
667 const Node
*SN
= SoFar
.second
->getSyntaxNode(OB
);
668 if (SN
->getKind() != KReferenceType
)
670 auto *RT
= static_cast<const ReferenceType
*>(SN
);
671 SoFar
.second
= RT
->Pointee
;
672 SoFar
.first
= std::min(SoFar
.first
, RT
->RK
);
674 // The middle of Prev is the 'slow' pointer moving at half speed
675 Prev
.push_back(SoFar
.second
);
676 if (Prev
.size() > 1 && SoFar
.second
== Prev
[(Prev
.size() - 1) / 2]) {
678 SoFar
.second
= nullptr;
686 ReferenceType(const Node
*Pointee_
, ReferenceKind RK_
)
687 : Node(KReferenceType
, Pointee_
->RHSComponentCache
),
688 Pointee(Pointee_
), RK(RK_
) {}
690 template<typename Fn
> void match(Fn F
) const { F(Pointee
, RK
); }
692 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
693 return Pointee
->hasRHSComponent(OB
);
696 void printLeft(OutputBuffer
&OB
) const override
{
699 ScopedOverride
<bool> SavePrinting(Printing
, true);
700 std::pair
<ReferenceKind
, const Node
*> Collapsed
= collapse(OB
);
701 if (!Collapsed
.second
)
703 Collapsed
.second
->printLeft(OB
);
704 if (Collapsed
.second
->hasArray(OB
))
706 if (Collapsed
.second
->hasArray(OB
) || Collapsed
.second
->hasFunction(OB
))
709 OB
+= (Collapsed
.first
== ReferenceKind::LValue
? "&" : "&&");
711 void printRight(OutputBuffer
&OB
) const override
{
714 ScopedOverride
<bool> SavePrinting(Printing
, true);
715 std::pair
<ReferenceKind
, const Node
*> Collapsed
= collapse(OB
);
716 if (!Collapsed
.second
)
718 if (Collapsed
.second
->hasArray(OB
) || Collapsed
.second
->hasFunction(OB
))
720 Collapsed
.second
->printRight(OB
);
724 class PointerToMemberType final
: public Node
{
725 const Node
*ClassType
;
726 const Node
*MemberType
;
729 PointerToMemberType(const Node
*ClassType_
, const Node
*MemberType_
)
730 : Node(KPointerToMemberType
, MemberType_
->RHSComponentCache
),
731 ClassType(ClassType_
), MemberType(MemberType_
) {}
733 template<typename Fn
> void match(Fn F
) const { F(ClassType
, MemberType
); }
735 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
736 return MemberType
->hasRHSComponent(OB
);
739 void printLeft(OutputBuffer
&OB
) const override
{
740 MemberType
->printLeft(OB
);
741 if (MemberType
->hasArray(OB
) || MemberType
->hasFunction(OB
))
745 ClassType
->print(OB
);
749 void printRight(OutputBuffer
&OB
) const override
{
750 if (MemberType
->hasArray(OB
) || MemberType
->hasFunction(OB
))
752 MemberType
->printRight(OB
);
756 class ArrayType final
: public Node
{
761 ArrayType(const Node
*Base_
, Node
*Dimension_
)
763 /*RHSComponentCache=*/Cache::Yes
,
764 /*ArrayCache=*/Cache::Yes
),
765 Base(Base_
), Dimension(Dimension_
) {}
767 template<typename Fn
> void match(Fn F
) const { F(Base
, Dimension
); }
769 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
770 bool hasArraySlow(OutputBuffer
&) const override
{ return true; }
772 void printLeft(OutputBuffer
&OB
) const override
{ Base
->printLeft(OB
); }
774 void printRight(OutputBuffer
&OB
) const override
{
775 if (OB
.back() != ']')
779 Dimension
->print(OB
);
781 Base
->printRight(OB
);
785 class FunctionType final
: public Node
{
789 FunctionRefQual RefQual
;
790 const Node
*ExceptionSpec
;
793 FunctionType(const Node
*Ret_
, NodeArray Params_
, Qualifiers CVQuals_
,
794 FunctionRefQual RefQual_
, const Node
*ExceptionSpec_
)
795 : Node(KFunctionType
,
796 /*RHSComponentCache=*/Cache::Yes
, /*ArrayCache=*/Cache::No
,
797 /*FunctionCache=*/Cache::Yes
),
798 Ret(Ret_
), Params(Params_
), CVQuals(CVQuals_
), RefQual(RefQual_
),
799 ExceptionSpec(ExceptionSpec_
) {}
801 template<typename Fn
> void match(Fn F
) const {
802 F(Ret
, Params
, CVQuals
, RefQual
, ExceptionSpec
);
805 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
806 bool hasFunctionSlow(OutputBuffer
&) const override
{ return true; }
808 // Handle C++'s ... quirky decl grammar by using the left & right
809 // distinction. Consider:
810 // int (*f(float))(char) {}
811 // f is a function that takes a float and returns a pointer to a function
812 // that takes a char and returns an int. If we're trying to print f, start
813 // by printing out the return types's left, then print our parameters, then
814 // finally print right of the return type.
815 void printLeft(OutputBuffer
&OB
) const override
{
820 void printRight(OutputBuffer
&OB
) const override
{
822 Params
.printWithComma(OB
);
826 if (CVQuals
& QualConst
)
828 if (CVQuals
& QualVolatile
)
830 if (CVQuals
& QualRestrict
)
833 if (RefQual
== FrefQualLValue
)
835 else if (RefQual
== FrefQualRValue
)
838 if (ExceptionSpec
!= nullptr) {
840 ExceptionSpec
->print(OB
);
845 class NoexceptSpec
: public Node
{
848 NoexceptSpec(const Node
*E_
) : Node(KNoexceptSpec
), E(E_
) {}
850 template<typename Fn
> void match(Fn F
) const { F(E
); }
852 void printLeft(OutputBuffer
&OB
) const override
{
855 E
->printAsOperand(OB
);
860 class DynamicExceptionSpec
: public Node
{
863 DynamicExceptionSpec(NodeArray Types_
)
864 : Node(KDynamicExceptionSpec
), Types(Types_
) {}
866 template<typename Fn
> void match(Fn F
) const { F(Types
); }
868 void printLeft(OutputBuffer
&OB
) const override
{
871 Types
.printWithComma(OB
);
876 class FunctionEncoding final
: public Node
{
882 FunctionRefQual RefQual
;
885 FunctionEncoding(const Node
*Ret_
, const Node
*Name_
, NodeArray Params_
,
886 const Node
*Attrs_
, Qualifiers CVQuals_
,
887 FunctionRefQual RefQual_
)
888 : Node(KFunctionEncoding
,
889 /*RHSComponentCache=*/Cache::Yes
, /*ArrayCache=*/Cache::No
,
890 /*FunctionCache=*/Cache::Yes
),
891 Ret(Ret_
), Name(Name_
), Params(Params_
), Attrs(Attrs_
),
892 CVQuals(CVQuals_
), RefQual(RefQual_
) {}
894 template<typename Fn
> void match(Fn F
) const {
895 F(Ret
, Name
, Params
, Attrs
, CVQuals
, RefQual
);
898 Qualifiers
getCVQuals() const { return CVQuals
; }
899 FunctionRefQual
getRefQual() const { return RefQual
; }
900 NodeArray
getParams() const { return Params
; }
901 const Node
*getReturnType() const { return Ret
; }
903 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
904 bool hasFunctionSlow(OutputBuffer
&) const override
{ return true; }
906 const Node
*getName() const { return Name
; }
908 void printLeft(OutputBuffer
&OB
) const override
{
911 if (!Ret
->hasRHSComponent(OB
))
917 void printRight(OutputBuffer
&OB
) const override
{
919 Params
.printWithComma(OB
);
924 if (CVQuals
& QualConst
)
926 if (CVQuals
& QualVolatile
)
928 if (CVQuals
& QualRestrict
)
931 if (RefQual
== FrefQualLValue
)
933 else if (RefQual
== FrefQualRValue
)
936 if (Attrs
!= nullptr)
941 class LiteralOperator
: public Node
{
945 LiteralOperator(const Node
*OpName_
)
946 : Node(KLiteralOperator
), OpName(OpName_
) {}
948 template<typename Fn
> void match(Fn F
) const { F(OpName
); }
950 void printLeft(OutputBuffer
&OB
) const override
{
951 OB
+= "operator\"\" ";
956 class SpecialName final
: public Node
{
957 const std::string_view Special
;
961 SpecialName(std::string_view Special_
, const Node
*Child_
)
962 : Node(KSpecialName
), Special(Special_
), Child(Child_
) {}
964 template<typename Fn
> void match(Fn F
) const { F(Special
, Child
); }
966 void printLeft(OutputBuffer
&OB
) const override
{
972 class CtorVtableSpecialName final
: public Node
{
973 const Node
*FirstType
;
974 const Node
*SecondType
;
977 CtorVtableSpecialName(const Node
*FirstType_
, const Node
*SecondType_
)
978 : Node(KCtorVtableSpecialName
),
979 FirstType(FirstType_
), SecondType(SecondType_
) {}
981 template<typename Fn
> void match(Fn F
) const { F(FirstType
, SecondType
); }
983 void printLeft(OutputBuffer
&OB
) const override
{
984 OB
+= "construction vtable for ";
985 FirstType
->print(OB
);
987 SecondType
->print(OB
);
991 struct NestedName
: Node
{
995 NestedName(Node
*Qual_
, Node
*Name_
)
996 : Node(KNestedName
), Qual(Qual_
), Name(Name_
) {}
998 template<typename Fn
> void match(Fn F
) const { F(Qual
, Name
); }
1000 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1002 void printLeft(OutputBuffer
&OB
) const override
{
1009 struct ModuleName
: Node
{
1014 ModuleName(ModuleName
*Parent_
, Node
*Name_
, bool IsPartition_
= false)
1015 : Node(KModuleName
), Parent(Parent_
), Name(Name_
),
1016 IsPartition(IsPartition_
) {}
1018 template <typename Fn
> void match(Fn F
) const {
1019 F(Parent
, Name
, IsPartition
);
1022 void printLeft(OutputBuffer
&OB
) const override
{
1025 if (Parent
|| IsPartition
)
1026 OB
+= IsPartition
? ':' : '.';
1031 struct ModuleEntity
: Node
{
1035 ModuleEntity(ModuleName
*Module_
, Node
*Name_
)
1036 : Node(KModuleEntity
), Module(Module_
), Name(Name_
) {}
1038 template <typename Fn
> void match(Fn F
) const { F(Module
, Name
); }
1040 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1042 void printLeft(OutputBuffer
&OB
) const override
{
1049 struct LocalName
: Node
{
1053 LocalName(Node
*Encoding_
, Node
*Entity_
)
1054 : Node(KLocalName
), Encoding(Encoding_
), Entity(Entity_
) {}
1056 template<typename Fn
> void match(Fn F
) const { F(Encoding
, Entity
); }
1058 void printLeft(OutputBuffer
&OB
) const override
{
1059 Encoding
->print(OB
);
1065 class QualifiedName final
: public Node
{
1067 const Node
*Qualifier
;
1071 QualifiedName(const Node
*Qualifier_
, const Node
*Name_
)
1072 : Node(KQualifiedName
), Qualifier(Qualifier_
), Name(Name_
) {}
1074 template<typename Fn
> void match(Fn F
) const { F(Qualifier
, Name
); }
1076 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1078 void printLeft(OutputBuffer
&OB
) const override
{
1079 Qualifier
->print(OB
);
1085 class VectorType final
: public Node
{
1086 const Node
*BaseType
;
1087 const Node
*Dimension
;
1090 VectorType(const Node
*BaseType_
, const Node
*Dimension_
)
1091 : Node(KVectorType
), BaseType(BaseType_
), Dimension(Dimension_
) {}
1093 const Node
*getBaseType() const { return BaseType
; }
1094 const Node
*getDimension() const { return Dimension
; }
1096 template<typename Fn
> void match(Fn F
) const { F(BaseType
, Dimension
); }
1098 void printLeft(OutputBuffer
&OB
) const override
{
1099 BaseType
->print(OB
);
1102 Dimension
->print(OB
);
1107 class PixelVectorType final
: public Node
{
1108 const Node
*Dimension
;
1111 PixelVectorType(const Node
*Dimension_
)
1112 : Node(KPixelVectorType
), Dimension(Dimension_
) {}
1114 template<typename Fn
> void match(Fn F
) const { F(Dimension
); }
1116 void printLeft(OutputBuffer
&OB
) const override
{
1117 // FIXME: This should demangle as "vector pixel".
1118 OB
+= "pixel vector[";
1119 Dimension
->print(OB
);
1124 class BinaryFPType final
: public Node
{
1125 const Node
*Dimension
;
1128 BinaryFPType(const Node
*Dimension_
)
1129 : Node(KBinaryFPType
), Dimension(Dimension_
) {}
1131 template<typename Fn
> void match(Fn F
) const { F(Dimension
); }
1133 void printLeft(OutputBuffer
&OB
) const override
{
1135 Dimension
->print(OB
);
1139 enum class TemplateParamKind
{ Type
, NonType
, Template
};
1141 /// An invented name for a template parameter for which we don't have a
1142 /// corresponding template argument.
1144 /// This node is created when parsing the <lambda-sig> for a lambda with
1145 /// explicit template arguments, which might be referenced in the parameter
1146 /// types appearing later in the <lambda-sig>.
1147 class SyntheticTemplateParamName final
: public Node
{
1148 TemplateParamKind Kind
;
1152 SyntheticTemplateParamName(TemplateParamKind Kind_
, unsigned Index_
)
1153 : Node(KSyntheticTemplateParamName
), Kind(Kind_
), Index(Index_
) {}
1155 template<typename Fn
> void match(Fn F
) const { F(Kind
, Index
); }
1157 void printLeft(OutputBuffer
&OB
) const override
{
1159 case TemplateParamKind::Type
:
1162 case TemplateParamKind::NonType
:
1165 case TemplateParamKind::Template
:
1174 /// A template type parameter declaration, 'typename T'.
1175 class TypeTemplateParamDecl final
: public Node
{
1179 TypeTemplateParamDecl(Node
*Name_
)
1180 : Node(KTypeTemplateParamDecl
, Cache::Yes
), Name(Name_
) {}
1182 template<typename Fn
> void match(Fn F
) const { F(Name
); }
1184 void printLeft(OutputBuffer
&OB
) const override
{ OB
+= "typename "; }
1186 void printRight(OutputBuffer
&OB
) const override
{ Name
->print(OB
); }
1189 /// A non-type template parameter declaration, 'int N'.
1190 class NonTypeTemplateParamDecl final
: public Node
{
1195 NonTypeTemplateParamDecl(Node
*Name_
, Node
*Type_
)
1196 : Node(KNonTypeTemplateParamDecl
, Cache::Yes
), Name(Name_
), Type(Type_
) {}
1198 template<typename Fn
> void match(Fn F
) const { F(Name
, Type
); }
1200 void printLeft(OutputBuffer
&OB
) const override
{
1201 Type
->printLeft(OB
);
1202 if (!Type
->hasRHSComponent(OB
))
1206 void printRight(OutputBuffer
&OB
) const override
{
1208 Type
->printRight(OB
);
1212 /// A template template parameter declaration,
1213 /// 'template<typename T> typename N'.
1214 class TemplateTemplateParamDecl final
: public Node
{
1219 TemplateTemplateParamDecl(Node
*Name_
, NodeArray Params_
)
1220 : Node(KTemplateTemplateParamDecl
, Cache::Yes
), Name(Name_
),
1223 template<typename Fn
> void match(Fn F
) const { F(Name
, Params
); }
1225 void printLeft(OutputBuffer
&OB
) const override
{
1226 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1228 Params
.printWithComma(OB
);
1229 OB
+= "> typename ";
1232 void printRight(OutputBuffer
&OB
) const override
{ Name
->print(OB
); }
1235 /// A template parameter pack declaration, 'typename ...T'.
1236 class TemplateParamPackDecl final
: public Node
{
1240 TemplateParamPackDecl(Node
*Param_
)
1241 : Node(KTemplateParamPackDecl
, Cache::Yes
), Param(Param_
) {}
1243 template<typename Fn
> void match(Fn F
) const { F(Param
); }
1245 void printLeft(OutputBuffer
&OB
) const override
{
1246 Param
->printLeft(OB
);
1250 void printRight(OutputBuffer
&OB
) const override
{ Param
->printRight(OB
); }
1253 /// An unexpanded parameter pack (either in the expression or type context). If
1254 /// this AST is correct, this node will have a ParameterPackExpansion node above
1257 /// This node is created when some <template-args> are found that apply to an
1258 /// <encoding>, and is stored in the TemplateParams table. In order for this to
1259 /// appear in the final AST, it has to referenced via a <template-param> (ie,
1261 class ParameterPack final
: public Node
{
1264 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1266 void initializePackExpansion(OutputBuffer
&OB
) const {
1267 if (OB
.CurrentPackMax
== std::numeric_limits
<unsigned>::max()) {
1268 OB
.CurrentPackMax
= static_cast<unsigned>(Data
.size());
1269 OB
.CurrentPackIndex
= 0;
1274 ParameterPack(NodeArray Data_
) : Node(KParameterPack
), Data(Data_
) {
1275 ArrayCache
= FunctionCache
= RHSComponentCache
= Cache::Unknown
;
1276 if (std::all_of(Data
.begin(), Data
.end(), [](Node
* P
) {
1277 return P
->ArrayCache
== Cache::No
;
1279 ArrayCache
= Cache::No
;
1280 if (std::all_of(Data
.begin(), Data
.end(), [](Node
* P
) {
1281 return P
->FunctionCache
== Cache::No
;
1283 FunctionCache
= Cache::No
;
1284 if (std::all_of(Data
.begin(), Data
.end(), [](Node
* P
) {
1285 return P
->RHSComponentCache
== Cache::No
;
1287 RHSComponentCache
= Cache::No
;
1290 template<typename Fn
> void match(Fn F
) const { F(Data
); }
1292 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
1293 initializePackExpansion(OB
);
1294 size_t Idx
= OB
.CurrentPackIndex
;
1295 return Idx
< Data
.size() && Data
[Idx
]->hasRHSComponent(OB
);
1297 bool hasArraySlow(OutputBuffer
&OB
) const override
{
1298 initializePackExpansion(OB
);
1299 size_t Idx
= OB
.CurrentPackIndex
;
1300 return Idx
< Data
.size() && Data
[Idx
]->hasArray(OB
);
1302 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
1303 initializePackExpansion(OB
);
1304 size_t Idx
= OB
.CurrentPackIndex
;
1305 return Idx
< Data
.size() && Data
[Idx
]->hasFunction(OB
);
1307 const Node
*getSyntaxNode(OutputBuffer
&OB
) const override
{
1308 initializePackExpansion(OB
);
1309 size_t Idx
= OB
.CurrentPackIndex
;
1310 return Idx
< Data
.size() ? Data
[Idx
]->getSyntaxNode(OB
) : this;
1313 void printLeft(OutputBuffer
&OB
) const override
{
1314 initializePackExpansion(OB
);
1315 size_t Idx
= OB
.CurrentPackIndex
;
1316 if (Idx
< Data
.size())
1317 Data
[Idx
]->printLeft(OB
);
1319 void printRight(OutputBuffer
&OB
) const override
{
1320 initializePackExpansion(OB
);
1321 size_t Idx
= OB
.CurrentPackIndex
;
1322 if (Idx
< Data
.size())
1323 Data
[Idx
]->printRight(OB
);
1327 /// A variadic template argument. This node represents an occurrence of
1328 /// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1329 /// one of it's Elements is. The parser inserts a ParameterPack into the
1330 /// TemplateParams table if the <template-args> this pack belongs to apply to an
1332 class TemplateArgumentPack final
: public Node
{
1335 TemplateArgumentPack(NodeArray Elements_
)
1336 : Node(KTemplateArgumentPack
), Elements(Elements_
) {}
1338 template<typename Fn
> void match(Fn F
) const { F(Elements
); }
1340 NodeArray
getElements() const { return Elements
; }
1342 void printLeft(OutputBuffer
&OB
) const override
{
1343 Elements
.printWithComma(OB
);
1347 /// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1348 /// which each have Child->ParameterPackSize elements.
1349 class ParameterPackExpansion final
: public Node
{
1353 ParameterPackExpansion(const Node
*Child_
)
1354 : Node(KParameterPackExpansion
), Child(Child_
) {}
1356 template<typename Fn
> void match(Fn F
) const { F(Child
); }
1358 const Node
*getChild() const { return Child
; }
1360 void printLeft(OutputBuffer
&OB
) const override
{
1361 constexpr unsigned Max
= std::numeric_limits
<unsigned>::max();
1362 ScopedOverride
<unsigned> SavePackIdx(OB
.CurrentPackIndex
, Max
);
1363 ScopedOverride
<unsigned> SavePackMax(OB
.CurrentPackMax
, Max
);
1364 size_t StreamPos
= OB
.getCurrentPosition();
1366 // Print the first element in the pack. If Child contains a ParameterPack,
1367 // it will set up S.CurrentPackMax and print the first element.
1370 // No ParameterPack was found in Child. This can occur if we've found a pack
1371 // expansion on a <function-param>.
1372 if (OB
.CurrentPackMax
== Max
) {
1377 // We found a ParameterPack, but it has no elements. Erase whatever we may
1379 if (OB
.CurrentPackMax
== 0) {
1380 OB
.setCurrentPosition(StreamPos
);
1384 // Else, iterate through the rest of the elements in the pack.
1385 for (unsigned I
= 1, E
= OB
.CurrentPackMax
; I
< E
; ++I
) {
1387 OB
.CurrentPackIndex
= I
;
1393 class TemplateArgs final
: public Node
{
1397 TemplateArgs(NodeArray Params_
) : Node(KTemplateArgs
), Params(Params_
) {}
1399 template<typename Fn
> void match(Fn F
) const { F(Params
); }
1401 NodeArray
getParams() { return Params
; }
1403 void printLeft(OutputBuffer
&OB
) const override
{
1404 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1406 Params
.printWithComma(OB
);
1411 /// A forward-reference to a template argument that was not known at the point
1412 /// where the template parameter name was parsed in a mangling.
1414 /// This is created when demangling the name of a specialization of a
1415 /// conversion function template:
1419 /// template<typename T> operator T*();
1423 /// When demangling a specialization of the conversion function template, we
1424 /// encounter the name of the template (including the \c T) before we reach
1425 /// the template argument list, so we cannot substitute the parameter name
1426 /// for the corresponding argument while parsing. Instead, we create a
1427 /// \c ForwardTemplateReference node that is resolved after we parse the
1428 /// template arguments.
1429 struct ForwardTemplateReference
: Node
{
1431 Node
*Ref
= nullptr;
1433 // If we're currently printing this node. It is possible (though invalid) for
1434 // a forward template reference to refer to itself via a substitution. This
1435 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1436 // out if more than one print* function is active.
1437 mutable bool Printing
= false;
1439 ForwardTemplateReference(size_t Index_
)
1440 : Node(KForwardTemplateReference
, Cache::Unknown
, Cache::Unknown
,
1444 // We don't provide a matcher for these, because the value of the node is
1445 // not determined by its construction parameters, and it generally needs
1446 // special handling.
1447 template<typename Fn
> void match(Fn F
) const = delete;
1449 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
1452 ScopedOverride
<bool> SavePrinting(Printing
, true);
1453 return Ref
->hasRHSComponent(OB
);
1455 bool hasArraySlow(OutputBuffer
&OB
) const override
{
1458 ScopedOverride
<bool> SavePrinting(Printing
, true);
1459 return Ref
->hasArray(OB
);
1461 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
1464 ScopedOverride
<bool> SavePrinting(Printing
, true);
1465 return Ref
->hasFunction(OB
);
1467 const Node
*getSyntaxNode(OutputBuffer
&OB
) const override
{
1470 ScopedOverride
<bool> SavePrinting(Printing
, true);
1471 return Ref
->getSyntaxNode(OB
);
1474 void printLeft(OutputBuffer
&OB
) const override
{
1477 ScopedOverride
<bool> SavePrinting(Printing
, true);
1480 void printRight(OutputBuffer
&OB
) const override
{
1483 ScopedOverride
<bool> SavePrinting(Printing
, true);
1484 Ref
->printRight(OB
);
1488 struct NameWithTemplateArgs
: Node
{
1489 // name<template_args>
1493 NameWithTemplateArgs(Node
*Name_
, Node
*TemplateArgs_
)
1494 : Node(KNameWithTemplateArgs
), Name(Name_
), TemplateArgs(TemplateArgs_
) {}
1496 template<typename Fn
> void match(Fn F
) const { F(Name
, TemplateArgs
); }
1498 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1500 void printLeft(OutputBuffer
&OB
) const override
{
1502 TemplateArgs
->print(OB
);
1506 class GlobalQualifiedName final
: public Node
{
1510 GlobalQualifiedName(Node
* Child_
)
1511 : Node(KGlobalQualifiedName
), Child(Child_
) {}
1513 template<typename Fn
> void match(Fn F
) const { F(Child
); }
1515 std::string_view
getBaseName() const override
{ return Child
->getBaseName(); }
1517 void printLeft(OutputBuffer
&OB
) const override
{
1523 enum class SpecialSubKind
{
1532 class SpecialSubstitution
;
1533 class ExpandedSpecialSubstitution
: public Node
{
1537 ExpandedSpecialSubstitution(SpecialSubKind SSK_
, Kind K_
)
1538 : Node(K_
), SSK(SSK_
) {}
1540 ExpandedSpecialSubstitution(SpecialSubKind SSK_
)
1541 : ExpandedSpecialSubstitution(SSK_
, KExpandedSpecialSubstitution
) {}
1542 inline ExpandedSpecialSubstitution(SpecialSubstitution
const *);
1544 template<typename Fn
> void match(Fn F
) const { F(SSK
); }
1547 bool isInstantiation() const {
1548 return unsigned(SSK
) >= unsigned(SpecialSubKind::string
);
1551 std::string_view
getBaseName() const override
{
1553 case SpecialSubKind::allocator
:
1554 return {"allocator"};
1555 case SpecialSubKind::basic_string
:
1556 return {"basic_string"};
1557 case SpecialSubKind::string
:
1558 return {"basic_string"};
1559 case SpecialSubKind::istream
:
1560 return {"basic_istream"};
1561 case SpecialSubKind::ostream
:
1562 return {"basic_ostream"};
1563 case SpecialSubKind::iostream
:
1564 return {"basic_iostream"};
1566 DEMANGLE_UNREACHABLE
;
1570 void printLeft(OutputBuffer
&OB
) const override
{
1571 OB
<< "std::" << getBaseName();
1572 if (isInstantiation()) {
1573 OB
<< "<char, std::char_traits<char>";
1574 if (SSK
== SpecialSubKind::string
)
1575 OB
<< ", std::allocator<char>";
1581 class SpecialSubstitution final
: public ExpandedSpecialSubstitution
{
1583 SpecialSubstitution(SpecialSubKind SSK_
)
1584 : ExpandedSpecialSubstitution(SSK_
, KSpecialSubstitution
) {}
1586 template<typename Fn
> void match(Fn F
) const { F(SSK
); }
1588 std::string_view
getBaseName() const override
{
1589 std::string_view SV
= ExpandedSpecialSubstitution::getBaseName();
1590 if (isInstantiation()) {
1591 // The instantiations are typedefs that drop the "basic_" prefix.
1592 assert(starts_with(SV
, "basic_"));
1593 SV
.remove_prefix(sizeof("basic_") - 1);
1598 void printLeft(OutputBuffer
&OB
) const override
{
1599 OB
<< "std::" << getBaseName();
1603 inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(
1604 SpecialSubstitution
const *SS
)
1605 : ExpandedSpecialSubstitution(SS
->SSK
) {}
1607 class CtorDtorName final
: public Node
{
1608 const Node
*Basename
;
1613 CtorDtorName(const Node
*Basename_
, bool IsDtor_
, int Variant_
)
1614 : Node(KCtorDtorName
), Basename(Basename_
), IsDtor(IsDtor_
),
1615 Variant(Variant_
) {}
1617 template<typename Fn
> void match(Fn F
) const { F(Basename
, IsDtor
, Variant
); }
1619 void printLeft(OutputBuffer
&OB
) const override
{
1622 OB
+= Basename
->getBaseName();
1626 class DtorName
: public Node
{
1630 DtorName(const Node
*Base_
) : Node(KDtorName
), Base(Base_
) {}
1632 template<typename Fn
> void match(Fn F
) const { F(Base
); }
1634 void printLeft(OutputBuffer
&OB
) const override
{
1636 Base
->printLeft(OB
);
1640 class UnnamedTypeName
: public Node
{
1641 const std::string_view Count
;
1644 UnnamedTypeName(std::string_view Count_
)
1645 : Node(KUnnamedTypeName
), Count(Count_
) {}
1647 template<typename Fn
> void match(Fn F
) const { F(Count
); }
1649 void printLeft(OutputBuffer
&OB
) const override
{
1656 class ClosureTypeName
: public Node
{
1657 NodeArray TemplateParams
;
1659 std::string_view Count
;
1662 ClosureTypeName(NodeArray TemplateParams_
, NodeArray Params_
,
1663 std::string_view Count_
)
1664 : Node(KClosureTypeName
), TemplateParams(TemplateParams_
),
1665 Params(Params_
), Count(Count_
) {}
1667 template<typename Fn
> void match(Fn F
) const {
1668 F(TemplateParams
, Params
, Count
);
1671 void printDeclarator(OutputBuffer
&OB
) const {
1672 if (!TemplateParams
.empty()) {
1673 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1675 TemplateParams
.printWithComma(OB
);
1679 Params
.printWithComma(OB
);
1683 void printLeft(OutputBuffer
&OB
) const override
{
1687 printDeclarator(OB
);
1691 class StructuredBindingName
: public Node
{
1694 StructuredBindingName(NodeArray Bindings_
)
1695 : Node(KStructuredBindingName
), Bindings(Bindings_
) {}
1697 template<typename Fn
> void match(Fn F
) const { F(Bindings
); }
1699 void printLeft(OutputBuffer
&OB
) const override
{
1701 Bindings
.printWithComma(OB
);
1706 // -- Expression Nodes --
1708 class BinaryExpr
: public Node
{
1710 const std::string_view InfixOperator
;
1714 BinaryExpr(const Node
*LHS_
, std::string_view InfixOperator_
,
1715 const Node
*RHS_
, Prec Prec_
)
1716 : Node(KBinaryExpr
, Prec_
), LHS(LHS_
), InfixOperator(InfixOperator_
),
1719 template <typename Fn
> void match(Fn F
) const {
1720 F(LHS
, InfixOperator
, RHS
, getPrecedence());
1723 void printLeft(OutputBuffer
&OB
) const override
{
1724 bool ParenAll
= OB
.isGtInsideTemplateArgs() &&
1725 (InfixOperator
== ">" || InfixOperator
== ">>");
1728 // Assignment is right associative, with special LHS precedence.
1729 bool IsAssign
= getPrecedence() == Prec::Assign
;
1730 LHS
->printAsOperand(OB
, IsAssign
? Prec::OrIf
: getPrecedence(), !IsAssign
);
1731 // No space before comma operator
1732 if (!(InfixOperator
== ","))
1734 OB
+= InfixOperator
;
1736 RHS
->printAsOperand(OB
, getPrecedence(), IsAssign
);
1742 class ArraySubscriptExpr
: public Node
{
1747 ArraySubscriptExpr(const Node
*Op1_
, const Node
*Op2_
, Prec Prec_
)
1748 : Node(KArraySubscriptExpr
, Prec_
), Op1(Op1_
), Op2(Op2_
) {}
1750 template <typename Fn
> void match(Fn F
) const {
1751 F(Op1
, Op2
, getPrecedence());
1754 void printLeft(OutputBuffer
&OB
) const override
{
1755 Op1
->printAsOperand(OB
, getPrecedence());
1757 Op2
->printAsOperand(OB
);
1762 class PostfixExpr
: public Node
{
1764 const std::string_view Operator
;
1767 PostfixExpr(const Node
*Child_
, std::string_view Operator_
, Prec Prec_
)
1768 : Node(KPostfixExpr
, Prec_
), Child(Child_
), Operator(Operator_
) {}
1770 template <typename Fn
> void match(Fn F
) const {
1771 F(Child
, Operator
, getPrecedence());
1774 void printLeft(OutputBuffer
&OB
) const override
{
1775 Child
->printAsOperand(OB
, getPrecedence(), true);
1780 class ConditionalExpr
: public Node
{
1786 ConditionalExpr(const Node
*Cond_
, const Node
*Then_
, const Node
*Else_
,
1788 : Node(KConditionalExpr
, Prec_
), Cond(Cond_
), Then(Then_
), Else(Else_
) {}
1790 template <typename Fn
> void match(Fn F
) const {
1791 F(Cond
, Then
, Else
, getPrecedence());
1794 void printLeft(OutputBuffer
&OB
) const override
{
1795 Cond
->printAsOperand(OB
, getPrecedence());
1797 Then
->printAsOperand(OB
);
1799 Else
->printAsOperand(OB
, Prec::Assign
, true);
1803 class MemberExpr
: public Node
{
1805 const std::string_view Kind
;
1809 MemberExpr(const Node
*LHS_
, std::string_view Kind_
, const Node
*RHS_
,
1811 : Node(KMemberExpr
, Prec_
), LHS(LHS_
), Kind(Kind_
), RHS(RHS_
) {}
1813 template <typename Fn
> void match(Fn F
) const {
1814 F(LHS
, Kind
, RHS
, getPrecedence());
1817 void printLeft(OutputBuffer
&OB
) const override
{
1818 LHS
->printAsOperand(OB
, getPrecedence(), true);
1820 RHS
->printAsOperand(OB
, getPrecedence(), false);
1824 class SubobjectExpr
: public Node
{
1826 const Node
*SubExpr
;
1827 std::string_view Offset
;
1828 NodeArray UnionSelectors
;
1832 SubobjectExpr(const Node
*Type_
, const Node
*SubExpr_
,
1833 std::string_view Offset_
, NodeArray UnionSelectors_
,
1834 bool OnePastTheEnd_
)
1835 : Node(KSubobjectExpr
), Type(Type_
), SubExpr(SubExpr_
), Offset(Offset_
),
1836 UnionSelectors(UnionSelectors_
), OnePastTheEnd(OnePastTheEnd_
) {}
1838 template<typename Fn
> void match(Fn F
) const {
1839 F(Type
, SubExpr
, Offset
, UnionSelectors
, OnePastTheEnd
);
1842 void printLeft(OutputBuffer
&OB
) const override
{
1846 OB
+= " at offset ";
1847 if (Offset
.empty()) {
1849 } else if (Offset
[0] == 'n') {
1851 OB
+= std::string_view(Offset
.data() + 1, Offset
.size() - 1);
1859 class EnclosingExpr
: public Node
{
1860 const std::string_view Prefix
;
1862 const std::string_view Postfix
;
1865 EnclosingExpr(std::string_view Prefix_
, const Node
*Infix_
,
1866 Prec Prec_
= Prec::Primary
)
1867 : Node(KEnclosingExpr
, Prec_
), Prefix(Prefix_
), Infix(Infix_
) {}
1869 template <typename Fn
> void match(Fn F
) const {
1870 F(Prefix
, Infix
, getPrecedence());
1873 void printLeft(OutputBuffer
&OB
) const override
{
1882 class CastExpr
: public Node
{
1883 // cast_kind<to>(from)
1884 const std::string_view CastKind
;
1889 CastExpr(std::string_view CastKind_
, const Node
*To_
, const Node
*From_
,
1891 : Node(KCastExpr
, Prec_
), CastKind(CastKind_
), To(To_
), From(From_
) {}
1893 template <typename Fn
> void match(Fn F
) const {
1894 F(CastKind
, To
, From
, getPrecedence());
1897 void printLeft(OutputBuffer
&OB
) const override
{
1900 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1906 From
->printAsOperand(OB
);
1911 class SizeofParamPackExpr
: public Node
{
1915 SizeofParamPackExpr(const Node
*Pack_
)
1916 : Node(KSizeofParamPackExpr
), Pack(Pack_
) {}
1918 template<typename Fn
> void match(Fn F
) const { F(Pack
); }
1920 void printLeft(OutputBuffer
&OB
) const override
{
1923 ParameterPackExpansion
PPE(Pack
);
1929 class CallExpr
: public Node
{
1934 CallExpr(const Node
*Callee_
, NodeArray Args_
, Prec Prec_
)
1935 : Node(KCallExpr
, Prec_
), Callee(Callee_
), Args(Args_
) {}
1937 template <typename Fn
> void match(Fn F
) const {
1938 F(Callee
, Args
, getPrecedence());
1941 void printLeft(OutputBuffer
&OB
) const override
{
1944 Args
.printWithComma(OB
);
1949 class NewExpr
: public Node
{
1950 // new (expr_list) type(init_list)
1954 bool IsGlobal
; // ::operator new ?
1955 bool IsArray
; // new[] ?
1957 NewExpr(NodeArray ExprList_
, Node
*Type_
, NodeArray InitList_
, bool IsGlobal_
,
1958 bool IsArray_
, Prec Prec_
)
1959 : Node(KNewExpr
, Prec_
), ExprList(ExprList_
), Type(Type_
),
1960 InitList(InitList_
), IsGlobal(IsGlobal_
), IsArray(IsArray_
) {}
1962 template<typename Fn
> void match(Fn F
) const {
1963 F(ExprList
, Type
, InitList
, IsGlobal
, IsArray
, getPrecedence());
1966 void printLeft(OutputBuffer
&OB
) const override
{
1972 if (!ExprList
.empty()) {
1974 ExprList
.printWithComma(OB
);
1979 if (!InitList
.empty()) {
1981 InitList
.printWithComma(OB
);
1987 class DeleteExpr
: public Node
{
1993 DeleteExpr(Node
*Op_
, bool IsGlobal_
, bool IsArray_
, Prec Prec_
)
1994 : Node(KDeleteExpr
, Prec_
), Op(Op_
), IsGlobal(IsGlobal_
),
1995 IsArray(IsArray_
) {}
1997 template <typename Fn
> void match(Fn F
) const {
1998 F(Op
, IsGlobal
, IsArray
, getPrecedence());
2001 void printLeft(OutputBuffer
&OB
) const override
{
2012 class PrefixExpr
: public Node
{
2013 std::string_view Prefix
;
2017 PrefixExpr(std::string_view Prefix_
, Node
*Child_
, Prec Prec_
)
2018 : Node(KPrefixExpr
, Prec_
), Prefix(Prefix_
), Child(Child_
) {}
2020 template <typename Fn
> void match(Fn F
) const {
2021 F(Prefix
, Child
, getPrecedence());
2024 void printLeft(OutputBuffer
&OB
) const override
{
2026 Child
->printAsOperand(OB
, getPrecedence());
2030 class FunctionParam
: public Node
{
2031 std::string_view Number
;
2034 FunctionParam(std::string_view Number_
)
2035 : Node(KFunctionParam
), Number(Number_
) {}
2037 template<typename Fn
> void match(Fn F
) const { F(Number
); }
2039 void printLeft(OutputBuffer
&OB
) const override
{
2045 class ConversionExpr
: public Node
{
2047 NodeArray Expressions
;
2050 ConversionExpr(const Node
*Type_
, NodeArray Expressions_
, Prec Prec_
)
2051 : Node(KConversionExpr
, Prec_
), Type(Type_
), Expressions(Expressions_
) {}
2053 template <typename Fn
> void match(Fn F
) const {
2054 F(Type
, Expressions
, getPrecedence());
2057 void printLeft(OutputBuffer
&OB
) const override
{
2062 Expressions
.printWithComma(OB
);
2067 class PointerToMemberConversionExpr
: public Node
{
2069 const Node
*SubExpr
;
2070 std::string_view Offset
;
2073 PointerToMemberConversionExpr(const Node
*Type_
, const Node
*SubExpr_
,
2074 std::string_view Offset_
, Prec Prec_
)
2075 : Node(KPointerToMemberConversionExpr
, Prec_
), Type(Type_
),
2076 SubExpr(SubExpr_
), Offset(Offset_
) {}
2078 template <typename Fn
> void match(Fn F
) const {
2079 F(Type
, SubExpr
, Offset
, getPrecedence());
2082 void printLeft(OutputBuffer
&OB
) const override
{
2092 class InitListExpr
: public Node
{
2096 InitListExpr(const Node
*Ty_
, NodeArray Inits_
)
2097 : Node(KInitListExpr
), Ty(Ty_
), Inits(Inits_
) {}
2099 template<typename Fn
> void match(Fn F
) const { F(Ty
, Inits
); }
2101 void printLeft(OutputBuffer
&OB
) const override
{
2105 Inits
.printWithComma(OB
);
2110 class BracedExpr
: public Node
{
2115 BracedExpr(const Node
*Elem_
, const Node
*Init_
, bool IsArray_
)
2116 : Node(KBracedExpr
), Elem(Elem_
), Init(Init_
), IsArray(IsArray_
) {}
2118 template<typename Fn
> void match(Fn F
) const { F(Elem
, Init
, IsArray
); }
2120 void printLeft(OutputBuffer
&OB
) const override
{
2129 if (Init
->getKind() != KBracedExpr
&& Init
->getKind() != KBracedRangeExpr
)
2135 class BracedRangeExpr
: public Node
{
2140 BracedRangeExpr(const Node
*First_
, const Node
*Last_
, const Node
*Init_
)
2141 : Node(KBracedRangeExpr
), First(First_
), Last(Last_
), Init(Init_
) {}
2143 template<typename Fn
> void match(Fn F
) const { F(First
, Last
, Init
); }
2145 void printLeft(OutputBuffer
&OB
) const override
{
2151 if (Init
->getKind() != KBracedExpr
&& Init
->getKind() != KBracedRangeExpr
)
2157 class FoldExpr
: public Node
{
2158 const Node
*Pack
, *Init
;
2159 std::string_view OperatorName
;
2163 FoldExpr(bool IsLeftFold_
, std::string_view OperatorName_
, const Node
*Pack_
,
2165 : Node(KFoldExpr
), Pack(Pack_
), Init(Init_
), OperatorName(OperatorName_
),
2166 IsLeftFold(IsLeftFold_
) {}
2168 template<typename Fn
> void match(Fn F
) const {
2169 F(IsLeftFold
, OperatorName
, Pack
, Init
);
2172 void printLeft(OutputBuffer
&OB
) const override
{
2173 auto PrintPack
= [&] {
2175 ParameterPackExpansion(Pack
).print(OB
);
2180 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2181 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2182 // Fold expr operands are cast-expressions
2183 if (!IsLeftFold
|| Init
!= nullptr) {
2184 // '(init|pack) op '
2186 Init
->printAsOperand(OB
, Prec::Cast
, true);
2189 OB
<< " " << OperatorName
<< " ";
2192 if (IsLeftFold
|| Init
!= nullptr) {
2193 // ' op (init|pack)'
2194 OB
<< " " << OperatorName
<< " ";
2198 Init
->printAsOperand(OB
, Prec::Cast
, true);
2204 class ThrowExpr
: public Node
{
2208 ThrowExpr(const Node
*Op_
) : Node(KThrowExpr
), Op(Op_
) {}
2210 template<typename Fn
> void match(Fn F
) const { F(Op
); }
2212 void printLeft(OutputBuffer
&OB
) const override
{
2218 class BoolExpr
: public Node
{
2222 BoolExpr(bool Value_
) : Node(KBoolExpr
), Value(Value_
) {}
2224 template<typename Fn
> void match(Fn F
) const { F(Value
); }
2226 void printLeft(OutputBuffer
&OB
) const override
{
2227 OB
+= Value
? std::string_view("true") : std::string_view("false");
2231 class StringLiteral
: public Node
{
2235 StringLiteral(const Node
*Type_
) : Node(KStringLiteral
), Type(Type_
) {}
2237 template<typename Fn
> void match(Fn F
) const { F(Type
); }
2239 void printLeft(OutputBuffer
&OB
) const override
{
2246 class LambdaExpr
: public Node
{
2250 LambdaExpr(const Node
*Type_
) : Node(KLambdaExpr
), Type(Type_
) {}
2252 template<typename Fn
> void match(Fn F
) const { F(Type
); }
2254 void printLeft(OutputBuffer
&OB
) const override
{
2256 if (Type
->getKind() == KClosureTypeName
)
2257 static_cast<const ClosureTypeName
*>(Type
)->printDeclarator(OB
);
2262 class EnumLiteral
: public Node
{
2265 std::string_view Integer
;
2268 EnumLiteral(const Node
*Ty_
, std::string_view Integer_
)
2269 : Node(KEnumLiteral
), Ty(Ty_
), Integer(Integer_
) {}
2271 template<typename Fn
> void match(Fn F
) const { F(Ty
, Integer
); }
2273 void printLeft(OutputBuffer
&OB
) const override
{
2278 if (Integer
[0] == 'n')
2279 OB
<< '-' << std::string_view(Integer
.data() + 1, Integer
.size() - 1);
2285 class IntegerLiteral
: public Node
{
2286 std::string_view Type
;
2287 std::string_view Value
;
2290 IntegerLiteral(std::string_view Type_
, std::string_view Value_
)
2291 : Node(KIntegerLiteral
), Type(Type_
), Value(Value_
) {}
2293 template<typename Fn
> void match(Fn F
) const { F(Type
, Value
); }
2295 void printLeft(OutputBuffer
&OB
) const override
{
2296 if (Type
.size() > 3) {
2302 if (Value
[0] == 'n')
2303 OB
<< '-' << std::string_view(Value
.data() + 1, Value
.size() - 1);
2307 if (Type
.size() <= 3)
2312 template <class Float
> struct FloatData
;
2314 namespace float_literal_impl
{
2315 constexpr Node::Kind
getFloatLiteralKind(float *) {
2316 return Node::KFloatLiteral
;
2318 constexpr Node::Kind
getFloatLiteralKind(double *) {
2319 return Node::KDoubleLiteral
;
2321 constexpr Node::Kind
getFloatLiteralKind(long double *) {
2322 return Node::KLongDoubleLiteral
;
2326 template <class Float
> class FloatLiteralImpl
: public Node
{
2327 const std::string_view Contents
;
2329 static constexpr Kind KindForClass
=
2330 float_literal_impl::getFloatLiteralKind((Float
*)nullptr);
2333 FloatLiteralImpl(std::string_view Contents_
)
2334 : Node(KindForClass
), Contents(Contents_
) {}
2336 template<typename Fn
> void match(Fn F
) const { F(Contents
); }
2338 void printLeft(OutputBuffer
&OB
) const override
{
2339 const size_t N
= FloatData
<Float
>::mangled_size
;
2340 if (Contents
.size() >= N
) {
2343 char buf
[sizeof(Float
)];
2345 const char *t
= Contents
.data();
2346 const char *last
= t
+ N
;
2348 for (; t
!= last
; ++t
, ++e
) {
2349 unsigned d1
= isdigit(*t
) ? static_cast<unsigned>(*t
- '0')
2350 : static_cast<unsigned>(*t
- 'a' + 10);
2352 unsigned d0
= isdigit(*t
) ? static_cast<unsigned>(*t
- '0')
2353 : static_cast<unsigned>(*t
- 'a' + 10);
2354 *e
= static_cast<char>((d1
<< 4) + d0
);
2356 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2357 std::reverse(buf
, e
);
2359 char num
[FloatData
<Float
>::max_demangled_size
] = {0};
2360 int n
= snprintf(num
, sizeof(num
), FloatData
<Float
>::spec
, value
);
2361 OB
+= std::string_view(num
, n
);
2366 using FloatLiteral
= FloatLiteralImpl
<float>;
2367 using DoubleLiteral
= FloatLiteralImpl
<double>;
2368 using LongDoubleLiteral
= FloatLiteralImpl
<long double>;
2370 /// Visit the node. Calls \c F(P), where \c P is the node cast to the
2371 /// appropriate derived class.
2372 template<typename Fn
>
2373 void Node::visit(Fn F
) const {
2377 return F(static_cast<const X *>(this));
2378 #include "ItaniumNodes.def"
2380 assert(0 && "unknown mangling node kind");
2383 /// Determine the kind of a node from its type.
2384 template<typename NodeT
> struct NodeKind
;
2386 template <> struct NodeKind<X> { \
2387 static constexpr Node::Kind Kind = Node::K##X; \
2388 static constexpr const char *name() { return #X; } \
2390 #include "ItaniumNodes.def"
2392 template <typename Derived
, typename Alloc
> struct AbstractManglingParser
{
2396 // Name stack, this is used by the parser to hold temporary names that were
2397 // parsed. The parser collapses multiple names into new nodes to construct
2398 // the AST. Once the parser is finished, names.size() == 1.
2399 PODSmallVector
<Node
*, 32> Names
;
2401 // Substitution table. Itanium supports name substitutions as a means of
2402 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2404 PODSmallVector
<Node
*, 32> Subs
;
2406 using TemplateParamList
= PODSmallVector
<Node
*, 8>;
2408 class ScopedTemplateParamList
{
2409 AbstractManglingParser
*Parser
;
2410 size_t OldNumTemplateParamLists
;
2411 TemplateParamList Params
;
2414 ScopedTemplateParamList(AbstractManglingParser
*TheParser
)
2415 : Parser(TheParser
),
2416 OldNumTemplateParamLists(TheParser
->TemplateParams
.size()) {
2417 Parser
->TemplateParams
.push_back(&Params
);
2419 ~ScopedTemplateParamList() {
2420 assert(Parser
->TemplateParams
.size() >= OldNumTemplateParamLists
);
2421 Parser
->TemplateParams
.dropBack(OldNumTemplateParamLists
);
2425 // Template parameter table. Like the above, but referenced like "T42_".
2426 // This has a smaller size compared to Subs and Names because it can be
2427 // stored on the stack.
2428 TemplateParamList OuterTemplateParams
;
2430 // Lists of template parameters indexed by template parameter depth,
2431 // referenced like "TL2_4_". If nonempty, element 0 is always
2432 // OuterTemplateParams; inner elements are always template parameter lists of
2433 // lambda expressions. For a generic lambda with no explicit template
2434 // parameter list, the corresponding parameter list pointer will be null.
2435 PODSmallVector
<TemplateParamList
*, 4> TemplateParams
;
2437 // Set of unresolved forward <template-param> references. These can occur in a
2438 // conversion operator's type, and are resolved in the enclosing <encoding>.
2439 PODSmallVector
<ForwardTemplateReference
*, 4> ForwardTemplateRefs
;
2441 bool TryToParseTemplateArgs
= true;
2442 bool PermitForwardTemplateReferences
= false;
2443 size_t ParsingLambdaParamsAtLevel
= (size_t)-1;
2445 unsigned NumSyntheticTemplateParameters
[3] = {};
2449 AbstractManglingParser(const char *First_
, const char *Last_
)
2450 : First(First_
), Last(Last_
) {}
2452 Derived
&getDerived() { return static_cast<Derived
&>(*this); }
2454 void reset(const char *First_
, const char *Last_
) {
2459 TemplateParams
.clear();
2460 ParsingLambdaParamsAtLevel
= (size_t)-1;
2461 TryToParseTemplateArgs
= true;
2462 PermitForwardTemplateReferences
= false;
2463 for (int I
= 0; I
!= 3; ++I
)
2464 NumSyntheticTemplateParameters
[I
] = 0;
2465 ASTAllocator
.reset();
2468 template <class T
, class... Args
> Node
*make(Args
&&... args
) {
2469 return ASTAllocator
.template makeNode
<T
>(std::forward
<Args
>(args
)...);
2472 template <class It
> NodeArray
makeNodeArray(It begin
, It end
) {
2473 size_t sz
= static_cast<size_t>(end
- begin
);
2474 void *mem
= ASTAllocator
.allocateNodeArray(sz
);
2475 Node
**data
= new (mem
) Node
*[sz
];
2476 std::copy(begin
, end
, data
);
2477 return NodeArray(data
, sz
);
2480 NodeArray
popTrailingNodeArray(size_t FromPosition
) {
2481 assert(FromPosition
<= Names
.size());
2483 makeNodeArray(Names
.begin() + (long)FromPosition
, Names
.end());
2484 Names
.dropBack(FromPosition
);
2488 bool consumeIf(std::string_view S
) {
2489 if (starts_with(std::string_view(First
, Last
- First
), S
)) {
2496 bool consumeIf(char C
) {
2497 if (First
!= Last
&& *First
== C
) {
2504 char consume() { return First
!= Last
? *First
++ : '\0'; }
2506 char look(unsigned Lookahead
= 0) const {
2507 if (static_cast<size_t>(Last
- First
) <= Lookahead
)
2509 return First
[Lookahead
];
2512 size_t numLeft() const { return static_cast<size_t>(Last
- First
); }
2514 std::string_view
parseNumber(bool AllowNegative
= false);
2515 Qualifiers
parseCVQualifiers();
2516 bool parsePositiveInteger(size_t *Out
);
2517 std::string_view
parseBareSourceName();
2519 bool parseSeqId(size_t *Out
);
2520 Node
*parseSubstitution();
2521 Node
*parseTemplateParam();
2522 Node
*parseTemplateParamDecl();
2523 Node
*parseTemplateArgs(bool TagTemplates
= false);
2524 Node
*parseTemplateArg();
2526 /// Parse the <expr> production.
2528 Node
*parsePrefixExpr(std::string_view Kind
, Node::Prec Prec
);
2529 Node
*parseBinaryExpr(std::string_view Kind
, Node::Prec Prec
);
2530 Node
*parseIntegerLiteral(std::string_view Lit
);
2531 Node
*parseExprPrimary();
2532 template <class Float
> Node
*parseFloatingLiteral();
2533 Node
*parseFunctionParam();
2534 Node
*parseConversionExpr();
2535 Node
*parseBracedExpr();
2536 Node
*parseFoldExpr();
2537 Node
*parsePointerToMemberConversionExpr(Node::Prec Prec
);
2538 Node
*parseSubobjectExpr();
2540 /// Parse the <type> production.
2542 Node
*parseFunctionType();
2543 Node
*parseVectorType();
2544 Node
*parseDecltype();
2545 Node
*parseArrayType();
2546 Node
*parsePointerToMemberType();
2547 Node
*parseClassEnumType();
2548 Node
*parseQualifiedType();
2550 Node
*parseEncoding();
2551 bool parseCallOffset();
2552 Node
*parseSpecialName();
2554 /// Holds some extra information about a <name> that is being parsed. This
2555 /// information is only pertinent if the <name> refers to an <encoding>.
2557 bool CtorDtorConversion
= false;
2558 bool EndsWithTemplateArgs
= false;
2559 Qualifiers CVQualifiers
= QualNone
;
2560 FunctionRefQual ReferenceQualifier
= FrefQualNone
;
2561 size_t ForwardTemplateRefsBegin
;
2563 NameState(AbstractManglingParser
*Enclosing
)
2564 : ForwardTemplateRefsBegin(Enclosing
->ForwardTemplateRefs
.size()) {}
2567 bool resolveForwardTemplateRefs(NameState
&State
) {
2568 size_t I
= State
.ForwardTemplateRefsBegin
;
2569 size_t E
= ForwardTemplateRefs
.size();
2570 for (; I
< E
; ++I
) {
2571 size_t Idx
= ForwardTemplateRefs
[I
]->Index
;
2572 if (TemplateParams
.empty() || !TemplateParams
[0] ||
2573 Idx
>= TemplateParams
[0]->size())
2575 ForwardTemplateRefs
[I
]->Ref
= (*TemplateParams
[0])[Idx
];
2577 ForwardTemplateRefs
.dropBack(State
.ForwardTemplateRefsBegin
);
2581 /// Parse the <name> production>
2582 Node
*parseName(NameState
*State
= nullptr);
2583 Node
*parseLocalName(NameState
*State
);
2584 Node
*parseOperatorName(NameState
*State
);
2585 bool parseModuleNameOpt(ModuleName
*&Module
);
2586 Node
*parseUnqualifiedName(NameState
*State
, Node
*Scope
, ModuleName
*Module
);
2587 Node
*parseUnnamedTypeName(NameState
*State
);
2588 Node
*parseSourceName(NameState
*State
);
2589 Node
*parseUnscopedName(NameState
*State
, bool *isSubstName
);
2590 Node
*parseNestedName(NameState
*State
);
2591 Node
*parseCtorDtorName(Node
*&SoFar
, NameState
*State
);
2593 Node
*parseAbiTags(Node
*N
);
2595 struct OperatorInfo
{
2596 enum OIKind
: unsigned char {
2597 Prefix
, // Prefix unary: @ expr
2598 Postfix
, // Postfix unary: expr @
2599 Binary
, // Binary: lhs @ rhs
2600 Array
, // Array index: lhs [ rhs ]
2601 Member
, // Member access: lhs @ rhs
2604 Call
, // Function call: expr (expr*)
2605 CCast
, // C cast: (type)expr
2606 Conditional
, // Conditional: expr ? expr : expr
2607 NameOnly
, // Overload only, not allowed in expression.
2608 // Below do not have operator names
2609 NamedCast
, // Named cast, @<type>(expr)
2610 OfIdOp
, // alignof, sizeof, typeid
2612 Unnameable
= NamedCast
,
2614 char Enc
[2]; // Encoding
2615 OIKind Kind
; // Kind of operator
2616 bool Flag
: 1; // Entry-specific flag
2617 Node::Prec Prec
: 7; // Precedence
2618 const char *Name
; // Spelling
2621 constexpr OperatorInfo(const char (&E
)[3], OIKind K
, bool F
, Node::Prec P
,
2623 : Enc
{E
[0], E
[1]}, Kind
{K
}, Flag
{F
}, Prec
{P
}, Name
{N
} {}
2626 bool operator<(const OperatorInfo
&Other
) const {
2627 return *this < Other
.Enc
;
2629 bool operator<(const char *Peek
) const {
2630 return Enc
[0] < Peek
[0] || (Enc
[0] == Peek
[0] && Enc
[1] < Peek
[1]);
2632 bool operator==(const char *Peek
) const {
2633 return Enc
[0] == Peek
[0] && Enc
[1] == Peek
[1];
2635 bool operator!=(const char *Peek
) const { return !this->operator==(Peek
); }
2638 std::string_view
getSymbol() const {
2639 std::string_view Res
= Name
;
2640 if (Kind
< Unnameable
) {
2641 assert(starts_with(Res
, "operator") &&
2642 "operator name does not start with 'operator'");
2643 Res
.remove_prefix(sizeof("operator") - 1);
2644 if (starts_with(Res
, ' '))
2645 Res
.remove_prefix(1);
2649 std::string_view
getName() const { return Name
; }
2650 OIKind
getKind() const { return Kind
; }
2651 bool getFlag() const { return Flag
; }
2652 Node::Prec
getPrecedence() const { return Prec
; }
2654 static const OperatorInfo Ops
[];
2655 static const size_t NumOps
;
2656 const OperatorInfo
*parseOperatorEncoding();
2658 /// Parse the <unresolved-name> production.
2659 Node
*parseUnresolvedName(bool Global
);
2660 Node
*parseSimpleId();
2661 Node
*parseBaseUnresolvedName();
2662 Node
*parseUnresolvedType();
2663 Node
*parseDestructorName();
2665 /// Top-level entry point into the parser.
2669 const char* parse_discriminator(const char* first
, const char* last
);
2671 // <name> ::= <nested-name> // N
2672 // ::= <local-name> # See Scope Encoding below // Z
2673 // ::= <unscoped-template-name> <template-args>
2674 // ::= <unscoped-name>
2676 // <unscoped-template-name> ::= <unscoped-name>
2677 // ::= <substitution>
2678 template <typename Derived
, typename Alloc
>
2679 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseName(NameState
*State
) {
2681 return getDerived().parseNestedName(State
);
2683 return getDerived().parseLocalName(State
);
2685 Node
*Result
= nullptr;
2686 bool IsSubst
= false;
2688 Result
= getDerived().parseUnscopedName(State
, &IsSubst
);
2692 if (look() == 'I') {
2693 // ::= <unscoped-template-name> <template-args>
2695 // An unscoped-template-name is substitutable.
2696 Subs
.push_back(Result
);
2697 Node
*TA
= getDerived().parseTemplateArgs(State
!= nullptr);
2701 State
->EndsWithTemplateArgs
= true;
2702 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
2703 } else if (IsSubst
) {
2704 // The substitution case must be followed by <template-args>.
2711 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2712 // := Z <function encoding> E s [<discriminator>]
2713 // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
2714 template <typename Derived
, typename Alloc
>
2715 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseLocalName(NameState
*State
) {
2716 if (!consumeIf('Z'))
2718 Node
*Encoding
= getDerived().parseEncoding();
2719 if (Encoding
== nullptr || !consumeIf('E'))
2722 if (consumeIf('s')) {
2723 First
= parse_discriminator(First
, Last
);
2724 auto *StringLitName
= make
<NameType
>("string literal");
2727 return make
<LocalName
>(Encoding
, StringLitName
);
2730 if (consumeIf('d')) {
2732 if (!consumeIf('_'))
2734 Node
*N
= getDerived().parseName(State
);
2737 return make
<LocalName
>(Encoding
, N
);
2740 Node
*Entity
= getDerived().parseName(State
);
2741 if (Entity
== nullptr)
2743 First
= parse_discriminator(First
, Last
);
2744 return make
<LocalName
>(Encoding
, Entity
);
2747 // <unscoped-name> ::= <unqualified-name>
2748 // ::= St <unqualified-name> # ::std::
2750 template <typename Derived
, typename Alloc
>
2752 AbstractManglingParser
<Derived
, Alloc
>::parseUnscopedName(NameState
*State
,
2755 Node
*Std
= nullptr;
2756 if (consumeIf("St")) {
2757 Std
= make
<NameType
>("std");
2762 Node
*Res
= nullptr;
2763 ModuleName
*Module
= nullptr;
2764 if (look() == 'S') {
2765 Node
*S
= getDerived().parseSubstitution();
2768 if (S
->getKind() == Node::KModuleName
)
2769 Module
= static_cast<ModuleName
*>(S
);
2770 else if (IsSubst
&& Std
== nullptr) {
2778 if (Res
== nullptr || Std
!= nullptr) {
2779 Res
= getDerived().parseUnqualifiedName(State
, Std
, Module
);
2785 // <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
2786 // ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
2787 // ::= [<module-name>] L? <source-name> [<abi-tags>]
2788 // ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
2789 // # structured binding declaration
2790 // ::= [<module-name>] L? DC <source-name>+ E
2791 template <typename Derived
, typename Alloc
>
2792 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnqualifiedName(
2793 NameState
*State
, Node
*Scope
, ModuleName
*Module
) {
2794 if (getDerived().parseModuleNameOpt(Module
))
2800 if (look() >= '1' && look() <= '9') {
2801 Result
= getDerived().parseSourceName(State
);
2802 } else if (look() == 'U') {
2803 Result
= getDerived().parseUnnamedTypeName(State
);
2804 } else if (consumeIf("DC")) {
2805 // Structured binding
2806 size_t BindingsBegin
= Names
.size();
2808 Node
*Binding
= getDerived().parseSourceName(State
);
2809 if (Binding
== nullptr)
2811 Names
.push_back(Binding
);
2812 } while (!consumeIf('E'));
2813 Result
= make
<StructuredBindingName
>(popTrailingNodeArray(BindingsBegin
));
2814 } else if (look() == 'C' || look() == 'D') {
2815 // A <ctor-dtor-name>.
2816 if (Scope
== nullptr || Module
!= nullptr)
2818 Result
= getDerived().parseCtorDtorName(Scope
, State
);
2820 Result
= getDerived().parseOperatorName(State
);
2823 if (Result
!= nullptr && Module
!= nullptr)
2824 Result
= make
<ModuleEntity
>(Module
, Result
);
2825 if (Result
!= nullptr)
2826 Result
= getDerived().parseAbiTags(Result
);
2827 if (Result
!= nullptr && Scope
!= nullptr)
2828 Result
= make
<NestedName
>(Scope
, Result
);
2833 // <module-name> ::= <module-subname>
2834 // ::= <module-name> <module-subname>
2835 // ::= <substitution> # passed in by caller
2836 // <module-subname> ::= W <source-name>
2837 // ::= W P <source-name>
2838 template <typename Derived
, typename Alloc
>
2839 bool AbstractManglingParser
<Derived
, Alloc
>::parseModuleNameOpt(
2840 ModuleName
*&Module
) {
2841 while (consumeIf('W')) {
2842 bool IsPartition
= consumeIf('P');
2843 Node
*Sub
= getDerived().parseSourceName(nullptr);
2847 static_cast<ModuleName
*>(make
<ModuleName
>(Module
, Sub
, IsPartition
));
2848 Subs
.push_back(Module
);
2854 // <unnamed-type-name> ::= Ut [<nonnegative number>] _
2855 // ::= <closure-type-name>
2857 // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2859 // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
2860 template <typename Derived
, typename Alloc
>
2862 AbstractManglingParser
<Derived
, Alloc
>::parseUnnamedTypeName(NameState
*State
) {
2863 // <template-params> refer to the innermost <template-args>. Clear out any
2864 // outer args that we may have inserted into TemplateParams.
2865 if (State
!= nullptr)
2866 TemplateParams
.clear();
2868 if (consumeIf("Ut")) {
2869 std::string_view Count
= parseNumber();
2870 if (!consumeIf('_'))
2872 return make
<UnnamedTypeName
>(Count
);
2874 if (consumeIf("Ul")) {
2875 ScopedOverride
<size_t> SwapParams(ParsingLambdaParamsAtLevel
,
2876 TemplateParams
.size());
2877 ScopedTemplateParamList
LambdaTemplateParams(this);
2879 size_t ParamsBegin
= Names
.size();
2880 while (look() == 'T' &&
2881 std::string_view("yptn").find(look(1)) != std::string_view::npos
) {
2882 Node
*T
= parseTemplateParamDecl();
2887 NodeArray TempParams
= popTrailingNodeArray(ParamsBegin
);
2889 // FIXME: If TempParams is empty and none of the function parameters
2890 // includes 'auto', we should remove LambdaTemplateParams from the
2891 // TemplateParams list. Unfortunately, we don't find out whether there are
2892 // any 'auto' parameters until too late in an example such as:
2894 // template<typename T> void f(
2895 // decltype([](decltype([]<typename T>(T v) {}),
2897 // template<typename T> void f(
2898 // decltype([](decltype([]<typename T>(T w) {}),
2901 // Here, the type of v is at level 2 but the type of w is at level 1. We
2902 // don't find this out until we encounter the type of the next parameter.
2904 // However, compilers can't actually cope with the former example in
2905 // practice, and it's likely to be made ill-formed in future, so we don't
2906 // need to support it here.
2908 // If we encounter an 'auto' in the function parameter types, we will
2909 // recreate a template parameter scope for it, but any intervening lambdas
2910 // will be parsed in the 'wrong' template parameter depth.
2911 if (TempParams
.empty())
2912 TemplateParams
.pop_back();
2914 if (!consumeIf("vE")) {
2916 Node
*P
= getDerived().parseType();
2920 } while (!consumeIf('E'));
2922 NodeArray Params
= popTrailingNodeArray(ParamsBegin
);
2924 std::string_view Count
= parseNumber();
2925 if (!consumeIf('_'))
2927 return make
<ClosureTypeName
>(TempParams
, Params
, Count
);
2929 if (consumeIf("Ub")) {
2930 (void)parseNumber();
2931 if (!consumeIf('_'))
2933 return make
<NameType
>("'block-literal'");
2938 // <source-name> ::= <positive length number> <identifier>
2939 template <typename Derived
, typename Alloc
>
2940 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSourceName(NameState
*) {
2942 if (parsePositiveInteger(&Length
))
2944 if (numLeft() < Length
|| Length
== 0)
2946 std::string_view
Name(First
, Length
);
2948 if (starts_with(Name
, "_GLOBAL__N"))
2949 return make
<NameType
>("(anonymous namespace)");
2950 return make
<NameType
>(Name
);
2953 // Operator encodings
2954 template <typename Derived
, typename Alloc
>
2955 const typename AbstractManglingParser
<
2956 Derived
, Alloc
>::OperatorInfo AbstractManglingParser
<Derived
,
2958 // Keep ordered by encoding
2959 {"aN", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator&="},
2960 {"aS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator="},
2961 {"aa", OperatorInfo::Binary
, false, Node::Prec::AndIf
, "operator&&"},
2962 {"ad", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator&"},
2963 {"an", OperatorInfo::Binary
, false, Node::Prec::And
, "operator&"},
2964 {"at", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Unary
, "alignof "},
2965 {"aw", OperatorInfo::NameOnly
, false, Node::Prec::Primary
,
2966 "operator co_await"},
2967 {"az", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Unary
, "alignof "},
2968 {"cc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "const_cast"},
2969 {"cl", OperatorInfo::Call
, false, Node::Prec::Postfix
, "operator()"},
2970 {"cm", OperatorInfo::Binary
, false, Node::Prec::Comma
, "operator,"},
2971 {"co", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator~"},
2972 {"cv", OperatorInfo::CCast
, false, Node::Prec::Cast
, "operator"}, // C Cast
2973 {"dV", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator/="},
2974 {"da", OperatorInfo::Del
, /*Ary*/ true, Node::Prec::Unary
,
2975 "operator delete[]"},
2976 {"dc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "dynamic_cast"},
2977 {"de", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator*"},
2978 {"dl", OperatorInfo::Del
, /*Ary*/ false, Node::Prec::Unary
,
2980 {"ds", OperatorInfo::Member
, /*Named*/ false, Node::Prec::PtrMem
,
2982 {"dt", OperatorInfo::Member
, /*Named*/ false, Node::Prec::Postfix
,
2984 {"dv", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator/"},
2985 {"eO", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator^="},
2986 {"eo", OperatorInfo::Binary
, false, Node::Prec::Xor
, "operator^"},
2987 {"eq", OperatorInfo::Binary
, false, Node::Prec::Equality
, "operator=="},
2988 {"ge", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator>="},
2989 {"gt", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator>"},
2990 {"ix", OperatorInfo::Array
, false, Node::Prec::Postfix
, "operator[]"},
2991 {"lS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator<<="},
2992 {"le", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator<="},
2993 {"ls", OperatorInfo::Binary
, false, Node::Prec::Shift
, "operator<<"},
2994 {"lt", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator<"},
2995 {"mI", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator-="},
2996 {"mL", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator*="},
2997 {"mi", OperatorInfo::Binary
, false, Node::Prec::Additive
, "operator-"},
2998 {"ml", OperatorInfo::Binary
, false, Node::Prec::Multiplicative
,
3000 {"mm", OperatorInfo::Postfix
, false, Node::Prec::Postfix
, "operator--"},
3001 {"na", OperatorInfo::New
, /*Ary*/ true, Node::Prec::Unary
,
3003 {"ne", OperatorInfo::Binary
, false, Node::Prec::Equality
, "operator!="},
3004 {"ng", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator-"},
3005 {"nt", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator!"},
3006 {"nw", OperatorInfo::New
, /*Ary*/ false, Node::Prec::Unary
, "operator new"},
3007 {"oR", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator|="},
3008 {"oo", OperatorInfo::Binary
, false, Node::Prec::OrIf
, "operator||"},
3009 {"or", OperatorInfo::Binary
, false, Node::Prec::Ior
, "operator|"},
3010 {"pL", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator+="},
3011 {"pl", OperatorInfo::Binary
, false, Node::Prec::Additive
, "operator+"},
3012 {"pm", OperatorInfo::Member
, /*Named*/ false, Node::Prec::PtrMem
,
3014 {"pp", OperatorInfo::Postfix
, false, Node::Prec::Postfix
, "operator++"},
3015 {"ps", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator+"},
3016 {"pt", OperatorInfo::Member
, /*Named*/ true, Node::Prec::Postfix
,
3018 {"qu", OperatorInfo::Conditional
, false, Node::Prec::Conditional
,
3020 {"rM", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator%="},
3021 {"rS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator>>="},
3022 {"rc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
,
3023 "reinterpret_cast"},
3024 {"rm", OperatorInfo::Binary
, false, Node::Prec::Multiplicative
,
3026 {"rs", OperatorInfo::Binary
, false, Node::Prec::Shift
, "operator>>"},
3027 {"sc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "static_cast"},
3028 {"ss", OperatorInfo::Binary
, false, Node::Prec::Spaceship
, "operator<=>"},
3029 {"st", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Unary
, "sizeof "},
3030 {"sz", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Unary
, "sizeof "},
3031 {"te", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Postfix
,
3033 {"ti", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Postfix
, "typeid "},
3035 template <typename Derived
, typename Alloc
>
3036 const size_t AbstractManglingParser
<Derived
, Alloc
>::NumOps
= sizeof(Ops
) /
3039 // If the next 2 chars are an operator encoding, consume them and return their
3040 // OperatorInfo. Otherwise return nullptr.
3041 template <typename Derived
, typename Alloc
>
3042 const typename AbstractManglingParser
<Derived
, Alloc
>::OperatorInfo
*
3043 AbstractManglingParser
<Derived
, Alloc
>::parseOperatorEncoding() {
3047 // We can't use lower_bound as that can link to symbols in the C++ library,
3048 // and this must remain independant of that.
3049 size_t lower
= 0u, upper
= NumOps
- 1; // Inclusive bounds.
3050 while (upper
!= lower
) {
3051 size_t middle
= (upper
+ lower
) / 2;
3052 if (Ops
[middle
] < First
)
3057 if (Ops
[lower
] != First
)
3064 // <operator-name> ::= See parseOperatorEncoding()
3065 // ::= li <source-name> # operator ""
3066 // ::= v <digit> <source-name> # vendor extended operator
3067 template <typename Derived
, typename Alloc
>
3069 AbstractManglingParser
<Derived
, Alloc
>::parseOperatorName(NameState
*State
) {
3070 if (const auto *Op
= parseOperatorEncoding()) {
3071 if (Op
->getKind() == OperatorInfo::CCast
) {
3072 // ::= cv <type> # (cast)
3073 ScopedOverride
<bool> SaveTemplate(TryToParseTemplateArgs
, false);
3074 // If we're parsing an encoding, State != nullptr and the conversion
3075 // operators' <type> could have a <template-param> that refers to some
3076 // <template-arg>s further ahead in the mangled name.
3077 ScopedOverride
<bool> SavePermit(PermitForwardTemplateReferences
,
3078 PermitForwardTemplateReferences
||
3080 Node
*Ty
= getDerived().parseType();
3083 if (State
) State
->CtorDtorConversion
= true;
3084 return make
<ConversionOperatorType
>(Ty
);
3087 if (Op
->getKind() >= OperatorInfo::Unnameable
)
3088 /* Not a nameable operator. */
3090 if (Op
->getKind() == OperatorInfo::Member
&& !Op
->getFlag())
3091 /* Not a nameable MemberExpr */
3094 return make
<NameType
>(Op
->getName());
3097 if (consumeIf("li")) {
3098 // ::= li <source-name> # operator ""
3099 Node
*SN
= getDerived().parseSourceName(State
);
3102 return make
<LiteralOperator
>(SN
);
3105 if (consumeIf('v')) {
3106 // ::= v <digit> <source-name> # vendor extended operator
3107 if (look() >= '0' && look() <= '9') {
3109 Node
*SN
= getDerived().parseSourceName(State
);
3112 return make
<ConversionOperatorType
>(SN
);
3120 // <ctor-dtor-name> ::= C1 # complete object constructor
3121 // ::= C2 # base object constructor
3122 // ::= C3 # complete object allocating constructor
3123 // extension ::= C4 # gcc old-style "[unified]" constructor
3124 // extension ::= C5 # the COMDAT used for ctors
3125 // ::= D0 # deleting destructor
3126 // ::= D1 # complete object destructor
3127 // ::= D2 # base object destructor
3128 // extension ::= D4 # gcc old-style "[unified]" destructor
3129 // extension ::= D5 # the COMDAT used for dtors
3130 template <typename Derived
, typename Alloc
>
3132 AbstractManglingParser
<Derived
, Alloc
>::parseCtorDtorName(Node
*&SoFar
,
3134 if (SoFar
->getKind() == Node::KSpecialSubstitution
) {
3135 // Expand the special substitution.
3136 SoFar
= make
<ExpandedSpecialSubstitution
>(
3137 static_cast<SpecialSubstitution
*>(SoFar
));
3142 if (consumeIf('C')) {
3143 bool IsInherited
= consumeIf('I');
3144 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3147 int Variant
= look() - '0';
3149 if (State
) State
->CtorDtorConversion
= true;
3151 if (getDerived().parseName(State
) == nullptr)
3154 return make
<CtorDtorName
>(SoFar
, /*IsDtor=*/false, Variant
);
3157 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3158 look(1) == '4' || look(1) == '5')) {
3159 int Variant
= look(1) - '0';
3161 if (State
) State
->CtorDtorConversion
= true;
3162 return make
<CtorDtorName
>(SoFar
, /*IsDtor=*/true, Variant
);
3168 // <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3169 // <unqualified-name> E
3170 // ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3171 // <template-args> E
3173 // <prefix> ::= <prefix> <unqualified-name>
3174 // ::= <template-prefix> <template-args>
3175 // ::= <template-param>
3178 // ::= <substitution>
3179 // ::= <prefix> <data-member-prefix>
3182 // <data-member-prefix> := <member source-name> [<template-args>] M
3184 // <template-prefix> ::= <prefix> <template unqualified-name>
3185 // ::= <template-param>
3186 // ::= <substitution>
3187 template <typename Derived
, typename Alloc
>
3189 AbstractManglingParser
<Derived
, Alloc
>::parseNestedName(NameState
*State
) {
3190 if (!consumeIf('N'))
3193 Qualifiers CVTmp
= parseCVQualifiers();
3194 if (State
) State
->CVQualifiers
= CVTmp
;
3196 if (consumeIf('O')) {
3197 if (State
) State
->ReferenceQualifier
= FrefQualRValue
;
3198 } else if (consumeIf('R')) {
3199 if (State
) State
->ReferenceQualifier
= FrefQualLValue
;
3201 if (State
) State
->ReferenceQualifier
= FrefQualNone
;
3204 Node
*SoFar
= nullptr;
3205 while (!consumeIf('E')) {
3207 // Only set end-with-template on the case that does that.
3208 State
->EndsWithTemplateArgs
= false;
3210 if (look() == 'T') {
3211 // ::= <template-param>
3212 if (SoFar
!= nullptr)
3213 return nullptr; // Cannot have a prefix.
3214 SoFar
= getDerived().parseTemplateParam();
3215 } else if (look() == 'I') {
3216 // ::= <template-prefix> <template-args>
3217 if (SoFar
== nullptr)
3218 return nullptr; // Must have a prefix.
3219 Node
*TA
= getDerived().parseTemplateArgs(State
!= nullptr);
3222 if (SoFar
->getKind() == Node::KNameWithTemplateArgs
)
3223 // Semantically <template-args> <template-args> cannot be generated by a
3224 // C++ entity. There will always be [something like] a name between
3228 State
->EndsWithTemplateArgs
= true;
3229 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3230 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3232 if (SoFar
!= nullptr)
3233 return nullptr; // Cannot have a prefix.
3234 SoFar
= getDerived().parseDecltype();
3236 ModuleName
*Module
= nullptr;
3238 if (look() == 'S') {
3239 // ::= <substitution>
3241 if (look(1) == 't') {
3243 S
= make
<NameType
>("std");
3245 S
= getDerived().parseSubstitution();
3249 if (S
->getKind() == Node::KModuleName
) {
3250 Module
= static_cast<ModuleName
*>(S
);
3251 } else if (SoFar
!= nullptr) {
3252 return nullptr; // Cannot have a prefix.
3255 continue; // Do not push a new substitution.
3259 // ::= [<prefix>] <unqualified-name>
3260 SoFar
= getDerived().parseUnqualifiedName(State
, SoFar
, Module
);
3263 if (SoFar
== nullptr)
3265 Subs
.push_back(SoFar
);
3268 // <data-member-prefix> := <member source-name> [<template-args>] M
3272 if (SoFar
== nullptr || Subs
.empty())
3279 // <simple-id> ::= <source-name> [ <template-args> ]
3280 template <typename Derived
, typename Alloc
>
3281 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSimpleId() {
3282 Node
*SN
= getDerived().parseSourceName(/*NameState=*/nullptr);
3285 if (look() == 'I') {
3286 Node
*TA
= getDerived().parseTemplateArgs();
3289 return make
<NameWithTemplateArgs
>(SN
, TA
);
3294 // <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3295 // ::= <simple-id> # e.g., ~A<2*N>
3296 template <typename Derived
, typename Alloc
>
3297 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseDestructorName() {
3299 if (std::isdigit(look()))
3300 Result
= getDerived().parseSimpleId();
3302 Result
= getDerived().parseUnresolvedType();
3303 if (Result
== nullptr)
3305 return make
<DtorName
>(Result
);
3308 // <unresolved-type> ::= <template-param>
3310 // ::= <substitution>
3311 template <typename Derived
, typename Alloc
>
3312 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnresolvedType() {
3313 if (look() == 'T') {
3314 Node
*TP
= getDerived().parseTemplateParam();
3320 if (look() == 'D') {
3321 Node
*DT
= getDerived().parseDecltype();
3327 return getDerived().parseSubstitution();
3330 // <base-unresolved-name> ::= <simple-id> # unresolved name
3331 // extension ::= <operator-name> # unresolved operator-function-id
3332 // extension ::= <operator-name> <template-args> # unresolved operator template-id
3333 // ::= on <operator-name> # unresolved operator-function-id
3334 // ::= on <operator-name> <template-args> # unresolved operator template-id
3335 // ::= dn <destructor-name> # destructor or pseudo-destructor;
3336 // # e.g. ~X or ~X<N-1>
3337 template <typename Derived
, typename Alloc
>
3338 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseBaseUnresolvedName() {
3339 if (std::isdigit(look()))
3340 return getDerived().parseSimpleId();
3342 if (consumeIf("dn"))
3343 return getDerived().parseDestructorName();
3347 Node
*Oper
= getDerived().parseOperatorName(/*NameState=*/nullptr);
3348 if (Oper
== nullptr)
3350 if (look() == 'I') {
3351 Node
*TA
= getDerived().parseTemplateArgs();
3354 return make
<NameWithTemplateArgs
>(Oper
, TA
);
3359 // <unresolved-name>
3360 // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3361 // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3362 // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3363 // # A::x, N::y, A<T>::z; "gs" means leading "::"
3364 // [gs] has been parsed by caller.
3365 // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3366 // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3367 // # T::N::x /decltype(p)::N::x
3368 // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3370 // <unresolved-qualifier-level> ::= <simple-id>
3371 template <typename Derived
, typename Alloc
>
3372 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnresolvedName(bool Global
) {
3373 Node
*SoFar
= nullptr;
3375 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3376 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3377 if (consumeIf("srN")) {
3378 SoFar
= getDerived().parseUnresolvedType();
3379 if (SoFar
== nullptr)
3382 if (look() == 'I') {
3383 Node
*TA
= getDerived().parseTemplateArgs();
3386 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3391 while (!consumeIf('E')) {
3392 Node
*Qual
= getDerived().parseSimpleId();
3393 if (Qual
== nullptr)
3395 SoFar
= make
<QualifiedName
>(SoFar
, Qual
);
3400 Node
*Base
= getDerived().parseBaseUnresolvedName();
3401 if (Base
== nullptr)
3403 return make
<QualifiedName
>(SoFar
, Base
);
3406 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3407 if (!consumeIf("sr")) {
3408 SoFar
= getDerived().parseBaseUnresolvedName();
3409 if (SoFar
== nullptr)
3412 SoFar
= make
<GlobalQualifiedName
>(SoFar
);
3416 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3417 if (std::isdigit(look())) {
3419 Node
*Qual
= getDerived().parseSimpleId();
3420 if (Qual
== nullptr)
3423 SoFar
= make
<QualifiedName
>(SoFar
, Qual
);
3425 SoFar
= make
<GlobalQualifiedName
>(Qual
);
3430 } while (!consumeIf('E'));
3432 // sr <unresolved-type> <base-unresolved-name>
3433 // sr <unresolved-type> <template-args> <base-unresolved-name>
3435 SoFar
= getDerived().parseUnresolvedType();
3436 if (SoFar
== nullptr)
3439 if (look() == 'I') {
3440 Node
*TA
= getDerived().parseTemplateArgs();
3443 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3449 assert(SoFar
!= nullptr);
3451 Node
*Base
= getDerived().parseBaseUnresolvedName();
3452 if (Base
== nullptr)
3454 return make
<QualifiedName
>(SoFar
, Base
);
3457 // <abi-tags> ::= <abi-tag> [<abi-tags>]
3458 // <abi-tag> ::= B <source-name>
3459 template <typename Derived
, typename Alloc
>
3460 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseAbiTags(Node
*N
) {
3461 while (consumeIf('B')) {
3462 std::string_view SN
= parseBareSourceName();
3465 N
= make
<AbiTagAttr
>(N
, SN
);
3472 // <number> ::= [n] <non-negative decimal integer>
3473 template <typename Alloc
, typename Derived
>
3475 AbstractManglingParser
<Alloc
, Derived
>::parseNumber(bool AllowNegative
) {
3476 const char *Tmp
= First
;
3479 if (numLeft() == 0 || !std::isdigit(*First
))
3480 return std::string_view();
3481 while (numLeft() != 0 && std::isdigit(*First
))
3483 return std::string_view(Tmp
, First
- Tmp
);
3486 // <positive length number> ::= [0-9]*
3487 template <typename Alloc
, typename Derived
>
3488 bool AbstractManglingParser
<Alloc
, Derived
>::parsePositiveInteger(size_t *Out
) {
3490 if (look() < '0' || look() > '9')
3492 while (look() >= '0' && look() <= '9') {
3494 *Out
+= static_cast<size_t>(consume() - '0');
3499 template <typename Alloc
, typename Derived
>
3500 std::string_view AbstractManglingParser
<Alloc
, Derived
>::parseBareSourceName() {
3502 if (parsePositiveInteger(&Int
) || numLeft() < Int
)
3504 std::string_view
R(First
, Int
);
3509 // <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3511 // <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3512 // ::= DO <expression> E # computed (instantiation-dependent) noexcept
3513 // ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3515 // <ref-qualifier> ::= R # & ref-qualifier
3516 // <ref-qualifier> ::= O # && ref-qualifier
3517 template <typename Derived
, typename Alloc
>
3518 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFunctionType() {
3519 Qualifiers CVQuals
= parseCVQualifiers();
3521 Node
*ExceptionSpec
= nullptr;
3522 if (consumeIf("Do")) {
3523 ExceptionSpec
= make
<NameType
>("noexcept");
3526 } else if (consumeIf("DO")) {
3527 Node
*E
= getDerived().parseExpr();
3528 if (E
== nullptr || !consumeIf('E'))
3530 ExceptionSpec
= make
<NoexceptSpec
>(E
);
3533 } else if (consumeIf("Dw")) {
3534 size_t SpecsBegin
= Names
.size();
3535 while (!consumeIf('E')) {
3536 Node
*T
= getDerived().parseType();
3542 make
<DynamicExceptionSpec
>(popTrailingNodeArray(SpecsBegin
));
3547 consumeIf("Dx"); // transaction safe
3549 if (!consumeIf('F'))
3551 consumeIf('Y'); // extern "C"
3552 Node
*ReturnType
= getDerived().parseType();
3553 if (ReturnType
== nullptr)
3556 FunctionRefQual ReferenceQualifier
= FrefQualNone
;
3557 size_t ParamsBegin
= Names
.size();
3563 if (consumeIf("RE")) {
3564 ReferenceQualifier
= FrefQualLValue
;
3567 if (consumeIf("OE")) {
3568 ReferenceQualifier
= FrefQualRValue
;
3571 Node
*T
= getDerived().parseType();
3577 NodeArray Params
= popTrailingNodeArray(ParamsBegin
);
3578 return make
<FunctionType
>(ReturnType
, Params
, CVQuals
,
3579 ReferenceQualifier
, ExceptionSpec
);
3583 // <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3584 // ::= Dv [<dimension expression>] _ <element type>
3585 // <extended element type> ::= <element type>
3586 // ::= p # AltiVec vector pixel
3587 template <typename Derived
, typename Alloc
>
3588 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseVectorType() {
3589 if (!consumeIf("Dv"))
3591 if (look() >= '1' && look() <= '9') {
3592 Node
*DimensionNumber
= make
<NameType
>(parseNumber());
3593 if (!DimensionNumber
)
3595 if (!consumeIf('_'))
3598 return make
<PixelVectorType
>(DimensionNumber
);
3599 Node
*ElemType
= getDerived().parseType();
3600 if (ElemType
== nullptr)
3602 return make
<VectorType
>(ElemType
, DimensionNumber
);
3605 if (!consumeIf('_')) {
3606 Node
*DimExpr
= getDerived().parseExpr();
3609 if (!consumeIf('_'))
3611 Node
*ElemType
= getDerived().parseType();
3614 return make
<VectorType
>(ElemType
, DimExpr
);
3616 Node
*ElemType
= getDerived().parseType();
3619 return make
<VectorType
>(ElemType
, /*Dimension=*/nullptr);
3622 // <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3623 // ::= DT <expression> E # decltype of an expression (C++0x)
3624 template <typename Derived
, typename Alloc
>
3625 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseDecltype() {
3626 if (!consumeIf('D'))
3628 if (!consumeIf('t') && !consumeIf('T'))
3630 Node
*E
= getDerived().parseExpr();
3633 if (!consumeIf('E'))
3635 return make
<EnclosingExpr
>("decltype", E
);
3638 // <array-type> ::= A <positive dimension number> _ <element type>
3639 // ::= A [<dimension expression>] _ <element type>
3640 template <typename Derived
, typename Alloc
>
3641 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseArrayType() {
3642 if (!consumeIf('A'))
3645 Node
*Dimension
= nullptr;
3647 if (std::isdigit(look())) {
3648 Dimension
= make
<NameType
>(parseNumber());
3651 if (!consumeIf('_'))
3653 } else if (!consumeIf('_')) {
3654 Node
*DimExpr
= getDerived().parseExpr();
3655 if (DimExpr
== nullptr)
3657 if (!consumeIf('_'))
3659 Dimension
= DimExpr
;
3662 Node
*Ty
= getDerived().parseType();
3665 return make
<ArrayType
>(Ty
, Dimension
);
3668 // <pointer-to-member-type> ::= M <class type> <member type>
3669 template <typename Derived
, typename Alloc
>
3670 Node
*AbstractManglingParser
<Derived
, Alloc
>::parsePointerToMemberType() {
3671 if (!consumeIf('M'))
3673 Node
*ClassType
= getDerived().parseType();
3674 if (ClassType
== nullptr)
3676 Node
*MemberType
= getDerived().parseType();
3677 if (MemberType
== nullptr)
3679 return make
<PointerToMemberType
>(ClassType
, MemberType
);
3682 // <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3683 // ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3684 // ::= Tu <name> # dependent elaborated type specifier using 'union'
3685 // ::= Te <name> # dependent elaborated type specifier using 'enum'
3686 template <typename Derived
, typename Alloc
>
3687 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseClassEnumType() {
3688 std::string_view ElabSpef
;
3689 if (consumeIf("Ts"))
3690 ElabSpef
= "struct";
3691 else if (consumeIf("Tu"))
3693 else if (consumeIf("Te"))
3696 Node
*Name
= getDerived().parseName();
3697 if (Name
== nullptr)
3700 if (!ElabSpef
.empty())
3701 return make
<ElaboratedTypeSpefType
>(ElabSpef
, Name
);
3706 // <qualified-type> ::= <qualifiers> <type>
3707 // <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3708 // <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
3709 template <typename Derived
, typename Alloc
>
3710 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseQualifiedType() {
3711 if (consumeIf('U')) {
3712 std::string_view Qual
= parseBareSourceName();
3716 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3717 if (starts_with(Qual
, "objcproto")) {
3718 constexpr size_t Len
= sizeof("objcproto") - 1;
3719 std::string_view
ProtoSourceName(Qual
.data() + Len
, Qual
.size() - Len
);
3720 std::string_view Proto
;
3722 ScopedOverride
<const char *> SaveFirst(First
, ProtoSourceName
.data()),
3723 SaveLast(Last
, &*ProtoSourceName
.rbegin() + 1);
3724 Proto
= parseBareSourceName();
3728 Node
*Child
= getDerived().parseQualifiedType();
3729 if (Child
== nullptr)
3731 return make
<ObjCProtoName
>(Child
, Proto
);
3735 if (look() == 'I') {
3736 TA
= getDerived().parseTemplateArgs();
3741 Node
*Child
= getDerived().parseQualifiedType();
3742 if (Child
== nullptr)
3744 return make
<VendorExtQualType
>(Child
, Qual
, TA
);
3747 Qualifiers Quals
= parseCVQualifiers();
3748 Node
*Ty
= getDerived().parseType();
3751 if (Quals
!= QualNone
)
3752 Ty
= make
<QualType
>(Ty
, Quals
);
3756 // <type> ::= <builtin-type>
3757 // ::= <qualified-type>
3758 // ::= <function-type>
3759 // ::= <class-enum-type>
3761 // ::= <pointer-to-member-type>
3762 // ::= <template-param>
3763 // ::= <template-template-param> <template-args>
3765 // ::= P <type> # pointer
3766 // ::= R <type> # l-value reference
3767 // ::= O <type> # r-value reference (C++11)
3768 // ::= C <type> # complex pair (C99)
3769 // ::= G <type> # imaginary (C99)
3770 // ::= <substitution> # See Compression below
3771 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3772 // extension ::= <vector-type> # <vector-type> starts with Dv
3774 // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3775 // <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
3776 template <typename Derived
, typename Alloc
>
3777 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseType() {
3778 Node
*Result
= nullptr;
3781 // ::= <qualified-type>
3785 unsigned AfterQuals
= 0;
3786 if (look(AfterQuals
) == 'r') ++AfterQuals
;
3787 if (look(AfterQuals
) == 'V') ++AfterQuals
;
3788 if (look(AfterQuals
) == 'K') ++AfterQuals
;
3790 if (look(AfterQuals
) == 'F' ||
3791 (look(AfterQuals
) == 'D' &&
3792 (look(AfterQuals
+ 1) == 'o' || look(AfterQuals
+ 1) == 'O' ||
3793 look(AfterQuals
+ 1) == 'w' || look(AfterQuals
+ 1) == 'x'))) {
3794 Result
= getDerived().parseFunctionType();
3797 DEMANGLE_FALLTHROUGH
;
3800 Result
= getDerived().parseQualifiedType();
3803 // <builtin-type> ::= v # void
3806 return make
<NameType
>("void");
3810 return make
<NameType
>("wchar_t");
3814 return make
<NameType
>("bool");
3818 return make
<NameType
>("char");
3819 // ::= a # signed char
3822 return make
<NameType
>("signed char");
3823 // ::= h # unsigned char
3826 return make
<NameType
>("unsigned char");
3830 return make
<NameType
>("short");
3831 // ::= t # unsigned short
3834 return make
<NameType
>("unsigned short");
3838 return make
<NameType
>("int");
3839 // ::= j # unsigned int
3842 return make
<NameType
>("unsigned int");
3846 return make
<NameType
>("long");
3847 // ::= m # unsigned long
3850 return make
<NameType
>("unsigned long");
3851 // ::= x # long long, __int64
3854 return make
<NameType
>("long long");
3855 // ::= y # unsigned long long, __int64
3858 return make
<NameType
>("unsigned long long");
3862 return make
<NameType
>("__int128");
3863 // ::= o # unsigned __int128
3866 return make
<NameType
>("unsigned __int128");
3870 return make
<NameType
>("float");
3874 return make
<NameType
>("double");
3875 // ::= e # long double, __float80
3878 return make
<NameType
>("long double");
3879 // ::= g # __float128
3882 return make
<NameType
>("__float128");
3886 return make
<NameType
>("...");
3888 // <builtin-type> ::= u <source-name> # vendor extended type
3891 std::string_view Res
= parseBareSourceName();
3894 // Typically, <builtin-type>s are not considered substitution candidates,
3895 // but the exception to that exception is vendor extended types (Itanium C++
3897 Result
= make
<NameType
>(Res
);
3902 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3905 return make
<NameType
>("decimal64");
3906 // ::= De # IEEE 754r decimal floating point (128 bits)
3909 return make
<NameType
>("decimal128");
3910 // ::= Df # IEEE 754r decimal floating point (32 bits)
3913 return make
<NameType
>("decimal32");
3914 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3917 return make
<NameType
>("half");
3918 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3921 Node
*DimensionNumber
= make
<NameType
>(parseNumber());
3922 if (!DimensionNumber
)
3924 if (!consumeIf('_'))
3926 return make
<BinaryFPType
>(DimensionNumber
);
3928 // ::= DB <number> _ # C23 signed _BitInt(N)
3929 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
3930 // ::= DU <number> _ # C23 unsigned _BitInt(N)
3931 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
3934 bool Signed
= look(1) == 'B';
3936 Node
*Size
= std::isdigit(look()) ? make
<NameType
>(parseNumber())
3937 : getDerived().parseExpr();
3940 if (!consumeIf('_'))
3942 return make
<BitIntType
>(Size
, Signed
);
3944 // ::= Di # char32_t
3947 return make
<NameType
>("char32_t");
3948 // ::= Ds # char16_t
3951 return make
<NameType
>("char16_t");
3952 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3955 return make
<NameType
>("char8_t");
3956 // ::= Da # auto (in dependent new-expressions)
3959 return make
<NameType
>("auto");
3960 // ::= Dc # decltype(auto)
3963 return make
<NameType
>("decltype(auto)");
3964 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3967 return make
<NameType
>("std::nullptr_t");
3972 Result
= getDerived().parseDecltype();
3975 // extension ::= <vector-type> # <vector-type> starts with Dv
3977 Result
= getDerived().parseVectorType();
3980 // ::= Dp <type> # pack expansion (C++0x)
3983 Node
*Child
= getDerived().parseType();
3986 Result
= make
<ParameterPackExpansion
>(Child
);
3989 // Exception specifier on a function type.
3993 // Transaction safe function type.
3995 Result
= getDerived().parseFunctionType();
3999 // ::= <function-type>
4001 Result
= getDerived().parseFunctionType();
4006 Result
= getDerived().parseArrayType();
4009 // ::= <pointer-to-member-type>
4011 Result
= getDerived().parsePointerToMemberType();
4014 // ::= <template-param>
4016 // This could be an elaborate type specifier on a <class-enum-type>.
4017 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
4018 Result
= getDerived().parseClassEnumType();
4022 Result
= getDerived().parseTemplateParam();
4023 if (Result
== nullptr)
4026 // Result could be either of:
4027 // <type> ::= <template-param>
4028 // <type> ::= <template-template-param> <template-args>
4030 // <template-template-param> ::= <template-param>
4031 // ::= <substitution>
4033 // If this is followed by some <template-args>, and we're permitted to
4034 // parse them, take the second production.
4036 if (TryToParseTemplateArgs
&& look() == 'I') {
4037 Node
*TA
= getDerived().parseTemplateArgs();
4040 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
4044 // ::= P <type> # pointer
4047 Node
*Ptr
= getDerived().parseType();
4050 Result
= make
<PointerType
>(Ptr
);
4053 // ::= R <type> # l-value reference
4056 Node
*Ref
= getDerived().parseType();
4059 Result
= make
<ReferenceType
>(Ref
, ReferenceKind::LValue
);
4062 // ::= O <type> # r-value reference (C++11)
4065 Node
*Ref
= getDerived().parseType();
4068 Result
= make
<ReferenceType
>(Ref
, ReferenceKind::RValue
);
4071 // ::= C <type> # complex pair (C99)
4074 Node
*P
= getDerived().parseType();
4077 Result
= make
<PostfixQualifiedType
>(P
, " complex");
4080 // ::= G <type> # imaginary (C99)
4083 Node
*P
= getDerived().parseType();
4086 Result
= make
<PostfixQualifiedType
>(P
, " imaginary");
4089 // ::= <substitution> # See Compression below
4091 if (look(1) != 't') {
4092 bool IsSubst
= false;
4093 Result
= getDerived().parseUnscopedName(nullptr, &IsSubst
);
4097 // Sub could be either of:
4098 // <type> ::= <substitution>
4099 // <type> ::= <template-template-param> <template-args>
4101 // <template-template-param> ::= <template-param>
4102 // ::= <substitution>
4104 // If this is followed by some <template-args>, and we're permitted to
4105 // parse them, take the second production.
4107 if (look() == 'I' && (!IsSubst
|| TryToParseTemplateArgs
)) {
4109 Subs
.push_back(Result
);
4110 Node
*TA
= getDerived().parseTemplateArgs();
4113 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
4114 } else if (IsSubst
) {
4115 // If all we parsed was a substitution, don't re-insert into the
4116 // substitution table.
4121 DEMANGLE_FALLTHROUGH
;
4123 // ::= <class-enum-type>
4125 Result
= getDerived().parseClassEnumType();
4130 // If we parsed a type, insert it into the substitution table. Note that all
4131 // <builtin-type>s and <substitution>s have already bailed out, because they
4132 // don't get substitutions.
4133 if (Result
!= nullptr)
4134 Subs
.push_back(Result
);
4138 template <typename Derived
, typename Alloc
>
4140 AbstractManglingParser
<Derived
, Alloc
>::parsePrefixExpr(std::string_view Kind
,
4142 Node
*E
= getDerived().parseExpr();
4145 return make
<PrefixExpr
>(Kind
, E
, Prec
);
4148 template <typename Derived
, typename Alloc
>
4150 AbstractManglingParser
<Derived
, Alloc
>::parseBinaryExpr(std::string_view Kind
,
4152 Node
*LHS
= getDerived().parseExpr();
4155 Node
*RHS
= getDerived().parseExpr();
4158 return make
<BinaryExpr
>(LHS
, Kind
, RHS
, Prec
);
4161 template <typename Derived
, typename Alloc
>
4162 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseIntegerLiteral(
4163 std::string_view Lit
) {
4164 std::string_view Tmp
= parseNumber(true);
4165 if (!Tmp
.empty() && consumeIf('E'))
4166 return make
<IntegerLiteral
>(Lit
, Tmp
);
4170 // <CV-Qualifiers> ::= [r] [V] [K]
4171 template <typename Alloc
, typename Derived
>
4172 Qualifiers AbstractManglingParser
<Alloc
, Derived
>::parseCVQualifiers() {
4173 Qualifiers CVR
= QualNone
;
4175 CVR
|= QualRestrict
;
4177 CVR
|= QualVolatile
;
4183 // <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4184 // ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4185 // ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4186 // ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
4187 // ::= fpT # 'this' expression (not part of standard?)
4188 template <typename Derived
, typename Alloc
>
4189 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFunctionParam() {
4190 if (consumeIf("fpT"))
4191 return make
<NameType
>("this");
4192 if (consumeIf("fp")) {
4193 parseCVQualifiers();
4194 std::string_view Num
= parseNumber();
4195 if (!consumeIf('_'))
4197 return make
<FunctionParam
>(Num
);
4199 if (consumeIf("fL")) {
4200 if (parseNumber().empty())
4202 if (!consumeIf('p'))
4204 parseCVQualifiers();
4205 std::string_view Num
= parseNumber();
4206 if (!consumeIf('_'))
4208 return make
<FunctionParam
>(Num
);
4213 // cv <type> <expression> # conversion with one argument
4214 // cv <type> _ <expression>* E # conversion with a different number of arguments
4215 template <typename Derived
, typename Alloc
>
4216 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseConversionExpr() {
4217 if (!consumeIf("cv"))
4221 ScopedOverride
<bool> SaveTemp(TryToParseTemplateArgs
, false);
4222 Ty
= getDerived().parseType();
4228 if (consumeIf('_')) {
4229 size_t ExprsBegin
= Names
.size();
4230 while (!consumeIf('E')) {
4231 Node
*E
= getDerived().parseExpr();
4236 NodeArray Exprs
= popTrailingNodeArray(ExprsBegin
);
4237 return make
<ConversionExpr
>(Ty
, Exprs
);
4240 Node
*E
[1] = {getDerived().parseExpr()};
4241 if (E
[0] == nullptr)
4243 return make
<ConversionExpr
>(Ty
, makeNodeArray(E
, E
+ 1));
4246 // <expr-primary> ::= L <type> <value number> E # integer literal
4247 // ::= L <type> <value float> E # floating literal
4248 // ::= L <string type> E # string literal
4249 // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
4250 // ::= L <lambda type> E # lambda expression
4251 // FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4252 // ::= L <mangled-name> E # external name
4253 template <typename Derived
, typename Alloc
>
4254 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseExprPrimary() {
4255 if (!consumeIf('L'))
4260 return getDerived().parseIntegerLiteral("wchar_t");
4262 if (consumeIf("b0E"))
4263 return make
<BoolExpr
>(0);
4264 if (consumeIf("b1E"))
4265 return make
<BoolExpr
>(1);
4269 return getDerived().parseIntegerLiteral("char");
4272 return getDerived().parseIntegerLiteral("signed char");
4275 return getDerived().parseIntegerLiteral("unsigned char");
4278 return getDerived().parseIntegerLiteral("short");
4281 return getDerived().parseIntegerLiteral("unsigned short");
4284 return getDerived().parseIntegerLiteral("");
4287 return getDerived().parseIntegerLiteral("u");
4290 return getDerived().parseIntegerLiteral("l");
4293 return getDerived().parseIntegerLiteral("ul");
4296 return getDerived().parseIntegerLiteral("ll");
4299 return getDerived().parseIntegerLiteral("ull");
4302 return getDerived().parseIntegerLiteral("__int128");
4305 return getDerived().parseIntegerLiteral("unsigned __int128");
4308 return getDerived().template parseFloatingLiteral
<float>();
4311 return getDerived().template parseFloatingLiteral
<double>();
4314 #if defined(__powerpc__) || defined(__s390__)
4315 // Handle cases where long doubles encoded with e have the same size
4316 // and representation as doubles.
4317 return getDerived().template parseFloatingLiteral
<double>();
4319 return getDerived().template parseFloatingLiteral
<long double>();
4322 if (consumeIf("_Z")) {
4323 Node
*R
= getDerived().parseEncoding();
4324 if (R
!= nullptr && consumeIf('E'))
4329 Node
*T
= getDerived().parseType();
4332 // FIXME: We need to include the string contents in the mangling.
4334 return make
<StringLiteral
>(T
);
4338 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
4339 return make
<NameType
>("nullptr");
4342 // Invalid mangled name per
4343 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4346 // FIXME: Should we support LUb... for block literals?
4349 Node
*T
= parseUnnamedTypeName(nullptr);
4350 if (!T
|| !consumeIf('E'))
4352 return make
<LambdaExpr
>(T
);
4355 // might be named type
4356 Node
*T
= getDerived().parseType();
4359 std::string_view N
= parseNumber(/*AllowNegative=*/true);
4362 if (!consumeIf('E'))
4364 return make
<EnumLiteral
>(T
, N
);
4369 // <braced-expression> ::= <expression>
4370 // ::= di <field source-name> <braced-expression> # .name = expr
4371 // ::= dx <index expression> <braced-expression> # [expr] = expr
4372 // ::= dX <range begin expression> <range end expression> <braced-expression>
4373 template <typename Derived
, typename Alloc
>
4374 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseBracedExpr() {
4375 if (look() == 'd') {
4379 Node
*Field
= getDerived().parseSourceName(/*NameState=*/nullptr);
4380 if (Field
== nullptr)
4382 Node
*Init
= getDerived().parseBracedExpr();
4383 if (Init
== nullptr)
4385 return make
<BracedExpr
>(Field
, Init
, /*isArray=*/false);
4389 Node
*Index
= getDerived().parseExpr();
4390 if (Index
== nullptr)
4392 Node
*Init
= getDerived().parseBracedExpr();
4393 if (Init
== nullptr)
4395 return make
<BracedExpr
>(Index
, Init
, /*isArray=*/true);
4399 Node
*RangeBegin
= getDerived().parseExpr();
4400 if (RangeBegin
== nullptr)
4402 Node
*RangeEnd
= getDerived().parseExpr();
4403 if (RangeEnd
== nullptr)
4405 Node
*Init
= getDerived().parseBracedExpr();
4406 if (Init
== nullptr)
4408 return make
<BracedRangeExpr
>(RangeBegin
, RangeEnd
, Init
);
4412 return getDerived().parseExpr();
4415 // (not yet in the spec)
4416 // <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4417 // ::= fR <binary-operator-name> <expression> <expression>
4418 // ::= fl <binary-operator-name> <expression>
4419 // ::= fr <binary-operator-name> <expression>
4420 template <typename Derived
, typename Alloc
>
4421 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFoldExpr() {
4422 if (!consumeIf('f'))
4425 bool IsLeftFold
= false, HasInitializer
= false;
4431 HasInitializer
= true;
4434 HasInitializer
= true;
4444 const auto *Op
= parseOperatorEncoding();
4447 if (!(Op
->getKind() == OperatorInfo::Binary
4448 || (Op
->getKind() == OperatorInfo::Member
4449 && Op
->getName().back() == '*')))
4452 Node
*Pack
= getDerived().parseExpr();
4453 if (Pack
== nullptr)
4456 Node
*Init
= nullptr;
4457 if (HasInitializer
) {
4458 Init
= getDerived().parseExpr();
4459 if (Init
== nullptr)
4463 if (IsLeftFold
&& Init
)
4464 std::swap(Pack
, Init
);
4466 return make
<FoldExpr
>(IsLeftFold
, Op
->getSymbol(), Pack
, Init
);
4469 // <expression> ::= mc <parameter type> <expr> [<offset number>] E
4471 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4472 template <typename Derived
, typename Alloc
>
4474 AbstractManglingParser
<Derived
, Alloc
>::parsePointerToMemberConversionExpr(
4476 Node
*Ty
= getDerived().parseType();
4479 Node
*Expr
= getDerived().parseExpr();
4482 std::string_view Offset
= getDerived().parseNumber(true);
4483 if (!consumeIf('E'))
4485 return make
<PointerToMemberConversionExpr
>(Ty
, Expr
, Offset
, Prec
);
4488 // <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4489 // <union-selector> ::= _ [<number>]
4491 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4492 template <typename Derived
, typename Alloc
>
4493 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSubobjectExpr() {
4494 Node
*Ty
= getDerived().parseType();
4497 Node
*Expr
= getDerived().parseExpr();
4500 std::string_view Offset
= getDerived().parseNumber(true);
4501 size_t SelectorsBegin
= Names
.size();
4502 while (consumeIf('_')) {
4503 Node
*Selector
= make
<NameType
>(parseNumber());
4506 Names
.push_back(Selector
);
4508 bool OnePastTheEnd
= consumeIf('p');
4509 if (!consumeIf('E'))
4511 return make
<SubobjectExpr
>(
4512 Ty
, Expr
, Offset
, popTrailingNodeArray(SelectorsBegin
), OnePastTheEnd
);
4515 // <expression> ::= <unary operator-name> <expression>
4516 // ::= <binary operator-name> <expression> <expression>
4517 // ::= <ternary operator-name> <expression> <expression> <expression>
4518 // ::= cl <expression>+ E # call
4519 // ::= cv <type> <expression> # conversion with one argument
4520 // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4521 // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4522 // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4523 // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4524 // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4525 // ::= [gs] dl <expression> # delete expression
4526 // ::= [gs] da <expression> # delete[] expression
4527 // ::= pp_ <expression> # prefix ++
4528 // ::= mm_ <expression> # prefix --
4529 // ::= ti <type> # typeid (type)
4530 // ::= te <expression> # typeid (expression)
4531 // ::= dc <type> <expression> # dynamic_cast<type> (expression)
4532 // ::= sc <type> <expression> # static_cast<type> (expression)
4533 // ::= cc <type> <expression> # const_cast<type> (expression)
4534 // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4535 // ::= st <type> # sizeof (a type)
4536 // ::= sz <expression> # sizeof (an expression)
4537 // ::= at <type> # alignof (a type)
4538 // ::= az <expression> # alignof (an expression)
4539 // ::= nx <expression> # noexcept (expression)
4540 // ::= <template-param>
4541 // ::= <function-param>
4542 // ::= dt <expression> <unresolved-name> # expr.name
4543 // ::= pt <expression> <unresolved-name> # expr->name
4544 // ::= ds <expression> <expression> # expr.*expr
4545 // ::= sZ <template-param> # size of a parameter pack
4546 // ::= sZ <function-param> # size of a function parameter pack
4547 // ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4548 // ::= sp <expression> # pack expansion
4549 // ::= tw <expression> # throw expression
4550 // ::= tr # throw with no operand (rethrow)
4551 // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4552 // # freestanding dependent name (e.g., T::x),
4553 // # objectless nonstatic member reference
4554 // ::= fL <binary-operator-name> <expression> <expression>
4555 // ::= fR <binary-operator-name> <expression> <expression>
4556 // ::= fl <binary-operator-name> <expression>
4557 // ::= fr <binary-operator-name> <expression>
4558 // ::= <expr-primary>
4559 template <typename Derived
, typename Alloc
>
4560 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseExpr() {
4561 bool Global
= consumeIf("gs");
4563 const auto *Op
= parseOperatorEncoding();
4565 auto Sym
= Op
->getSymbol();
4566 switch (Op
->getKind()) {
4567 case OperatorInfo::Binary
:
4568 // Binary operator: lhs @ rhs
4569 return getDerived().parseBinaryExpr(Sym
, Op
->getPrecedence());
4570 case OperatorInfo::Prefix
:
4571 // Prefix unary operator: @ expr
4572 return getDerived().parsePrefixExpr(Sym
, Op
->getPrecedence());
4573 case OperatorInfo::Postfix
: {
4574 // Postfix unary operator: expr @
4576 return getDerived().parsePrefixExpr(Sym
, Op
->getPrecedence());
4577 Node
*Ex
= getDerived().parseExpr();
4580 return make
<PostfixExpr
>(Ex
, Sym
, Op
->getPrecedence());
4582 case OperatorInfo::Array
: {
4583 // Array Index: lhs [ rhs ]
4584 Node
*Base
= getDerived().parseExpr();
4585 if (Base
== nullptr)
4587 Node
*Index
= getDerived().parseExpr();
4588 if (Index
== nullptr)
4590 return make
<ArraySubscriptExpr
>(Base
, Index
, Op
->getPrecedence());
4592 case OperatorInfo::Member
: {
4593 // Member access lhs @ rhs
4594 Node
*LHS
= getDerived().parseExpr();
4597 Node
*RHS
= getDerived().parseExpr();
4600 return make
<MemberExpr
>(LHS
, Sym
, RHS
, Op
->getPrecedence());
4602 case OperatorInfo::New
: {
4604 // # new (expr-list) type [(init)]
4605 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4606 // # new[] (expr-list) type [(init)]
4607 // [gs] na <expression>* _ <type> [pi <expression>*] E
4608 size_t Exprs
= Names
.size();
4609 while (!consumeIf('_')) {
4610 Node
*Ex
= getDerived().parseExpr();
4613 Names
.push_back(Ex
);
4615 NodeArray ExprList
= popTrailingNodeArray(Exprs
);
4616 Node
*Ty
= getDerived().parseType();
4619 bool HaveInits
= consumeIf("pi");
4620 size_t InitsBegin
= Names
.size();
4621 while (!consumeIf('E')) {
4624 Node
*Init
= getDerived().parseExpr();
4625 if (Init
== nullptr)
4627 Names
.push_back(Init
);
4629 NodeArray Inits
= popTrailingNodeArray(InitsBegin
);
4630 return make
<NewExpr
>(ExprList
, Ty
, Inits
, Global
,
4631 /*IsArray=*/Op
->getFlag(), Op
->getPrecedence());
4633 case OperatorInfo::Del
: {
4635 Node
*Ex
= getDerived().parseExpr();
4638 return make
<DeleteExpr
>(Ex
, Global
, /*IsArray=*/Op
->getFlag(),
4639 Op
->getPrecedence());
4641 case OperatorInfo::Call
: {
4643 Node
*Callee
= getDerived().parseExpr();
4644 if (Callee
== nullptr)
4646 size_t ExprsBegin
= Names
.size();
4647 while (!consumeIf('E')) {
4648 Node
*E
= getDerived().parseExpr();
4653 return make
<CallExpr
>(Callee
, popTrailingNodeArray(ExprsBegin
),
4654 Op
->getPrecedence());
4656 case OperatorInfo::CCast
: {
4657 // C Cast: (type)expr
4660 ScopedOverride
<bool> SaveTemp(TryToParseTemplateArgs
, false);
4661 Ty
= getDerived().parseType();
4666 size_t ExprsBegin
= Names
.size();
4667 bool IsMany
= consumeIf('_');
4668 while (!consumeIf('E')) {
4669 Node
*E
= getDerived().parseExpr();
4676 NodeArray Exprs
= popTrailingNodeArray(ExprsBegin
);
4677 if (!IsMany
&& Exprs
.size() != 1)
4679 return make
<ConversionExpr
>(Ty
, Exprs
, Op
->getPrecedence());
4681 case OperatorInfo::Conditional
: {
4682 // Conditional operator: expr ? expr : expr
4683 Node
*Cond
= getDerived().parseExpr();
4684 if (Cond
== nullptr)
4686 Node
*LHS
= getDerived().parseExpr();
4689 Node
*RHS
= getDerived().parseExpr();
4692 return make
<ConditionalExpr
>(Cond
, LHS
, RHS
, Op
->getPrecedence());
4694 case OperatorInfo::NamedCast
: {
4695 // Named cast operation, @<type>(expr)
4696 Node
*Ty
= getDerived().parseType();
4699 Node
*Ex
= getDerived().parseExpr();
4702 return make
<CastExpr
>(Sym
, Ty
, Ex
, Op
->getPrecedence());
4704 case OperatorInfo::OfIdOp
: {
4705 // [sizeof/alignof/typeid] ( <type>|<expr> )
4707 Op
->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4710 return make
<EnclosingExpr
>(Sym
, Arg
, Op
->getPrecedence());
4712 case OperatorInfo::NameOnly
: {
4713 // Not valid as an expression operand.
4717 DEMANGLE_UNREACHABLE
;
4724 return getDerived().parseExprPrimary();
4726 return getDerived().parseTemplateParam();
4727 if (look() == 'f') {
4728 // Disambiguate a fold expression from a <function-param>.
4729 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4730 return getDerived().parseFunctionParam();
4731 return getDerived().parseFoldExpr();
4733 if (consumeIf("il")) {
4734 size_t InitsBegin
= Names
.size();
4735 while (!consumeIf('E')) {
4736 Node
*E
= getDerived().parseBracedExpr();
4741 return make
<InitListExpr
>(nullptr, popTrailingNodeArray(InitsBegin
));
4743 if (consumeIf("mc"))
4744 return parsePointerToMemberConversionExpr(Node::Prec::Unary
);
4745 if (consumeIf("nx")) {
4746 Node
*Ex
= getDerived().parseExpr();
4749 return make
<EnclosingExpr
>("noexcept ", Ex
, Node::Prec::Unary
);
4751 if (consumeIf("so"))
4752 return parseSubobjectExpr();
4753 if (consumeIf("sp")) {
4754 Node
*Child
= getDerived().parseExpr();
4755 if (Child
== nullptr)
4757 return make
<ParameterPackExpansion
>(Child
);
4759 if (consumeIf("sZ")) {
4760 if (look() == 'T') {
4761 Node
*R
= getDerived().parseTemplateParam();
4764 return make
<SizeofParamPackExpr
>(R
);
4766 Node
*FP
= getDerived().parseFunctionParam();
4769 return make
<EnclosingExpr
>("sizeof... ", FP
);
4771 if (consumeIf("sP")) {
4772 size_t ArgsBegin
= Names
.size();
4773 while (!consumeIf('E')) {
4774 Node
*Arg
= getDerived().parseTemplateArg();
4777 Names
.push_back(Arg
);
4779 auto *Pack
= make
<NodeArrayNode
>(popTrailingNodeArray(ArgsBegin
));
4782 return make
<EnclosingExpr
>("sizeof... ", Pack
);
4784 if (consumeIf("tl")) {
4785 Node
*Ty
= getDerived().parseType();
4788 size_t InitsBegin
= Names
.size();
4789 while (!consumeIf('E')) {
4790 Node
*E
= getDerived().parseBracedExpr();
4795 return make
<InitListExpr
>(Ty
, popTrailingNodeArray(InitsBegin
));
4797 if (consumeIf("tr"))
4798 return make
<NameType
>("throw");
4799 if (consumeIf("tw")) {
4800 Node
*Ex
= getDerived().parseExpr();
4803 return make
<ThrowExpr
>(Ex
);
4805 if (consumeIf('u')) {
4806 Node
*Name
= getDerived().parseSourceName(/*NameState=*/nullptr);
4809 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4810 // standard encoding expects a <template-arg>, and would be otherwise be
4811 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4812 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4813 // actual conflict here.
4814 bool IsUUID
= false;
4815 Node
*UUID
= nullptr;
4816 if (Name
->getBaseName() == "__uuidof") {
4817 if (consumeIf('t')) {
4818 UUID
= getDerived().parseType();
4820 } else if (consumeIf('z')) {
4821 UUID
= getDerived().parseExpr();
4825 size_t ExprsBegin
= Names
.size();
4827 if (UUID
== nullptr)
4829 Names
.push_back(UUID
);
4831 while (!consumeIf('E')) {
4832 Node
*E
= getDerived().parseTemplateArg();
4838 return make
<CallExpr
>(Name
, popTrailingNodeArray(ExprsBegin
),
4839 Node::Prec::Postfix
);
4842 // Only unresolved names remain.
4843 return getDerived().parseUnresolvedName(Global
);
4846 // <call-offset> ::= h <nv-offset> _
4847 // ::= v <v-offset> _
4849 // <nv-offset> ::= <offset number>
4850 // # non-virtual base override
4852 // <v-offset> ::= <offset number> _ <virtual offset number>
4853 // # virtual base override, with vcall offset
4854 template <typename Alloc
, typename Derived
>
4855 bool AbstractManglingParser
<Alloc
, Derived
>::parseCallOffset() {
4856 // Just scan through the call offset, we never add this information into the
4859 return parseNumber(true).empty() || !consumeIf('_');
4861 return parseNumber(true).empty() || !consumeIf('_') ||
4862 parseNumber(true).empty() || !consumeIf('_');
4866 // <special-name> ::= TV <type> # virtual table
4867 // ::= TT <type> # VTT structure (construction vtable index)
4868 // ::= TI <type> # typeinfo structure
4869 // ::= TS <type> # typeinfo name (null-terminated byte string)
4870 // ::= Tc <call-offset> <call-offset> <base encoding>
4871 // # base is the nominal target function of thunk
4872 // # first call-offset is 'this' adjustment
4873 // # second call-offset is result adjustment
4874 // ::= T <call-offset> <base encoding>
4875 // # base is the nominal target function of thunk
4876 // # Guard variable for one-time initialization
4877 // ::= GV <object name>
4879 // ::= TW <object name> # Thread-local wrapper
4880 // ::= TH <object name> # Thread-local initialization
4881 // ::= GR <object name> _ # First temporary
4882 // ::= GR <object name> <seq-id> _ # Subsequent temporaries
4883 // # construction vtable for second-in-first
4884 // extension ::= TC <first type> <number> _ <second type>
4885 // extension ::= GR <object name> # reference temporary for object
4886 // extension ::= GI <module name> # module global initializer
4887 template <typename Derived
, typename Alloc
>
4888 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSpecialName() {
4892 // TA <template-arg> # template parameter object
4894 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4897 Node
*Arg
= getDerived().parseTemplateArg();
4900 return make
<SpecialName
>("template parameter object for ", Arg
);
4902 // TV <type> # virtual table
4905 Node
*Ty
= getDerived().parseType();
4908 return make
<SpecialName
>("vtable for ", Ty
);
4910 // TT <type> # VTT structure (construction vtable index)
4913 Node
*Ty
= getDerived().parseType();
4916 return make
<SpecialName
>("VTT for ", Ty
);
4918 // TI <type> # typeinfo structure
4921 Node
*Ty
= getDerived().parseType();
4924 return make
<SpecialName
>("typeinfo for ", Ty
);
4926 // TS <type> # typeinfo name (null-terminated byte string)
4929 Node
*Ty
= getDerived().parseType();
4932 return make
<SpecialName
>("typeinfo name for ", Ty
);
4934 // Tc <call-offset> <call-offset> <base encoding>
4937 if (parseCallOffset() || parseCallOffset())
4939 Node
*Encoding
= getDerived().parseEncoding();
4940 if (Encoding
== nullptr)
4942 return make
<SpecialName
>("covariant return thunk to ", Encoding
);
4944 // extension ::= TC <first type> <number> _ <second type>
4945 // # construction vtable for second-in-first
4948 Node
*FirstType
= getDerived().parseType();
4949 if (FirstType
== nullptr)
4951 if (parseNumber(true).empty() || !consumeIf('_'))
4953 Node
*SecondType
= getDerived().parseType();
4954 if (SecondType
== nullptr)
4956 return make
<CtorVtableSpecialName
>(SecondType
, FirstType
);
4958 // TW <object name> # Thread-local wrapper
4961 Node
*Name
= getDerived().parseName();
4962 if (Name
== nullptr)
4964 return make
<SpecialName
>("thread-local wrapper routine for ", Name
);
4966 // TH <object name> # Thread-local initialization
4969 Node
*Name
= getDerived().parseName();
4970 if (Name
== nullptr)
4972 return make
<SpecialName
>("thread-local initialization routine for ", Name
);
4974 // T <call-offset> <base encoding>
4977 bool IsVirt
= look() == 'v';
4978 if (parseCallOffset())
4980 Node
*BaseEncoding
= getDerived().parseEncoding();
4981 if (BaseEncoding
== nullptr)
4984 return make
<SpecialName
>("virtual thunk to ", BaseEncoding
);
4986 return make
<SpecialName
>("non-virtual thunk to ", BaseEncoding
);
4991 // GV <object name> # Guard variable for one-time initialization
4994 Node
*Name
= getDerived().parseName();
4995 if (Name
== nullptr)
4997 return make
<SpecialName
>("guard variable for ", Name
);
4999 // GR <object name> # reference temporary for object
5000 // GR <object name> _ # First temporary
5001 // GR <object name> <seq-id> _ # Subsequent temporaries
5004 Node
*Name
= getDerived().parseName();
5005 if (Name
== nullptr)
5008 bool ParsedSeqId
= !parseSeqId(&Count
);
5009 if (!consumeIf('_') && ParsedSeqId
)
5011 return make
<SpecialName
>("reference temporary for ", Name
);
5013 // GI <module-name> v
5016 ModuleName
*Module
= nullptr;
5017 if (getDerived().parseModuleNameOpt(Module
))
5019 if (Module
== nullptr)
5021 return make
<SpecialName
>("initializer for module ", Module
);
5028 // <encoding> ::= <function name> <bare-function-type>
5030 // ::= <special-name>
5031 template <typename Derived
, typename Alloc
>
5032 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseEncoding() {
5033 // The template parameters of an encoding are unrelated to those of the
5034 // enclosing context.
5035 class SaveTemplateParams
{
5036 AbstractManglingParser
*Parser
;
5037 decltype(TemplateParams
) OldParams
;
5038 decltype(OuterTemplateParams
) OldOuterParams
;
5041 SaveTemplateParams(AbstractManglingParser
*TheParser
) : Parser(TheParser
) {
5042 OldParams
= std::move(Parser
->TemplateParams
);
5043 OldOuterParams
= std::move(Parser
->OuterTemplateParams
);
5044 Parser
->TemplateParams
.clear();
5045 Parser
->OuterTemplateParams
.clear();
5047 ~SaveTemplateParams() {
5048 Parser
->TemplateParams
= std::move(OldParams
);
5049 Parser
->OuterTemplateParams
= std::move(OldOuterParams
);
5051 } SaveTemplateParams(this);
5053 if (look() == 'G' || look() == 'T')
5054 return getDerived().parseSpecialName();
5056 auto IsEndOfEncoding
= [&] {
5057 // The set of chars that can potentially follow an <encoding> (none of which
5058 // can start a <type>). Enumerating these allows us to avoid speculative
5060 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5063 NameState
NameInfo(this);
5064 Node
*Name
= getDerived().parseName(&NameInfo
);
5065 if (Name
== nullptr)
5068 if (resolveForwardTemplateRefs(NameInfo
))
5071 if (IsEndOfEncoding())
5074 Node
*Attrs
= nullptr;
5075 if (consumeIf("Ua9enable_ifI")) {
5076 size_t BeforeArgs
= Names
.size();
5077 while (!consumeIf('E')) {
5078 Node
*Arg
= getDerived().parseTemplateArg();
5081 Names
.push_back(Arg
);
5083 Attrs
= make
<EnableIfAttr
>(popTrailingNodeArray(BeforeArgs
));
5088 Node
*ReturnType
= nullptr;
5089 if (!NameInfo
.CtorDtorConversion
&& NameInfo
.EndsWithTemplateArgs
) {
5090 ReturnType
= getDerived().parseType();
5091 if (ReturnType
== nullptr)
5096 return make
<FunctionEncoding
>(ReturnType
, Name
, NodeArray(),
5097 Attrs
, NameInfo
.CVQualifiers
,
5098 NameInfo
.ReferenceQualifier
);
5100 size_t ParamsBegin
= Names
.size();
5102 Node
*Ty
= getDerived().parseType();
5105 Names
.push_back(Ty
);
5106 } while (!IsEndOfEncoding());
5108 return make
<FunctionEncoding
>(ReturnType
, Name
,
5109 popTrailingNodeArray(ParamsBegin
),
5110 Attrs
, NameInfo
.CVQualifiers
,
5111 NameInfo
.ReferenceQualifier
);
5114 template <class Float
>
5118 struct FloatData
<float>
5120 static const size_t mangled_size
= 8;
5121 static const size_t max_demangled_size
= 24;
5122 static constexpr const char* spec
= "%af";
5126 struct FloatData
<double>
5128 static const size_t mangled_size
= 16;
5129 static const size_t max_demangled_size
= 32;
5130 static constexpr const char* spec
= "%a";
5134 struct FloatData
<long double>
5136 #if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5137 defined(__wasm__) || defined(__riscv) || defined(__loongarch__)
5138 static const size_t mangled_size
= 32;
5139 #elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5140 static const size_t mangled_size
= 16;
5142 static const size_t mangled_size
= 20; // May need to be adjusted to 16 or 24 on other platforms
5144 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5145 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5146 // Negatives are one character longer than positives.
5147 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5148 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5149 static const size_t max_demangled_size
= 42;
5150 static constexpr const char *spec
= "%LaL";
5153 template <typename Alloc
, typename Derived
>
5154 template <class Float
>
5155 Node
*AbstractManglingParser
<Alloc
, Derived
>::parseFloatingLiteral() {
5156 const size_t N
= FloatData
<Float
>::mangled_size
;
5159 std::string_view
Data(First
, N
);
5161 if (!std::isxdigit(C
))
5164 if (!consumeIf('E'))
5166 return make
<FloatLiteralImpl
<Float
>>(Data
);
5169 // <seq-id> ::= <0-9A-Z>+
5170 template <typename Alloc
, typename Derived
>
5171 bool AbstractManglingParser
<Alloc
, Derived
>::parseSeqId(size_t *Out
) {
5172 if (!(look() >= '0' && look() <= '9') &&
5173 !(look() >= 'A' && look() <= 'Z'))
5178 if (look() >= '0' && look() <= '9') {
5180 Id
+= static_cast<size_t>(look() - '0');
5181 } else if (look() >= 'A' && look() <= 'Z') {
5183 Id
+= static_cast<size_t>(look() - 'A') + 10;
5192 // <substitution> ::= S <seq-id> _
5194 // <substitution> ::= Sa # ::std::allocator
5195 // <substitution> ::= Sb # ::std::basic_string
5196 // <substitution> ::= Ss # ::std::basic_string < char,
5197 // ::std::char_traits<char>,
5198 // ::std::allocator<char> >
5199 // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5200 // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5201 // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
5202 // The St case is handled specially in parseNestedName.
5203 template <typename Derived
, typename Alloc
>
5204 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSubstitution() {
5205 if (!consumeIf('S'))
5208 if (look() >= 'a' && look() <= 'z') {
5209 SpecialSubKind Kind
;
5212 Kind
= SpecialSubKind::allocator
;
5215 Kind
= SpecialSubKind::basic_string
;
5218 Kind
= SpecialSubKind::iostream
;
5221 Kind
= SpecialSubKind::istream
;
5224 Kind
= SpecialSubKind::ostream
;
5227 Kind
= SpecialSubKind::string
;
5233 auto *SpecialSub
= make
<SpecialSubstitution
>(Kind
);
5237 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5238 // has ABI tags, the tags are appended to the substitution; the result is a
5239 // substitutable component.
5240 Node
*WithTags
= getDerived().parseAbiTags(SpecialSub
);
5241 if (WithTags
!= SpecialSub
) {
5242 Subs
.push_back(WithTags
);
5243 SpecialSub
= WithTags
;
5249 if (consumeIf('_')) {
5257 if (parseSeqId(&Index
))
5260 if (!consumeIf('_') || Index
>= Subs
.size())
5265 // <template-param> ::= T_ # first template parameter
5266 // ::= T <parameter-2 non-negative number> _
5267 // ::= TL <level-1> __
5268 // ::= TL <level-1> _ <parameter-2 non-negative number> _
5269 template <typename Derived
, typename Alloc
>
5270 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateParam() {
5271 if (!consumeIf('T'))
5275 if (consumeIf('L')) {
5276 if (parsePositiveInteger(&Level
))
5279 if (!consumeIf('_'))
5284 if (!consumeIf('_')) {
5285 if (parsePositiveInteger(&Index
))
5288 if (!consumeIf('_'))
5292 // If we're in a context where this <template-param> refers to a
5293 // <template-arg> further ahead in the mangled name (currently just conversion
5294 // operator types), then we should only look it up in the right context.
5295 // This can only happen at the outermost level.
5296 if (PermitForwardTemplateReferences
&& Level
== 0) {
5297 Node
*ForwardRef
= make
<ForwardTemplateReference
>(Index
);
5300 assert(ForwardRef
->getKind() == Node::KForwardTemplateReference
);
5301 ForwardTemplateRefs
.push_back(
5302 static_cast<ForwardTemplateReference
*>(ForwardRef
));
5306 if (Level
>= TemplateParams
.size() || !TemplateParams
[Level
] ||
5307 Index
>= TemplateParams
[Level
]->size()) {
5308 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5309 // list are mangled as the corresponding artificial template type parameter.
5310 if (ParsingLambdaParamsAtLevel
== Level
&& Level
<= TemplateParams
.size()) {
5311 // This will be popped by the ScopedTemplateParamList in
5312 // parseUnnamedTypeName.
5313 if (Level
== TemplateParams
.size())
5314 TemplateParams
.push_back(nullptr);
5315 return make
<NameType
>("auto");
5321 return (*TemplateParams
[Level
])[Index
];
5324 // <template-param-decl> ::= Ty # type parameter
5325 // ::= Tn <type> # non-type parameter
5326 // ::= Tt <template-param-decl>* E # template parameter
5327 // ::= Tp <template-param-decl> # parameter pack
5328 template <typename Derived
, typename Alloc
>
5329 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateParamDecl() {
5330 auto InventTemplateParamName
= [&](TemplateParamKind Kind
) {
5331 unsigned Index
= NumSyntheticTemplateParameters
[(int)Kind
]++;
5332 Node
*N
= make
<SyntheticTemplateParamName
>(Kind
, Index
);
5333 if (N
) TemplateParams
.back()->push_back(N
);
5337 if (consumeIf("Ty")) {
5338 Node
*Name
= InventTemplateParamName(TemplateParamKind::Type
);
5341 return make
<TypeTemplateParamDecl
>(Name
);
5344 if (consumeIf("Tn")) {
5345 Node
*Name
= InventTemplateParamName(TemplateParamKind::NonType
);
5348 Node
*Type
= parseType();
5351 return make
<NonTypeTemplateParamDecl
>(Name
, Type
);
5354 if (consumeIf("Tt")) {
5355 Node
*Name
= InventTemplateParamName(TemplateParamKind::Template
);
5358 size_t ParamsBegin
= Names
.size();
5359 ScopedTemplateParamList
TemplateTemplateParamParams(this);
5360 while (!consumeIf("E")) {
5361 Node
*P
= parseTemplateParamDecl();
5366 NodeArray Params
= popTrailingNodeArray(ParamsBegin
);
5367 return make
<TemplateTemplateParamDecl
>(Name
, Params
);
5370 if (consumeIf("Tp")) {
5371 Node
*P
= parseTemplateParamDecl();
5374 return make
<TemplateParamPackDecl
>(P
);
5380 // <template-arg> ::= <type> # type or template
5381 // ::= X <expression> E # expression
5382 // ::= <expr-primary> # simple expressions
5383 // ::= J <template-arg>* E # argument pack
5384 // ::= LZ <encoding> E # extension
5385 template <typename Derived
, typename Alloc
>
5386 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateArg() {
5390 Node
*Arg
= getDerived().parseExpr();
5391 if (Arg
== nullptr || !consumeIf('E'))
5397 size_t ArgsBegin
= Names
.size();
5398 while (!consumeIf('E')) {
5399 Node
*Arg
= getDerived().parseTemplateArg();
5402 Names
.push_back(Arg
);
5404 NodeArray Args
= popTrailingNodeArray(ArgsBegin
);
5405 return make
<TemplateArgumentPack
>(Args
);
5408 // ::= LZ <encoding> E # extension
5409 if (look(1) == 'Z') {
5411 Node
*Arg
= getDerived().parseEncoding();
5412 if (Arg
== nullptr || !consumeIf('E'))
5416 // ::= <expr-primary> # simple expressions
5417 return getDerived().parseExprPrimary();
5420 return getDerived().parseType();
5424 // <template-args> ::= I <template-arg>* E
5425 // extension, the abi says <template-arg>+
5426 template <typename Derived
, typename Alloc
>
5428 AbstractManglingParser
<Derived
, Alloc
>::parseTemplateArgs(bool TagTemplates
) {
5429 if (!consumeIf('I'))
5432 // <template-params> refer to the innermost <template-args>. Clear out any
5433 // outer args that we may have inserted into TemplateParams.
5435 TemplateParams
.clear();
5436 TemplateParams
.push_back(&OuterTemplateParams
);
5437 OuterTemplateParams
.clear();
5440 size_t ArgsBegin
= Names
.size();
5441 while (!consumeIf('E')) {
5443 auto OldParams
= std::move(TemplateParams
);
5444 Node
*Arg
= getDerived().parseTemplateArg();
5445 TemplateParams
= std::move(OldParams
);
5448 Names
.push_back(Arg
);
5449 Node
*TableEntry
= Arg
;
5450 if (Arg
->getKind() == Node::KTemplateArgumentPack
) {
5451 TableEntry
= make
<ParameterPack
>(
5452 static_cast<TemplateArgumentPack
*>(TableEntry
)->getElements());
5456 TemplateParams
.back()->push_back(TableEntry
);
5458 Node
*Arg
= getDerived().parseTemplateArg();
5461 Names
.push_back(Arg
);
5464 return make
<TemplateArgs
>(popTrailingNodeArray(ArgsBegin
));
5467 // <mangled-name> ::= _Z <encoding>
5469 // extension ::= ___Z <encoding> _block_invoke
5470 // extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5471 // extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
5472 template <typename Derived
, typename Alloc
>
5473 Node
*AbstractManglingParser
<Derived
, Alloc
>::parse() {
5474 if (consumeIf("_Z") || consumeIf("__Z")) {
5475 Node
*Encoding
= getDerived().parseEncoding();
5476 if (Encoding
== nullptr)
5478 if (look() == '.') {
5480 make
<DotSuffix
>(Encoding
, std::string_view(First
, Last
- First
));
5488 if (consumeIf("___Z") || consumeIf("____Z")) {
5489 Node
*Encoding
= getDerived().parseEncoding();
5490 if (Encoding
== nullptr || !consumeIf("_block_invoke"))
5492 bool RequireNumber
= consumeIf('_');
5493 if (parseNumber().empty() && RequireNumber
)
5499 return make
<SpecialName
>("invocation function for block in ", Encoding
);
5502 Node
*Ty
= getDerived().parseType();
5508 template <typename Alloc
>
5509 struct ManglingParser
: AbstractManglingParser
<ManglingParser
<Alloc
>, Alloc
> {
5510 using AbstractManglingParser
<ManglingParser
<Alloc
>,
5511 Alloc
>::AbstractManglingParser
;
5514 DEMANGLE_NAMESPACE_END
5516 #ifdef _LIBCXXABI_COMPILER_CLANG
5517 #pragma clang diagnostic pop
5520 #endif // DEMANGLE_ITANIUMDEMANGLE_H