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"
29 #include <string_view>
30 #include <type_traits>
33 #if defined(__clang__)
34 #pragma clang diagnostic push
35 #pragma clang diagnostic ignored "-Wunused-template"
38 DEMANGLE_NAMESPACE_BEGIN
40 template <class T
, size_t N
> class PODSmallVector
{
41 static_assert(std::is_trivial
<T
>::value
,
42 "T is required to be a trivial type");
48 bool isInline() const { return First
== Inline
; }
56 void reserve(size_t NewCap
) {
59 auto *Tmp
= static_cast<T
*>(std::malloc(NewCap
* sizeof(T
)));
62 std::copy(First
, Last
, Tmp
);
65 First
= static_cast<T
*>(std::realloc(First
, NewCap
* sizeof(T
)));
74 PODSmallVector() : First(Inline
), Last(First
), Cap(Inline
+ N
) {}
76 PODSmallVector(const PODSmallVector
&) = delete;
77 PODSmallVector
&operator=(const PODSmallVector
&) = delete;
79 PODSmallVector(PODSmallVector
&&Other
) : PODSmallVector() {
80 if (Other
.isInline()) {
81 std::copy(Other
.begin(), Other
.end(), First
);
82 Last
= First
+ Other
.size();
93 PODSmallVector
&operator=(PODSmallVector
&&Other
) {
94 if (Other
.isInline()) {
99 std::copy(Other
.begin(), Other
.end(), First
);
100 Last
= First
+ Other
.size();
113 std::swap(First
, Other
.First
);
114 std::swap(Last
, Other
.Last
);
115 std::swap(Cap
, Other
.Cap
);
120 // NOLINTNEXTLINE(readability-identifier-naming)
121 void push_back(const T
&Elem
) {
127 // NOLINTNEXTLINE(readability-identifier-naming)
129 DEMANGLE_ASSERT(Last
!= First
, "Popping empty vector!");
133 void shrinkToSize(size_t Index
) {
134 DEMANGLE_ASSERT(Index
<= size(), "shrinkToSize() can't expand!");
135 Last
= First
+ Index
;
138 T
*begin() { return First
; }
139 T
*end() { return Last
; }
141 bool empty() const { return First
== Last
; }
142 size_t size() const { return static_cast<size_t>(Last
- First
); }
144 DEMANGLE_ASSERT(Last
!= First
, "Calling back() on empty vector!");
147 T
&operator[](size_t Index
) {
148 DEMANGLE_ASSERT(Index
< size(), "Invalid access!");
149 return *(begin() + Index
);
151 void clear() { Last
= First
; }
161 // Base class of all AST nodes. The AST is built by the parser, then is
162 // traversed by the printLeft/Right functions to produce a demangled string.
165 enum Kind
: unsigned char {
166 #define NODE(NodeKind) K##NodeKind,
167 #include "ItaniumNodes.def"
170 /// Three-way bool to track a cached value. Unknown is possible if this node
171 /// has an unexpanded parameter pack below it that may affect this cache.
172 enum class Cache
: unsigned char { Yes
, No
, Unknown
, };
174 /// Operator precedence for expression nodes. Used to determine required
175 /// parens in expression emission.
205 /// Tracks if this node has a component on its right side, in which case we
206 /// need to call printRight.
207 Cache RHSComponentCache
: 2;
209 /// Track if this node is a (possibly qualified) array type. This can affect
210 /// how we format the output string.
211 Cache ArrayCache
: 2;
213 /// Track if this node is a (possibly qualified) function type. This can
214 /// affect how we format the output string.
215 Cache FunctionCache
: 2;
218 Node(Kind K_
, Prec Precedence_
= Prec::Primary
,
219 Cache RHSComponentCache_
= Cache::No
, Cache ArrayCache_
= Cache::No
,
220 Cache FunctionCache_
= Cache::No
)
221 : K(K_
), Precedence(Precedence_
), RHSComponentCache(RHSComponentCache_
),
222 ArrayCache(ArrayCache_
), FunctionCache(FunctionCache_
) {}
223 Node(Kind K_
, Cache RHSComponentCache_
, Cache ArrayCache_
= Cache::No
,
224 Cache FunctionCache_
= Cache::No
)
225 : Node(K_
, Prec::Primary
, RHSComponentCache_
, ArrayCache_
,
228 /// Visit the most-derived object corresponding to this object.
229 template<typename Fn
> void visit(Fn F
) const;
231 // The following function is provided by all derived classes:
233 // Call F with arguments that, when passed to the constructor of this node,
234 // would construct an equivalent node.
235 //template<typename Fn> void match(Fn F) const;
237 bool hasRHSComponent(OutputBuffer
&OB
) const {
238 if (RHSComponentCache
!= Cache::Unknown
)
239 return RHSComponentCache
== Cache::Yes
;
240 return hasRHSComponentSlow(OB
);
243 bool hasArray(OutputBuffer
&OB
) const {
244 if (ArrayCache
!= Cache::Unknown
)
245 return ArrayCache
== Cache::Yes
;
246 return hasArraySlow(OB
);
249 bool hasFunction(OutputBuffer
&OB
) const {
250 if (FunctionCache
!= Cache::Unknown
)
251 return FunctionCache
== Cache::Yes
;
252 return hasFunctionSlow(OB
);
255 Kind
getKind() const { return K
; }
257 Prec
getPrecedence() const { return Precedence
; }
258 Cache
getRHSComponentCache() const { return RHSComponentCache
; }
259 Cache
getArrayCache() const { return ArrayCache
; }
260 Cache
getFunctionCache() const { return FunctionCache
; }
262 virtual bool hasRHSComponentSlow(OutputBuffer
&) const { return false; }
263 virtual bool hasArraySlow(OutputBuffer
&) const { return false; }
264 virtual bool hasFunctionSlow(OutputBuffer
&) const { return false; }
266 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
267 // get at a node that actually represents some concrete syntax.
268 virtual const Node
*getSyntaxNode(OutputBuffer
&) const { return this; }
270 // Print this node as an expression operand, surrounding it in parentheses if
271 // its precedence is [Strictly] weaker than P.
272 void printAsOperand(OutputBuffer
&OB
, Prec P
= Prec::Default
,
273 bool StrictlyWorse
= false) const {
275 unsigned(getPrecedence()) >= unsigned(P
) + unsigned(StrictlyWorse
);
283 void print(OutputBuffer
&OB
) const {
285 if (RHSComponentCache
!= Cache::No
)
289 // Print the "left" side of this Node into OutputBuffer.
290 virtual void printLeft(OutputBuffer
&) const = 0;
292 // Print the "right". This distinction is necessary to represent C++ types
293 // that appear on the RHS of their subtype, such as arrays or functions.
294 // Since most types don't have such a component, provide a default
296 virtual void printRight(OutputBuffer
&) const {}
298 // Print an initializer list of this type. Returns true if we printed a custom
299 // representation, false if nothing has been printed and the default
300 // representation should be used.
301 virtual bool printInitListAsType(OutputBuffer
&, const NodeArray
&) const {
305 virtual std::string_view
getBaseName() const { return {}; }
307 // Silence compiler warnings, this dtor will never be called.
308 virtual ~Node() = default;
311 DEMANGLE_DUMP_METHOD
void dump() const;
320 NodeArray() : Elements(nullptr), NumElements(0) {}
321 NodeArray(Node
**Elements_
, size_t NumElements_
)
322 : Elements(Elements_
), NumElements(NumElements_
) {}
324 bool empty() const { return NumElements
== 0; }
325 size_t size() const { return NumElements
; }
327 Node
**begin() const { return Elements
; }
328 Node
**end() const { return Elements
+ NumElements
; }
330 Node
*operator[](size_t Idx
) const { return Elements
[Idx
]; }
332 void printWithComma(OutputBuffer
&OB
) const {
333 bool FirstElement
= true;
334 for (size_t Idx
= 0; Idx
!= NumElements
; ++Idx
) {
335 size_t BeforeComma
= OB
.getCurrentPosition();
338 size_t AfterComma
= OB
.getCurrentPosition();
339 Elements
[Idx
]->printAsOperand(OB
, Node::Prec::Comma
);
341 // Elements[Idx] is an empty parameter pack expansion, we should erase the
342 // comma we just printed.
343 if (AfterComma
== OB
.getCurrentPosition()) {
344 OB
.setCurrentPosition(BeforeComma
);
348 FirstElement
= false;
352 // Print an array of integer literals as a string literal. Returns whether we
354 bool printAsString(OutputBuffer
&OB
) const;
357 struct NodeArrayNode
: Node
{
359 NodeArrayNode(NodeArray Array_
) : Node(KNodeArrayNode
), Array(Array_
) {}
361 template<typename Fn
> void match(Fn F
) const { F(Array
); }
363 void printLeft(OutputBuffer
&OB
) const override
{ Array
.printWithComma(OB
); }
366 class DotSuffix final
: public Node
{
368 const std::string_view Suffix
;
371 DotSuffix(const Node
*Prefix_
, std::string_view Suffix_
)
372 : Node(KDotSuffix
), Prefix(Prefix_
), Suffix(Suffix_
) {}
374 template<typename Fn
> void match(Fn F
) const { F(Prefix
, Suffix
); }
376 void printLeft(OutputBuffer
&OB
) const override
{
384 class VendorExtQualType final
: public Node
{
386 std::string_view Ext
;
390 VendorExtQualType(const Node
*Ty_
, std::string_view Ext_
, const Node
*TA_
)
391 : Node(KVendorExtQualType
), Ty(Ty_
), Ext(Ext_
), TA(TA_
) {}
393 const Node
*getTy() const { return Ty
; }
394 std::string_view
getExt() const { return Ext
; }
395 const Node
*getTA() const { return TA
; }
397 template <typename Fn
> void match(Fn F
) const { F(Ty
, Ext
, TA
); }
399 void printLeft(OutputBuffer
&OB
) const override
{
408 enum FunctionRefQual
: unsigned char {
421 inline Qualifiers
operator|=(Qualifiers
&Q1
, Qualifiers Q2
) {
422 return Q1
= static_cast<Qualifiers
>(Q1
| Q2
);
425 class QualType final
: public Node
{
427 const Qualifiers Quals
;
430 void printQuals(OutputBuffer
&OB
) const {
431 if (Quals
& QualConst
)
433 if (Quals
& QualVolatile
)
435 if (Quals
& QualRestrict
)
440 QualType(const Node
*Child_
, Qualifiers Quals_
)
441 : Node(KQualType
, Child_
->getRHSComponentCache(), Child_
->getArrayCache(),
442 Child_
->getFunctionCache()),
443 Quals(Quals_
), Child(Child_
) {}
445 Qualifiers
getQuals() const { return Quals
; }
446 const Node
*getChild() const { return Child
; }
448 template<typename Fn
> void match(Fn F
) const { F(Child
, Quals
); }
450 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
451 return Child
->hasRHSComponent(OB
);
453 bool hasArraySlow(OutputBuffer
&OB
) const override
{
454 return Child
->hasArray(OB
);
456 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
457 return Child
->hasFunction(OB
);
460 void printLeft(OutputBuffer
&OB
) const override
{
461 Child
->printLeft(OB
);
465 void printRight(OutputBuffer
&OB
) const override
{ Child
->printRight(OB
); }
468 class ConversionOperatorType final
: public Node
{
472 ConversionOperatorType(const Node
*Ty_
)
473 : Node(KConversionOperatorType
), Ty(Ty_
) {}
475 template<typename Fn
> void match(Fn F
) const { F(Ty
); }
477 void printLeft(OutputBuffer
&OB
) const override
{
483 class PostfixQualifiedType final
: public Node
{
485 const std::string_view Postfix
;
488 PostfixQualifiedType(const Node
*Ty_
, std::string_view Postfix_
)
489 : Node(KPostfixQualifiedType
), Ty(Ty_
), Postfix(Postfix_
) {}
491 template<typename Fn
> void match(Fn F
) const { F(Ty
, Postfix
); }
493 void printLeft(OutputBuffer
&OB
) const override
{
499 class NameType final
: public Node
{
500 const std::string_view Name
;
503 NameType(std::string_view Name_
) : Node(KNameType
), Name(Name_
) {}
505 template<typename Fn
> void match(Fn F
) const { F(Name
); }
507 std::string_view
getName() const { return Name
; }
508 std::string_view
getBaseName() const override
{ return Name
; }
510 void printLeft(OutputBuffer
&OB
) const override
{ OB
+= Name
; }
513 class BitIntType final
: public Node
{
518 BitIntType(const Node
*Size_
, bool Signed_
)
519 : Node(KBitIntType
), Size(Size_
), Signed(Signed_
) {}
521 template <typename Fn
> void match(Fn F
) const { F(Size
, Signed
); }
523 void printLeft(OutputBuffer
&OB
) const override
{
528 Size
->printAsOperand(OB
);
533 class ElaboratedTypeSpefType
: public Node
{
534 std::string_view Kind
;
537 ElaboratedTypeSpefType(std::string_view Kind_
, Node
*Child_
)
538 : Node(KElaboratedTypeSpefType
), Kind(Kind_
), Child(Child_
) {}
540 template<typename Fn
> void match(Fn F
) const { F(Kind
, Child
); }
542 void printLeft(OutputBuffer
&OB
) const override
{
549 class TransformedType
: public Node
{
550 std::string_view Transform
;
553 TransformedType(std::string_view Transform_
, Node
*BaseType_
)
554 : Node(KTransformedType
), Transform(Transform_
), BaseType(BaseType_
) {}
556 template<typename Fn
> void match(Fn F
) const { F(Transform
, BaseType
); }
558 void printLeft(OutputBuffer
&OB
) const override
{
566 struct AbiTagAttr
: Node
{
568 std::string_view Tag
;
570 AbiTagAttr(Node
*Base_
, std::string_view Tag_
)
571 : Node(KAbiTagAttr
, Base_
->getRHSComponentCache(), Base_
->getArrayCache(),
572 Base_
->getFunctionCache()),
573 Base(Base_
), Tag(Tag_
) {}
575 template<typename Fn
> void match(Fn F
) const { F(Base
, Tag
); }
577 std::string_view
getBaseName() const override
{ return Base
->getBaseName(); }
579 void printLeft(OutputBuffer
&OB
) const override
{
587 class EnableIfAttr
: public Node
{
588 NodeArray Conditions
;
590 EnableIfAttr(NodeArray Conditions_
)
591 : Node(KEnableIfAttr
), Conditions(Conditions_
) {}
593 template<typename Fn
> void match(Fn F
) const { F(Conditions
); }
595 void printLeft(OutputBuffer
&OB
) const override
{
596 OB
+= " [enable_if:";
597 Conditions
.printWithComma(OB
);
602 class ObjCProtoName
: public Node
{
604 std::string_view Protocol
;
606 friend class PointerType
;
609 ObjCProtoName(const Node
*Ty_
, std::string_view Protocol_
)
610 : Node(KObjCProtoName
), Ty(Ty_
), Protocol(Protocol_
) {}
612 template<typename Fn
> void match(Fn F
) const { F(Ty
, Protocol
); }
614 bool isObjCObject() const {
615 return Ty
->getKind() == KNameType
&&
616 static_cast<const NameType
*>(Ty
)->getName() == "objc_object";
619 void printLeft(OutputBuffer
&OB
) const override
{
627 class PointerType final
: public Node
{
631 PointerType(const Node
*Pointee_
)
632 : Node(KPointerType
, Pointee_
->getRHSComponentCache()),
635 const Node
*getPointee() const { return Pointee
; }
637 template<typename Fn
> void match(Fn F
) const { F(Pointee
); }
639 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
640 return Pointee
->hasRHSComponent(OB
);
643 void printLeft(OutputBuffer
&OB
) const override
{
644 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
645 if (Pointee
->getKind() != KObjCProtoName
||
646 !static_cast<const ObjCProtoName
*>(Pointee
)->isObjCObject()) {
647 Pointee
->printLeft(OB
);
648 if (Pointee
->hasArray(OB
))
650 if (Pointee
->hasArray(OB
) || Pointee
->hasFunction(OB
))
654 const auto *objcProto
= static_cast<const ObjCProtoName
*>(Pointee
);
656 OB
+= objcProto
->Protocol
;
661 void printRight(OutputBuffer
&OB
) const override
{
662 if (Pointee
->getKind() != KObjCProtoName
||
663 !static_cast<const ObjCProtoName
*>(Pointee
)->isObjCObject()) {
664 if (Pointee
->hasArray(OB
) || Pointee
->hasFunction(OB
))
666 Pointee
->printRight(OB
);
671 enum class ReferenceKind
{
676 // Represents either a LValue or an RValue reference type.
677 class ReferenceType
: public Node
{
681 mutable bool Printing
= false;
683 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
684 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
685 // other combination collapses to a lvalue ref.
687 // A combination of a TemplateForwardReference and a back-ref Substitution
688 // from an ill-formed string may have created a cycle; use cycle detection to
689 // avoid looping forever.
690 std::pair
<ReferenceKind
, const Node
*> collapse(OutputBuffer
&OB
) const {
691 auto SoFar
= std::make_pair(RK
, Pointee
);
692 // Track the chain of nodes for the Floyd's 'tortoise and hare'
693 // cycle-detection algorithm, since getSyntaxNode(S) is impure
694 PODSmallVector
<const Node
*, 8> Prev
;
696 const Node
*SN
= SoFar
.second
->getSyntaxNode(OB
);
697 if (SN
->getKind() != KReferenceType
)
699 auto *RT
= static_cast<const ReferenceType
*>(SN
);
700 SoFar
.second
= RT
->Pointee
;
701 SoFar
.first
= std::min(SoFar
.first
, RT
->RK
);
703 // The middle of Prev is the 'slow' pointer moving at half speed
704 Prev
.push_back(SoFar
.second
);
705 if (Prev
.size() > 1 && SoFar
.second
== Prev
[(Prev
.size() - 1) / 2]) {
707 SoFar
.second
= nullptr;
715 ReferenceType(const Node
*Pointee_
, ReferenceKind RK_
)
716 : Node(KReferenceType
, Pointee_
->getRHSComponentCache()),
717 Pointee(Pointee_
), RK(RK_
) {}
719 template<typename Fn
> void match(Fn F
) const { F(Pointee
, RK
); }
721 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
722 return Pointee
->hasRHSComponent(OB
);
725 void printLeft(OutputBuffer
&OB
) const override
{
728 ScopedOverride
<bool> SavePrinting(Printing
, true);
729 std::pair
<ReferenceKind
, const Node
*> Collapsed
= collapse(OB
);
730 if (!Collapsed
.second
)
732 Collapsed
.second
->printLeft(OB
);
733 if (Collapsed
.second
->hasArray(OB
))
735 if (Collapsed
.second
->hasArray(OB
) || Collapsed
.second
->hasFunction(OB
))
738 OB
+= (Collapsed
.first
== ReferenceKind::LValue
? "&" : "&&");
740 void printRight(OutputBuffer
&OB
) const override
{
743 ScopedOverride
<bool> SavePrinting(Printing
, true);
744 std::pair
<ReferenceKind
, const Node
*> Collapsed
= collapse(OB
);
745 if (!Collapsed
.second
)
747 if (Collapsed
.second
->hasArray(OB
) || Collapsed
.second
->hasFunction(OB
))
749 Collapsed
.second
->printRight(OB
);
753 class PointerToMemberType final
: public Node
{
754 const Node
*ClassType
;
755 const Node
*MemberType
;
758 PointerToMemberType(const Node
*ClassType_
, const Node
*MemberType_
)
759 : Node(KPointerToMemberType
, MemberType_
->getRHSComponentCache()),
760 ClassType(ClassType_
), MemberType(MemberType_
) {}
762 template<typename Fn
> void match(Fn F
) const { F(ClassType
, MemberType
); }
764 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
765 return MemberType
->hasRHSComponent(OB
);
768 void printLeft(OutputBuffer
&OB
) const override
{
769 MemberType
->printLeft(OB
);
770 if (MemberType
->hasArray(OB
) || MemberType
->hasFunction(OB
))
774 ClassType
->print(OB
);
778 void printRight(OutputBuffer
&OB
) const override
{
779 if (MemberType
->hasArray(OB
) || MemberType
->hasFunction(OB
))
781 MemberType
->printRight(OB
);
785 class ArrayType final
: public Node
{
790 ArrayType(const Node
*Base_
, Node
*Dimension_
)
792 /*RHSComponentCache=*/Cache::Yes
,
793 /*ArrayCache=*/Cache::Yes
),
794 Base(Base_
), Dimension(Dimension_
) {}
796 template<typename Fn
> void match(Fn F
) const { F(Base
, Dimension
); }
798 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
799 bool hasArraySlow(OutputBuffer
&) const override
{ return true; }
801 void printLeft(OutputBuffer
&OB
) const override
{ Base
->printLeft(OB
); }
803 void printRight(OutputBuffer
&OB
) const override
{
804 if (OB
.back() != ']')
808 Dimension
->print(OB
);
810 Base
->printRight(OB
);
813 bool printInitListAsType(OutputBuffer
&OB
,
814 const NodeArray
&Elements
) const override
{
815 if (Base
->getKind() == KNameType
&&
816 static_cast<const NameType
*>(Base
)->getName() == "char") {
817 return Elements
.printAsString(OB
);
823 class FunctionType final
: public Node
{
827 FunctionRefQual RefQual
;
828 const Node
*ExceptionSpec
;
831 FunctionType(const Node
*Ret_
, NodeArray Params_
, Qualifiers CVQuals_
,
832 FunctionRefQual RefQual_
, const Node
*ExceptionSpec_
)
833 : Node(KFunctionType
,
834 /*RHSComponentCache=*/Cache::Yes
, /*ArrayCache=*/Cache::No
,
835 /*FunctionCache=*/Cache::Yes
),
836 Ret(Ret_
), Params(Params_
), CVQuals(CVQuals_
), RefQual(RefQual_
),
837 ExceptionSpec(ExceptionSpec_
) {}
839 template<typename Fn
> void match(Fn F
) const {
840 F(Ret
, Params
, CVQuals
, RefQual
, ExceptionSpec
);
843 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
844 bool hasFunctionSlow(OutputBuffer
&) const override
{ return true; }
846 // Handle C++'s ... quirky decl grammar by using the left & right
847 // distinction. Consider:
848 // int (*f(float))(char) {}
849 // f is a function that takes a float and returns a pointer to a function
850 // that takes a char and returns an int. If we're trying to print f, start
851 // by printing out the return types's left, then print our parameters, then
852 // finally print right of the return type.
853 void printLeft(OutputBuffer
&OB
) const override
{
858 void printRight(OutputBuffer
&OB
) const override
{
860 Params
.printWithComma(OB
);
864 if (CVQuals
& QualConst
)
866 if (CVQuals
& QualVolatile
)
868 if (CVQuals
& QualRestrict
)
871 if (RefQual
== FrefQualLValue
)
873 else if (RefQual
== FrefQualRValue
)
876 if (ExceptionSpec
!= nullptr) {
878 ExceptionSpec
->print(OB
);
883 class NoexceptSpec
: public Node
{
886 NoexceptSpec(const Node
*E_
) : Node(KNoexceptSpec
), E(E_
) {}
888 template<typename Fn
> void match(Fn F
) const { F(E
); }
890 void printLeft(OutputBuffer
&OB
) const override
{
893 E
->printAsOperand(OB
);
898 class DynamicExceptionSpec
: public Node
{
901 DynamicExceptionSpec(NodeArray Types_
)
902 : Node(KDynamicExceptionSpec
), Types(Types_
) {}
904 template<typename Fn
> void match(Fn F
) const { F(Types
); }
906 void printLeft(OutputBuffer
&OB
) const override
{
909 Types
.printWithComma(OB
);
914 /// Represents the explicitly named object parameter.
918 /// void bar(this Foo && self);
921 class ExplicitObjectParameter final
: public Node
{
925 ExplicitObjectParameter(Node
*Base_
)
926 : Node(KExplicitObjectParameter
), Base(Base_
) {
929 "Creating an ExplicitObjectParameter without a valid Base Node.");
932 template <typename Fn
> void match(Fn F
) const { F(Base
); }
934 void printLeft(OutputBuffer
&OB
) const override
{
940 class FunctionEncoding final
: public Node
{
945 const Node
*Requires
;
947 FunctionRefQual RefQual
;
950 FunctionEncoding(const Node
*Ret_
, const Node
*Name_
, NodeArray Params_
,
951 const Node
*Attrs_
, const Node
*Requires_
,
952 Qualifiers CVQuals_
, FunctionRefQual RefQual_
)
953 : Node(KFunctionEncoding
,
954 /*RHSComponentCache=*/Cache::Yes
, /*ArrayCache=*/Cache::No
,
955 /*FunctionCache=*/Cache::Yes
),
956 Ret(Ret_
), Name(Name_
), Params(Params_
), Attrs(Attrs_
),
957 Requires(Requires_
), CVQuals(CVQuals_
), RefQual(RefQual_
) {}
959 template<typename Fn
> void match(Fn F
) const {
960 F(Ret
, Name
, Params
, Attrs
, Requires
, CVQuals
, RefQual
);
963 Qualifiers
getCVQuals() const { return CVQuals
; }
964 FunctionRefQual
getRefQual() const { return RefQual
; }
965 NodeArray
getParams() const { return Params
; }
966 const Node
*getReturnType() const { return Ret
; }
968 bool hasRHSComponentSlow(OutputBuffer
&) const override
{ return true; }
969 bool hasFunctionSlow(OutputBuffer
&) const override
{ return true; }
971 const Node
*getName() const { return Name
; }
973 void printLeft(OutputBuffer
&OB
) const override
{
976 if (!Ret
->hasRHSComponent(OB
))
982 void printRight(OutputBuffer
&OB
) const override
{
984 Params
.printWithComma(OB
);
989 if (CVQuals
& QualConst
)
991 if (CVQuals
& QualVolatile
)
993 if (CVQuals
& QualRestrict
)
996 if (RefQual
== FrefQualLValue
)
998 else if (RefQual
== FrefQualRValue
)
1001 if (Attrs
!= nullptr)
1004 if (Requires
!= nullptr) {
1006 Requires
->print(OB
);
1011 class LiteralOperator
: public Node
{
1015 LiteralOperator(const Node
*OpName_
)
1016 : Node(KLiteralOperator
), OpName(OpName_
) {}
1018 template<typename Fn
> void match(Fn F
) const { F(OpName
); }
1020 void printLeft(OutputBuffer
&OB
) const override
{
1021 OB
+= "operator\"\" ";
1026 class SpecialName final
: public Node
{
1027 const std::string_view Special
;
1031 SpecialName(std::string_view Special_
, const Node
*Child_
)
1032 : Node(KSpecialName
), Special(Special_
), Child(Child_
) {}
1034 template<typename Fn
> void match(Fn F
) const { F(Special
, Child
); }
1036 void printLeft(OutputBuffer
&OB
) const override
{
1042 class CtorVtableSpecialName final
: public Node
{
1043 const Node
*FirstType
;
1044 const Node
*SecondType
;
1047 CtorVtableSpecialName(const Node
*FirstType_
, const Node
*SecondType_
)
1048 : Node(KCtorVtableSpecialName
),
1049 FirstType(FirstType_
), SecondType(SecondType_
) {}
1051 template<typename Fn
> void match(Fn F
) const { F(FirstType
, SecondType
); }
1053 void printLeft(OutputBuffer
&OB
) const override
{
1054 OB
+= "construction vtable for ";
1055 FirstType
->print(OB
);
1057 SecondType
->print(OB
);
1061 struct NestedName
: Node
{
1065 NestedName(Node
*Qual_
, Node
*Name_
)
1066 : Node(KNestedName
), Qual(Qual_
), Name(Name_
) {}
1068 template<typename Fn
> void match(Fn F
) const { F(Qual
, Name
); }
1070 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1072 void printLeft(OutputBuffer
&OB
) const override
{
1079 struct MemberLikeFriendName
: Node
{
1083 MemberLikeFriendName(Node
*Qual_
, Node
*Name_
)
1084 : Node(KMemberLikeFriendName
), Qual(Qual_
), Name(Name_
) {}
1086 template<typename Fn
> void match(Fn F
) const { F(Qual
, Name
); }
1088 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1090 void printLeft(OutputBuffer
&OB
) const override
{
1097 struct ModuleName
: Node
{
1102 ModuleName(ModuleName
*Parent_
, Node
*Name_
, bool IsPartition_
= false)
1103 : Node(KModuleName
), Parent(Parent_
), Name(Name_
),
1104 IsPartition(IsPartition_
) {}
1106 template <typename Fn
> void match(Fn F
) const {
1107 F(Parent
, Name
, IsPartition
);
1110 void printLeft(OutputBuffer
&OB
) const override
{
1113 if (Parent
|| IsPartition
)
1114 OB
+= IsPartition
? ':' : '.';
1119 struct ModuleEntity
: Node
{
1123 ModuleEntity(ModuleName
*Module_
, Node
*Name_
)
1124 : Node(KModuleEntity
), Module(Module_
), Name(Name_
) {}
1126 template <typename Fn
> void match(Fn F
) const { F(Module
, Name
); }
1128 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1130 void printLeft(OutputBuffer
&OB
) const override
{
1137 struct LocalName
: Node
{
1141 LocalName(Node
*Encoding_
, Node
*Entity_
)
1142 : Node(KLocalName
), Encoding(Encoding_
), Entity(Entity_
) {}
1144 template<typename Fn
> void match(Fn F
) const { F(Encoding
, Entity
); }
1146 void printLeft(OutputBuffer
&OB
) const override
{
1147 Encoding
->print(OB
);
1153 class QualifiedName final
: public Node
{
1155 const Node
*Qualifier
;
1159 QualifiedName(const Node
*Qualifier_
, const Node
*Name_
)
1160 : Node(KQualifiedName
), Qualifier(Qualifier_
), Name(Name_
) {}
1162 template<typename Fn
> void match(Fn F
) const { F(Qualifier
, Name
); }
1164 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1166 void printLeft(OutputBuffer
&OB
) const override
{
1167 Qualifier
->print(OB
);
1173 class VectorType final
: public Node
{
1174 const Node
*BaseType
;
1175 const Node
*Dimension
;
1178 VectorType(const Node
*BaseType_
, const Node
*Dimension_
)
1179 : Node(KVectorType
), BaseType(BaseType_
), Dimension(Dimension_
) {}
1181 const Node
*getBaseType() const { return BaseType
; }
1182 const Node
*getDimension() const { return Dimension
; }
1184 template<typename Fn
> void match(Fn F
) const { F(BaseType
, Dimension
); }
1186 void printLeft(OutputBuffer
&OB
) const override
{
1187 BaseType
->print(OB
);
1190 Dimension
->print(OB
);
1195 class PixelVectorType final
: public Node
{
1196 const Node
*Dimension
;
1199 PixelVectorType(const Node
*Dimension_
)
1200 : Node(KPixelVectorType
), Dimension(Dimension_
) {}
1202 template<typename Fn
> void match(Fn F
) const { F(Dimension
); }
1204 void printLeft(OutputBuffer
&OB
) const override
{
1205 // FIXME: This should demangle as "vector pixel".
1206 OB
+= "pixel vector[";
1207 Dimension
->print(OB
);
1212 class BinaryFPType final
: public Node
{
1213 const Node
*Dimension
;
1216 BinaryFPType(const Node
*Dimension_
)
1217 : Node(KBinaryFPType
), Dimension(Dimension_
) {}
1219 template<typename Fn
> void match(Fn F
) const { F(Dimension
); }
1221 void printLeft(OutputBuffer
&OB
) const override
{
1223 Dimension
->print(OB
);
1227 enum class TemplateParamKind
{ Type
, NonType
, Template
};
1229 /// An invented name for a template parameter for which we don't have a
1230 /// corresponding template argument.
1232 /// This node is created when parsing the <lambda-sig> for a lambda with
1233 /// explicit template arguments, which might be referenced in the parameter
1234 /// types appearing later in the <lambda-sig>.
1235 class SyntheticTemplateParamName final
: public Node
{
1236 TemplateParamKind Kind
;
1240 SyntheticTemplateParamName(TemplateParamKind Kind_
, unsigned Index_
)
1241 : Node(KSyntheticTemplateParamName
), Kind(Kind_
), Index(Index_
) {}
1243 template<typename Fn
> void match(Fn F
) const { F(Kind
, Index
); }
1245 void printLeft(OutputBuffer
&OB
) const override
{
1247 case TemplateParamKind::Type
:
1250 case TemplateParamKind::NonType
:
1253 case TemplateParamKind::Template
:
1262 class TemplateParamQualifiedArg final
: public Node
{
1267 TemplateParamQualifiedArg(Node
*Param_
, Node
*Arg_
)
1268 : Node(KTemplateParamQualifiedArg
), Param(Param_
), Arg(Arg_
) {}
1270 template <typename Fn
> void match(Fn F
) const { F(Param
, Arg
); }
1272 Node
*getArg() { return Arg
; }
1274 void printLeft(OutputBuffer
&OB
) const override
{
1275 // Don't print Param to keep the output consistent.
1280 /// A template type parameter declaration, 'typename T'.
1281 class TypeTemplateParamDecl final
: public Node
{
1285 TypeTemplateParamDecl(Node
*Name_
)
1286 : Node(KTypeTemplateParamDecl
, Cache::Yes
), Name(Name_
) {}
1288 template<typename Fn
> void match(Fn F
) const { F(Name
); }
1290 void printLeft(OutputBuffer
&OB
) const override
{ OB
+= "typename "; }
1292 void printRight(OutputBuffer
&OB
) const override
{ Name
->print(OB
); }
1295 /// A constrained template type parameter declaration, 'C<U> T'.
1296 class ConstrainedTypeTemplateParamDecl final
: public Node
{
1301 ConstrainedTypeTemplateParamDecl(Node
*Constraint_
, Node
*Name_
)
1302 : Node(KConstrainedTypeTemplateParamDecl
, Cache::Yes
),
1303 Constraint(Constraint_
), Name(Name_
) {}
1305 template<typename Fn
> void match(Fn F
) const { F(Constraint
, Name
); }
1307 void printLeft(OutputBuffer
&OB
) const override
{
1308 Constraint
->print(OB
);
1312 void printRight(OutputBuffer
&OB
) const override
{ Name
->print(OB
); }
1315 /// A non-type template parameter declaration, 'int N'.
1316 class NonTypeTemplateParamDecl final
: public Node
{
1321 NonTypeTemplateParamDecl(Node
*Name_
, Node
*Type_
)
1322 : Node(KNonTypeTemplateParamDecl
, Cache::Yes
), Name(Name_
), Type(Type_
) {}
1324 template<typename Fn
> void match(Fn F
) const { F(Name
, Type
); }
1326 void printLeft(OutputBuffer
&OB
) const override
{
1327 Type
->printLeft(OB
);
1328 if (!Type
->hasRHSComponent(OB
))
1332 void printRight(OutputBuffer
&OB
) const override
{
1334 Type
->printRight(OB
);
1338 /// A template template parameter declaration,
1339 /// 'template<typename T> typename N'.
1340 class TemplateTemplateParamDecl final
: public Node
{
1346 TemplateTemplateParamDecl(Node
*Name_
, NodeArray Params_
, Node
*Requires_
)
1347 : Node(KTemplateTemplateParamDecl
, Cache::Yes
), Name(Name_
),
1348 Params(Params_
), Requires(Requires_
) {}
1350 template <typename Fn
> void match(Fn F
) const { F(Name
, Params
, Requires
); }
1352 void printLeft(OutputBuffer
&OB
) const override
{
1353 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1355 Params
.printWithComma(OB
);
1356 OB
+= "> typename ";
1359 void printRight(OutputBuffer
&OB
) const override
{
1361 if (Requires
!= nullptr) {
1363 Requires
->print(OB
);
1368 /// A template parameter pack declaration, 'typename ...T'.
1369 class TemplateParamPackDecl final
: public Node
{
1373 TemplateParamPackDecl(Node
*Param_
)
1374 : Node(KTemplateParamPackDecl
, Cache::Yes
), Param(Param_
) {}
1376 template<typename Fn
> void match(Fn F
) const { F(Param
); }
1378 void printLeft(OutputBuffer
&OB
) const override
{
1379 Param
->printLeft(OB
);
1383 void printRight(OutputBuffer
&OB
) const override
{ Param
->printRight(OB
); }
1386 /// An unexpanded parameter pack (either in the expression or type context). If
1387 /// this AST is correct, this node will have a ParameterPackExpansion node above
1390 /// This node is created when some <template-args> are found that apply to an
1391 /// <encoding>, and is stored in the TemplateParams table. In order for this to
1392 /// appear in the final AST, it has to referenced via a <template-param> (ie,
1394 class ParameterPack final
: public Node
{
1397 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1399 void initializePackExpansion(OutputBuffer
&OB
) const {
1400 if (OB
.CurrentPackMax
== std::numeric_limits
<unsigned>::max()) {
1401 OB
.CurrentPackMax
= static_cast<unsigned>(Data
.size());
1402 OB
.CurrentPackIndex
= 0;
1407 ParameterPack(NodeArray Data_
) : Node(KParameterPack
), Data(Data_
) {
1408 ArrayCache
= FunctionCache
= RHSComponentCache
= Cache::Unknown
;
1409 if (std::all_of(Data
.begin(), Data
.end(),
1410 [](Node
*P
) { return P
->getArrayCache() == Cache::No
; }))
1411 ArrayCache
= Cache::No
;
1412 if (std::all_of(Data
.begin(), Data
.end(),
1413 [](Node
*P
) { return P
->getFunctionCache() == Cache::No
; }))
1414 FunctionCache
= Cache::No
;
1415 if (std::all_of(Data
.begin(), Data
.end(), [](Node
*P
) {
1416 return P
->getRHSComponentCache() == Cache::No
;
1418 RHSComponentCache
= Cache::No
;
1421 template<typename Fn
> void match(Fn F
) const { F(Data
); }
1423 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
1424 initializePackExpansion(OB
);
1425 size_t Idx
= OB
.CurrentPackIndex
;
1426 return Idx
< Data
.size() && Data
[Idx
]->hasRHSComponent(OB
);
1428 bool hasArraySlow(OutputBuffer
&OB
) const override
{
1429 initializePackExpansion(OB
);
1430 size_t Idx
= OB
.CurrentPackIndex
;
1431 return Idx
< Data
.size() && Data
[Idx
]->hasArray(OB
);
1433 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
1434 initializePackExpansion(OB
);
1435 size_t Idx
= OB
.CurrentPackIndex
;
1436 return Idx
< Data
.size() && Data
[Idx
]->hasFunction(OB
);
1438 const Node
*getSyntaxNode(OutputBuffer
&OB
) const override
{
1439 initializePackExpansion(OB
);
1440 size_t Idx
= OB
.CurrentPackIndex
;
1441 return Idx
< Data
.size() ? Data
[Idx
]->getSyntaxNode(OB
) : this;
1444 void printLeft(OutputBuffer
&OB
) const override
{
1445 initializePackExpansion(OB
);
1446 size_t Idx
= OB
.CurrentPackIndex
;
1447 if (Idx
< Data
.size())
1448 Data
[Idx
]->printLeft(OB
);
1450 void printRight(OutputBuffer
&OB
) const override
{
1451 initializePackExpansion(OB
);
1452 size_t Idx
= OB
.CurrentPackIndex
;
1453 if (Idx
< Data
.size())
1454 Data
[Idx
]->printRight(OB
);
1458 /// A variadic template argument. This node represents an occurrence of
1459 /// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1460 /// one of its Elements is. The parser inserts a ParameterPack into the
1461 /// TemplateParams table if the <template-args> this pack belongs to apply to an
1463 class TemplateArgumentPack final
: public Node
{
1466 TemplateArgumentPack(NodeArray Elements_
)
1467 : Node(KTemplateArgumentPack
), Elements(Elements_
) {}
1469 template<typename Fn
> void match(Fn F
) const { F(Elements
); }
1471 NodeArray
getElements() const { return Elements
; }
1473 void printLeft(OutputBuffer
&OB
) const override
{
1474 Elements
.printWithComma(OB
);
1478 /// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1479 /// which each have Child->ParameterPackSize elements.
1480 class ParameterPackExpansion final
: public Node
{
1484 ParameterPackExpansion(const Node
*Child_
)
1485 : Node(KParameterPackExpansion
), Child(Child_
) {}
1487 template<typename Fn
> void match(Fn F
) const { F(Child
); }
1489 const Node
*getChild() const { return Child
; }
1491 void printLeft(OutputBuffer
&OB
) const override
{
1492 constexpr unsigned Max
= std::numeric_limits
<unsigned>::max();
1493 ScopedOverride
<unsigned> SavePackIdx(OB
.CurrentPackIndex
, Max
);
1494 ScopedOverride
<unsigned> SavePackMax(OB
.CurrentPackMax
, Max
);
1495 size_t StreamPos
= OB
.getCurrentPosition();
1497 // Print the first element in the pack. If Child contains a ParameterPack,
1498 // it will set up S.CurrentPackMax and print the first element.
1501 // No ParameterPack was found in Child. This can occur if we've found a pack
1502 // expansion on a <function-param>.
1503 if (OB
.CurrentPackMax
== Max
) {
1508 // We found a ParameterPack, but it has no elements. Erase whatever we may
1510 if (OB
.CurrentPackMax
== 0) {
1511 OB
.setCurrentPosition(StreamPos
);
1515 // Else, iterate through the rest of the elements in the pack.
1516 for (unsigned I
= 1, E
= OB
.CurrentPackMax
; I
< E
; ++I
) {
1518 OB
.CurrentPackIndex
= I
;
1524 class TemplateArgs final
: public Node
{
1529 TemplateArgs(NodeArray Params_
, Node
*Requires_
)
1530 : Node(KTemplateArgs
), Params(Params_
), Requires(Requires_
) {}
1532 template<typename Fn
> void match(Fn F
) const { F(Params
, Requires
); }
1534 NodeArray
getParams() { return Params
; }
1536 void printLeft(OutputBuffer
&OB
) const override
{
1537 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1539 Params
.printWithComma(OB
);
1541 // Don't print the requires clause to keep the output simple.
1545 /// A forward-reference to a template argument that was not known at the point
1546 /// where the template parameter name was parsed in a mangling.
1548 /// This is created when demangling the name of a specialization of a
1549 /// conversion function template:
1553 /// template<typename T> operator T*();
1557 /// When demangling a specialization of the conversion function template, we
1558 /// encounter the name of the template (including the \c T) before we reach
1559 /// the template argument list, so we cannot substitute the parameter name
1560 /// for the corresponding argument while parsing. Instead, we create a
1561 /// \c ForwardTemplateReference node that is resolved after we parse the
1562 /// template arguments.
1563 struct ForwardTemplateReference
: Node
{
1565 Node
*Ref
= nullptr;
1567 // If we're currently printing this node. It is possible (though invalid) for
1568 // a forward template reference to refer to itself via a substitution. This
1569 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1570 // out if more than one print* function is active.
1571 mutable bool Printing
= false;
1573 ForwardTemplateReference(size_t Index_
)
1574 : Node(KForwardTemplateReference
, Cache::Unknown
, Cache::Unknown
,
1578 // We don't provide a matcher for these, because the value of the node is
1579 // not determined by its construction parameters, and it generally needs
1580 // special handling.
1581 template<typename Fn
> void match(Fn F
) const = delete;
1583 bool hasRHSComponentSlow(OutputBuffer
&OB
) const override
{
1586 ScopedOverride
<bool> SavePrinting(Printing
, true);
1587 return Ref
->hasRHSComponent(OB
);
1589 bool hasArraySlow(OutputBuffer
&OB
) const override
{
1592 ScopedOverride
<bool> SavePrinting(Printing
, true);
1593 return Ref
->hasArray(OB
);
1595 bool hasFunctionSlow(OutputBuffer
&OB
) const override
{
1598 ScopedOverride
<bool> SavePrinting(Printing
, true);
1599 return Ref
->hasFunction(OB
);
1601 const Node
*getSyntaxNode(OutputBuffer
&OB
) const override
{
1604 ScopedOverride
<bool> SavePrinting(Printing
, true);
1605 return Ref
->getSyntaxNode(OB
);
1608 void printLeft(OutputBuffer
&OB
) const override
{
1611 ScopedOverride
<bool> SavePrinting(Printing
, true);
1614 void printRight(OutputBuffer
&OB
) const override
{
1617 ScopedOverride
<bool> SavePrinting(Printing
, true);
1618 Ref
->printRight(OB
);
1622 struct NameWithTemplateArgs
: Node
{
1623 // name<template_args>
1627 NameWithTemplateArgs(Node
*Name_
, Node
*TemplateArgs_
)
1628 : Node(KNameWithTemplateArgs
), Name(Name_
), TemplateArgs(TemplateArgs_
) {}
1630 template<typename Fn
> void match(Fn F
) const { F(Name
, TemplateArgs
); }
1632 std::string_view
getBaseName() const override
{ return Name
->getBaseName(); }
1634 void printLeft(OutputBuffer
&OB
) const override
{
1636 TemplateArgs
->print(OB
);
1640 class GlobalQualifiedName final
: public Node
{
1644 GlobalQualifiedName(Node
* Child_
)
1645 : Node(KGlobalQualifiedName
), Child(Child_
) {}
1647 template<typename Fn
> void match(Fn F
) const { F(Child
); }
1649 std::string_view
getBaseName() const override
{ return Child
->getBaseName(); }
1651 void printLeft(OutputBuffer
&OB
) const override
{
1657 enum class SpecialSubKind
{
1666 class SpecialSubstitution
;
1667 class ExpandedSpecialSubstitution
: public Node
{
1671 ExpandedSpecialSubstitution(SpecialSubKind SSK_
, Kind K_
)
1672 : Node(K_
), SSK(SSK_
) {}
1674 ExpandedSpecialSubstitution(SpecialSubKind SSK_
)
1675 : ExpandedSpecialSubstitution(SSK_
, KExpandedSpecialSubstitution
) {}
1676 inline ExpandedSpecialSubstitution(SpecialSubstitution
const *);
1678 template<typename Fn
> void match(Fn F
) const { F(SSK
); }
1681 bool isInstantiation() const {
1682 return unsigned(SSK
) >= unsigned(SpecialSubKind::string
);
1685 std::string_view
getBaseName() const override
{
1687 case SpecialSubKind::allocator
:
1688 return {"allocator"};
1689 case SpecialSubKind::basic_string
:
1690 return {"basic_string"};
1691 case SpecialSubKind::string
:
1692 return {"basic_string"};
1693 case SpecialSubKind::istream
:
1694 return {"basic_istream"};
1695 case SpecialSubKind::ostream
:
1696 return {"basic_ostream"};
1697 case SpecialSubKind::iostream
:
1698 return {"basic_iostream"};
1700 DEMANGLE_UNREACHABLE
;
1704 void printLeft(OutputBuffer
&OB
) const override
{
1705 OB
<< "std::" << getBaseName();
1706 if (isInstantiation()) {
1707 OB
<< "<char, std::char_traits<char>";
1708 if (SSK
== SpecialSubKind::string
)
1709 OB
<< ", std::allocator<char>";
1715 class SpecialSubstitution final
: public ExpandedSpecialSubstitution
{
1717 SpecialSubstitution(SpecialSubKind SSK_
)
1718 : ExpandedSpecialSubstitution(SSK_
, KSpecialSubstitution
) {}
1720 template<typename Fn
> void match(Fn F
) const { F(SSK
); }
1722 std::string_view
getBaseName() const override
{
1723 std::string_view SV
= ExpandedSpecialSubstitution::getBaseName();
1724 if (isInstantiation()) {
1725 // The instantiations are typedefs that drop the "basic_" prefix.
1726 DEMANGLE_ASSERT(starts_with(SV
, "basic_"), "");
1727 SV
.remove_prefix(sizeof("basic_") - 1);
1732 void printLeft(OutputBuffer
&OB
) const override
{
1733 OB
<< "std::" << getBaseName();
1737 inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(
1738 SpecialSubstitution
const *SS
)
1739 : ExpandedSpecialSubstitution(SS
->SSK
) {}
1741 class CtorDtorName final
: public Node
{
1742 const Node
*Basename
;
1747 CtorDtorName(const Node
*Basename_
, bool IsDtor_
, int Variant_
)
1748 : Node(KCtorDtorName
), Basename(Basename_
), IsDtor(IsDtor_
),
1749 Variant(Variant_
) {}
1751 template<typename Fn
> void match(Fn F
) const { F(Basename
, IsDtor
, Variant
); }
1753 void printLeft(OutputBuffer
&OB
) const override
{
1756 OB
+= Basename
->getBaseName();
1760 class DtorName
: public Node
{
1764 DtorName(const Node
*Base_
) : Node(KDtorName
), Base(Base_
) {}
1766 template<typename Fn
> void match(Fn F
) const { F(Base
); }
1768 void printLeft(OutputBuffer
&OB
) const override
{
1770 Base
->printLeft(OB
);
1774 class UnnamedTypeName
: public Node
{
1775 const std::string_view Count
;
1778 UnnamedTypeName(std::string_view Count_
)
1779 : Node(KUnnamedTypeName
), Count(Count_
) {}
1781 template<typename Fn
> void match(Fn F
) const { F(Count
); }
1783 void printLeft(OutputBuffer
&OB
) const override
{
1790 class ClosureTypeName
: public Node
{
1791 NodeArray TemplateParams
;
1792 const Node
*Requires1
;
1794 const Node
*Requires2
;
1795 std::string_view Count
;
1798 ClosureTypeName(NodeArray TemplateParams_
, const Node
*Requires1_
,
1799 NodeArray Params_
, const Node
*Requires2_
,
1800 std::string_view Count_
)
1801 : Node(KClosureTypeName
), TemplateParams(TemplateParams_
),
1802 Requires1(Requires1_
), Params(Params_
), Requires2(Requires2_
),
1805 template<typename Fn
> void match(Fn F
) const {
1806 F(TemplateParams
, Requires1
, Params
, Requires2
, Count
);
1809 void printDeclarator(OutputBuffer
&OB
) const {
1810 if (!TemplateParams
.empty()) {
1811 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
1813 TemplateParams
.printWithComma(OB
);
1816 if (Requires1
!= nullptr) {
1818 Requires1
->print(OB
);
1822 Params
.printWithComma(OB
);
1824 if (Requires2
!= nullptr) {
1826 Requires2
->print(OB
);
1830 void printLeft(OutputBuffer
&OB
) const override
{
1831 // FIXME: This demangling is not particularly readable.
1835 printDeclarator(OB
);
1839 class StructuredBindingName
: public Node
{
1842 StructuredBindingName(NodeArray Bindings_
)
1843 : Node(KStructuredBindingName
), Bindings(Bindings_
) {}
1845 template<typename Fn
> void match(Fn F
) const { F(Bindings
); }
1847 void printLeft(OutputBuffer
&OB
) const override
{
1849 Bindings
.printWithComma(OB
);
1854 // -- Expression Nodes --
1856 class BinaryExpr
: public Node
{
1858 const std::string_view InfixOperator
;
1862 BinaryExpr(const Node
*LHS_
, std::string_view InfixOperator_
,
1863 const Node
*RHS_
, Prec Prec_
)
1864 : Node(KBinaryExpr
, Prec_
), LHS(LHS_
), InfixOperator(InfixOperator_
),
1867 template <typename Fn
> void match(Fn F
) const {
1868 F(LHS
, InfixOperator
, RHS
, getPrecedence());
1871 void printLeft(OutputBuffer
&OB
) const override
{
1872 bool ParenAll
= OB
.isGtInsideTemplateArgs() &&
1873 (InfixOperator
== ">" || InfixOperator
== ">>");
1876 // Assignment is right associative, with special LHS precedence.
1877 bool IsAssign
= getPrecedence() == Prec::Assign
;
1878 LHS
->printAsOperand(OB
, IsAssign
? Prec::OrIf
: getPrecedence(), !IsAssign
);
1879 // No space before comma operator
1880 if (!(InfixOperator
== ","))
1882 OB
+= InfixOperator
;
1884 RHS
->printAsOperand(OB
, getPrecedence(), IsAssign
);
1890 class ArraySubscriptExpr
: public Node
{
1895 ArraySubscriptExpr(const Node
*Op1_
, const Node
*Op2_
, Prec Prec_
)
1896 : Node(KArraySubscriptExpr
, Prec_
), Op1(Op1_
), Op2(Op2_
) {}
1898 template <typename Fn
> void match(Fn F
) const {
1899 F(Op1
, Op2
, getPrecedence());
1902 void printLeft(OutputBuffer
&OB
) const override
{
1903 Op1
->printAsOperand(OB
, getPrecedence());
1905 Op2
->printAsOperand(OB
);
1910 class PostfixExpr
: public Node
{
1912 const std::string_view Operator
;
1915 PostfixExpr(const Node
*Child_
, std::string_view Operator_
, Prec Prec_
)
1916 : Node(KPostfixExpr
, Prec_
), Child(Child_
), Operator(Operator_
) {}
1918 template <typename Fn
> void match(Fn F
) const {
1919 F(Child
, Operator
, getPrecedence());
1922 void printLeft(OutputBuffer
&OB
) const override
{
1923 Child
->printAsOperand(OB
, getPrecedence(), true);
1928 class ConditionalExpr
: public Node
{
1934 ConditionalExpr(const Node
*Cond_
, const Node
*Then_
, const Node
*Else_
,
1936 : Node(KConditionalExpr
, Prec_
), Cond(Cond_
), Then(Then_
), Else(Else_
) {}
1938 template <typename Fn
> void match(Fn F
) const {
1939 F(Cond
, Then
, Else
, getPrecedence());
1942 void printLeft(OutputBuffer
&OB
) const override
{
1943 Cond
->printAsOperand(OB
, getPrecedence());
1945 Then
->printAsOperand(OB
);
1947 Else
->printAsOperand(OB
, Prec::Assign
, true);
1951 class MemberExpr
: public Node
{
1953 const std::string_view Kind
;
1957 MemberExpr(const Node
*LHS_
, std::string_view Kind_
, const Node
*RHS_
,
1959 : Node(KMemberExpr
, Prec_
), LHS(LHS_
), Kind(Kind_
), RHS(RHS_
) {}
1961 template <typename Fn
> void match(Fn F
) const {
1962 F(LHS
, Kind
, RHS
, getPrecedence());
1965 void printLeft(OutputBuffer
&OB
) const override
{
1966 LHS
->printAsOperand(OB
, getPrecedence(), true);
1968 RHS
->printAsOperand(OB
, getPrecedence(), false);
1972 class SubobjectExpr
: public Node
{
1974 const Node
*SubExpr
;
1975 std::string_view Offset
;
1976 NodeArray UnionSelectors
;
1980 SubobjectExpr(const Node
*Type_
, const Node
*SubExpr_
,
1981 std::string_view Offset_
, NodeArray UnionSelectors_
,
1982 bool OnePastTheEnd_
)
1983 : Node(KSubobjectExpr
), Type(Type_
), SubExpr(SubExpr_
), Offset(Offset_
),
1984 UnionSelectors(UnionSelectors_
), OnePastTheEnd(OnePastTheEnd_
) {}
1986 template<typename Fn
> void match(Fn F
) const {
1987 F(Type
, SubExpr
, Offset
, UnionSelectors
, OnePastTheEnd
);
1990 void printLeft(OutputBuffer
&OB
) const override
{
1994 OB
+= " at offset ";
1995 if (Offset
.empty()) {
1997 } else if (Offset
[0] == 'n') {
1999 OB
+= std::string_view(Offset
.data() + 1, Offset
.size() - 1);
2007 class EnclosingExpr
: public Node
{
2008 const std::string_view Prefix
;
2010 const std::string_view Postfix
;
2013 EnclosingExpr(std::string_view Prefix_
, const Node
*Infix_
,
2014 Prec Prec_
= Prec::Primary
)
2015 : Node(KEnclosingExpr
, Prec_
), Prefix(Prefix_
), Infix(Infix_
) {}
2017 template <typename Fn
> void match(Fn F
) const {
2018 F(Prefix
, Infix
, getPrecedence());
2021 void printLeft(OutputBuffer
&OB
) const override
{
2030 class CastExpr
: public Node
{
2031 // cast_kind<to>(from)
2032 const std::string_view CastKind
;
2037 CastExpr(std::string_view CastKind_
, const Node
*To_
, const Node
*From_
,
2039 : Node(KCastExpr
, Prec_
), CastKind(CastKind_
), To(To_
), From(From_
) {}
2041 template <typename Fn
> void match(Fn F
) const {
2042 F(CastKind
, To
, From
, getPrecedence());
2045 void printLeft(OutputBuffer
&OB
) const override
{
2048 ScopedOverride
<unsigned> LT(OB
.GtIsGt
, 0);
2054 From
->printAsOperand(OB
);
2059 class SizeofParamPackExpr
: public Node
{
2063 SizeofParamPackExpr(const Node
*Pack_
)
2064 : Node(KSizeofParamPackExpr
), Pack(Pack_
) {}
2066 template<typename Fn
> void match(Fn F
) const { F(Pack
); }
2068 void printLeft(OutputBuffer
&OB
) const override
{
2071 ParameterPackExpansion
PPE(Pack
);
2077 class CallExpr
: public Node
{
2080 bool IsParen
; // (func)(args ...) ?
2083 CallExpr(const Node
*Callee_
, NodeArray Args_
, bool IsParen_
, Prec Prec_
)
2084 : Node(KCallExpr
, Prec_
), Callee(Callee_
), Args(Args_
),
2085 IsParen(IsParen_
) {}
2087 template <typename Fn
> void match(Fn F
) const {
2088 F(Callee
, Args
, IsParen
, getPrecedence());
2091 void printLeft(OutputBuffer
&OB
) const override
{
2098 Args
.printWithComma(OB
);
2103 class NewExpr
: public Node
{
2104 // new (expr_list) type(init_list)
2108 bool IsGlobal
; // ::operator new ?
2109 bool IsArray
; // new[] ?
2111 NewExpr(NodeArray ExprList_
, Node
*Type_
, NodeArray InitList_
, bool IsGlobal_
,
2112 bool IsArray_
, Prec Prec_
)
2113 : Node(KNewExpr
, Prec_
), ExprList(ExprList_
), Type(Type_
),
2114 InitList(InitList_
), IsGlobal(IsGlobal_
), IsArray(IsArray_
) {}
2116 template<typename Fn
> void match(Fn F
) const {
2117 F(ExprList
, Type
, InitList
, IsGlobal
, IsArray
, getPrecedence());
2120 void printLeft(OutputBuffer
&OB
) const override
{
2126 if (!ExprList
.empty()) {
2128 ExprList
.printWithComma(OB
);
2133 if (!InitList
.empty()) {
2135 InitList
.printWithComma(OB
);
2141 class DeleteExpr
: public Node
{
2147 DeleteExpr(Node
*Op_
, bool IsGlobal_
, bool IsArray_
, Prec Prec_
)
2148 : Node(KDeleteExpr
, Prec_
), Op(Op_
), IsGlobal(IsGlobal_
),
2149 IsArray(IsArray_
) {}
2151 template <typename Fn
> void match(Fn F
) const {
2152 F(Op
, IsGlobal
, IsArray
, getPrecedence());
2155 void printLeft(OutputBuffer
&OB
) const override
{
2166 class PrefixExpr
: public Node
{
2167 std::string_view Prefix
;
2171 PrefixExpr(std::string_view Prefix_
, Node
*Child_
, Prec Prec_
)
2172 : Node(KPrefixExpr
, Prec_
), Prefix(Prefix_
), Child(Child_
) {}
2174 template <typename Fn
> void match(Fn F
) const {
2175 F(Prefix
, Child
, getPrecedence());
2178 void printLeft(OutputBuffer
&OB
) const override
{
2180 Child
->printAsOperand(OB
, getPrecedence());
2184 class FunctionParam
: public Node
{
2185 std::string_view Number
;
2188 FunctionParam(std::string_view Number_
)
2189 : Node(KFunctionParam
), Number(Number_
) {}
2191 template<typename Fn
> void match(Fn F
) const { F(Number
); }
2193 void printLeft(OutputBuffer
&OB
) const override
{
2199 class ConversionExpr
: public Node
{
2201 NodeArray Expressions
;
2204 ConversionExpr(const Node
*Type_
, NodeArray Expressions_
, Prec Prec_
)
2205 : Node(KConversionExpr
, Prec_
), Type(Type_
), Expressions(Expressions_
) {}
2207 template <typename Fn
> void match(Fn F
) const {
2208 F(Type
, Expressions
, getPrecedence());
2211 void printLeft(OutputBuffer
&OB
) const override
{
2216 Expressions
.printWithComma(OB
);
2221 class PointerToMemberConversionExpr
: public Node
{
2223 const Node
*SubExpr
;
2224 std::string_view Offset
;
2227 PointerToMemberConversionExpr(const Node
*Type_
, const Node
*SubExpr_
,
2228 std::string_view Offset_
, Prec Prec_
)
2229 : Node(KPointerToMemberConversionExpr
, Prec_
), Type(Type_
),
2230 SubExpr(SubExpr_
), Offset(Offset_
) {}
2232 template <typename Fn
> void match(Fn F
) const {
2233 F(Type
, SubExpr
, Offset
, getPrecedence());
2236 void printLeft(OutputBuffer
&OB
) const override
{
2246 class InitListExpr
: public Node
{
2250 InitListExpr(const Node
*Ty_
, NodeArray Inits_
)
2251 : Node(KInitListExpr
), Ty(Ty_
), Inits(Inits_
) {}
2253 template<typename Fn
> void match(Fn F
) const { F(Ty
, Inits
); }
2255 void printLeft(OutputBuffer
&OB
) const override
{
2257 if (Ty
->printInitListAsType(OB
, Inits
))
2262 Inits
.printWithComma(OB
);
2267 class BracedExpr
: public Node
{
2272 BracedExpr(const Node
*Elem_
, const Node
*Init_
, bool IsArray_
)
2273 : Node(KBracedExpr
), Elem(Elem_
), Init(Init_
), IsArray(IsArray_
) {}
2275 template<typename Fn
> void match(Fn F
) const { F(Elem
, Init
, IsArray
); }
2277 void printLeft(OutputBuffer
&OB
) const override
{
2286 if (Init
->getKind() != KBracedExpr
&& Init
->getKind() != KBracedRangeExpr
)
2292 class BracedRangeExpr
: public Node
{
2297 BracedRangeExpr(const Node
*First_
, const Node
*Last_
, const Node
*Init_
)
2298 : Node(KBracedRangeExpr
), First(First_
), Last(Last_
), Init(Init_
) {}
2300 template<typename Fn
> void match(Fn F
) const { F(First
, Last
, Init
); }
2302 void printLeft(OutputBuffer
&OB
) const override
{
2308 if (Init
->getKind() != KBracedExpr
&& Init
->getKind() != KBracedRangeExpr
)
2314 class FoldExpr
: public Node
{
2315 const Node
*Pack
, *Init
;
2316 std::string_view OperatorName
;
2320 FoldExpr(bool IsLeftFold_
, std::string_view OperatorName_
, const Node
*Pack_
,
2322 : Node(KFoldExpr
), Pack(Pack_
), Init(Init_
), OperatorName(OperatorName_
),
2323 IsLeftFold(IsLeftFold_
) {}
2325 template<typename Fn
> void match(Fn F
) const {
2326 F(IsLeftFold
, OperatorName
, Pack
, Init
);
2329 void printLeft(OutputBuffer
&OB
) const override
{
2330 auto PrintPack
= [&] {
2332 ParameterPackExpansion(Pack
).print(OB
);
2337 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2338 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2339 // Fold expr operands are cast-expressions
2340 if (!IsLeftFold
|| Init
!= nullptr) {
2341 // '(init|pack) op '
2343 Init
->printAsOperand(OB
, Prec::Cast
, true);
2346 OB
<< " " << OperatorName
<< " ";
2349 if (IsLeftFold
|| Init
!= nullptr) {
2350 // ' op (init|pack)'
2351 OB
<< " " << OperatorName
<< " ";
2355 Init
->printAsOperand(OB
, Prec::Cast
, true);
2361 class ThrowExpr
: public Node
{
2365 ThrowExpr(const Node
*Op_
) : Node(KThrowExpr
), Op(Op_
) {}
2367 template<typename Fn
> void match(Fn F
) const { F(Op
); }
2369 void printLeft(OutputBuffer
&OB
) const override
{
2375 class BoolExpr
: public Node
{
2379 BoolExpr(bool Value_
) : Node(KBoolExpr
), Value(Value_
) {}
2381 template<typename Fn
> void match(Fn F
) const { F(Value
); }
2383 void printLeft(OutputBuffer
&OB
) const override
{
2384 OB
+= Value
? std::string_view("true") : std::string_view("false");
2388 class StringLiteral
: public Node
{
2392 StringLiteral(const Node
*Type_
) : Node(KStringLiteral
), Type(Type_
) {}
2394 template<typename Fn
> void match(Fn F
) const { F(Type
); }
2396 void printLeft(OutputBuffer
&OB
) const override
{
2403 class LambdaExpr
: public Node
{
2407 LambdaExpr(const Node
*Type_
) : Node(KLambdaExpr
), Type(Type_
) {}
2409 template<typename Fn
> void match(Fn F
) const { F(Type
); }
2411 void printLeft(OutputBuffer
&OB
) const override
{
2413 if (Type
->getKind() == KClosureTypeName
)
2414 static_cast<const ClosureTypeName
*>(Type
)->printDeclarator(OB
);
2419 class EnumLiteral
: public Node
{
2422 std::string_view Integer
;
2425 EnumLiteral(const Node
*Ty_
, std::string_view Integer_
)
2426 : Node(KEnumLiteral
), Ty(Ty_
), Integer(Integer_
) {}
2428 template<typename Fn
> void match(Fn F
) const { F(Ty
, Integer
); }
2430 void printLeft(OutputBuffer
&OB
) const override
{
2435 if (Integer
[0] == 'n')
2436 OB
<< '-' << std::string_view(Integer
.data() + 1, Integer
.size() - 1);
2442 class IntegerLiteral
: public Node
{
2443 std::string_view Type
;
2444 std::string_view Value
;
2447 IntegerLiteral(std::string_view Type_
, std::string_view Value_
)
2448 : Node(KIntegerLiteral
), Type(Type_
), Value(Value_
) {}
2450 template<typename Fn
> void match(Fn F
) const { F(Type
, Value
); }
2452 void printLeft(OutputBuffer
&OB
) const override
{
2453 if (Type
.size() > 3) {
2459 if (Value
[0] == 'n')
2460 OB
<< '-' << std::string_view(Value
.data() + 1, Value
.size() - 1);
2464 if (Type
.size() <= 3)
2468 std::string_view
value() const { return Value
; }
2471 class RequiresExpr
: public Node
{
2472 NodeArray Parameters
;
2473 NodeArray Requirements
;
2475 RequiresExpr(NodeArray Parameters_
, NodeArray Requirements_
)
2476 : Node(KRequiresExpr
), Parameters(Parameters_
),
2477 Requirements(Requirements_
) {}
2479 template<typename Fn
> void match(Fn F
) const { F(Parameters
, Requirements
); }
2481 void printLeft(OutputBuffer
&OB
) const override
{
2483 if (!Parameters
.empty()) {
2486 Parameters
.printWithComma(OB
);
2491 for (const Node
*Req
: Requirements
) {
2499 class ExprRequirement
: public Node
{
2502 const Node
*TypeConstraint
;
2504 ExprRequirement(const Node
*Expr_
, bool IsNoexcept_
,
2505 const Node
*TypeConstraint_
)
2506 : Node(KExprRequirement
), Expr(Expr_
), IsNoexcept(IsNoexcept_
),
2507 TypeConstraint(TypeConstraint_
) {}
2509 template <typename Fn
> void match(Fn F
) const {
2510 F(Expr
, IsNoexcept
, TypeConstraint
);
2513 void printLeft(OutputBuffer
&OB
) const override
{
2515 if (IsNoexcept
|| TypeConstraint
)
2518 if (IsNoexcept
|| TypeConstraint
)
2522 if (TypeConstraint
) {
2524 TypeConstraint
->print(OB
);
2530 class TypeRequirement
: public Node
{
2533 TypeRequirement(const Node
*Type_
)
2534 : Node(KTypeRequirement
), Type(Type_
) {}
2536 template <typename Fn
> void match(Fn F
) const { F(Type
); }
2538 void printLeft(OutputBuffer
&OB
) const override
{
2545 class NestedRequirement
: public Node
{
2546 const Node
*Constraint
;
2548 NestedRequirement(const Node
*Constraint_
)
2549 : Node(KNestedRequirement
), Constraint(Constraint_
) {}
2551 template <typename Fn
> void match(Fn F
) const { F(Constraint
); }
2553 void printLeft(OutputBuffer
&OB
) const override
{
2555 Constraint
->print(OB
);
2560 template <class Float
> struct FloatData
;
2562 namespace float_literal_impl
{
2563 constexpr Node::Kind
getFloatLiteralKind(float *) {
2564 return Node::KFloatLiteral
;
2566 constexpr Node::Kind
getFloatLiteralKind(double *) {
2567 return Node::KDoubleLiteral
;
2569 constexpr Node::Kind
getFloatLiteralKind(long double *) {
2570 return Node::KLongDoubleLiteral
;
2574 template <class Float
> class FloatLiteralImpl
: public Node
{
2575 const std::string_view Contents
;
2577 static constexpr Kind KindForClass
=
2578 float_literal_impl::getFloatLiteralKind((Float
*)nullptr);
2581 FloatLiteralImpl(std::string_view Contents_
)
2582 : Node(KindForClass
), Contents(Contents_
) {}
2584 template<typename Fn
> void match(Fn F
) const { F(Contents
); }
2586 void printLeft(OutputBuffer
&OB
) const override
{
2587 const size_t N
= FloatData
<Float
>::mangled_size
;
2588 if (Contents
.size() >= N
) {
2591 char buf
[sizeof(Float
)];
2593 const char *t
= Contents
.data();
2594 const char *last
= t
+ N
;
2596 for (; t
!= last
; ++t
, ++e
) {
2597 unsigned d1
= isdigit(*t
) ? static_cast<unsigned>(*t
- '0')
2598 : static_cast<unsigned>(*t
- 'a' + 10);
2600 unsigned d0
= isdigit(*t
) ? static_cast<unsigned>(*t
- '0')
2601 : static_cast<unsigned>(*t
- 'a' + 10);
2602 *e
= static_cast<char>((d1
<< 4) + d0
);
2604 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2605 std::reverse(buf
, e
);
2607 char num
[FloatData
<Float
>::max_demangled_size
] = {0};
2608 int n
= snprintf(num
, sizeof(num
), FloatData
<Float
>::spec
, value
);
2609 OB
+= std::string_view(num
, n
);
2614 using FloatLiteral
= FloatLiteralImpl
<float>;
2615 using DoubleLiteral
= FloatLiteralImpl
<double>;
2616 using LongDoubleLiteral
= FloatLiteralImpl
<long double>;
2618 /// Visit the node. Calls \c F(P), where \c P is the node cast to the
2619 /// appropriate derived class.
2620 template<typename Fn
>
2621 void Node::visit(Fn F
) const {
2625 return F(static_cast<const X *>(this));
2626 #include "ItaniumNodes.def"
2628 DEMANGLE_ASSERT(0, "unknown mangling node kind");
2631 /// Determine the kind of a node from its type.
2632 template<typename NodeT
> struct NodeKind
;
2634 template <> struct NodeKind<X> { \
2635 static constexpr Node::Kind Kind = Node::K##X; \
2636 static constexpr const char *name() { return #X; } \
2638 #include "ItaniumNodes.def"
2640 inline bool NodeArray::printAsString(OutputBuffer
&OB
) const {
2641 auto StartPos
= OB
.getCurrentPosition();
2642 auto Fail
= [&OB
, StartPos
] {
2643 OB
.setCurrentPosition(StartPos
);
2648 bool LastWasNumericEscape
= false;
2649 for (const Node
*Element
: *this) {
2650 if (Element
->getKind() != Node::KIntegerLiteral
)
2652 int integer_value
= 0;
2653 for (char c
: static_cast<const IntegerLiteral
*>(Element
)->value()) {
2654 if (c
< '0' || c
> '9' || integer_value
> 25)
2656 integer_value
*= 10;
2657 integer_value
+= c
- '0';
2659 if (integer_value
> 255)
2662 // Insert a `""` to avoid accidentally extending a numeric escape.
2663 if (LastWasNumericEscape
) {
2664 if ((integer_value
>= '0' && integer_value
<= '9') ||
2665 (integer_value
>= 'a' && integer_value
<= 'f') ||
2666 (integer_value
>= 'A' && integer_value
<= 'F')) {
2671 LastWasNumericEscape
= false;
2673 // Determine how to print this character.
2674 switch (integer_value
) {
2705 // We assume that the character is ASCII, and use a numeric escape for all
2706 // remaining non-printable ASCII characters.
2707 if (integer_value
< 32 || integer_value
== 127) {
2708 constexpr char Hex
[] = "0123456789ABCDEF";
2710 if (integer_value
> 7)
2712 if (integer_value
>= 16)
2713 OB
+= Hex
[integer_value
>> 4];
2714 OB
+= Hex
[integer_value
& 0xF];
2715 LastWasNumericEscape
= true;
2719 // Assume all remaining characters are directly printable.
2720 OB
+= (char)integer_value
;
2728 template <typename Derived
, typename Alloc
> struct AbstractManglingParser
{
2732 // Name stack, this is used by the parser to hold temporary names that were
2733 // parsed. The parser collapses multiple names into new nodes to construct
2734 // the AST. Once the parser is finished, names.size() == 1.
2735 PODSmallVector
<Node
*, 32> Names
;
2737 // Substitution table. Itanium supports name substitutions as a means of
2738 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2740 PODSmallVector
<Node
*, 32> Subs
;
2742 // A list of template argument values corresponding to a template parameter
2744 using TemplateParamList
= PODSmallVector
<Node
*, 8>;
2746 class ScopedTemplateParamList
{
2747 AbstractManglingParser
*Parser
;
2748 size_t OldNumTemplateParamLists
;
2749 TemplateParamList Params
;
2752 ScopedTemplateParamList(AbstractManglingParser
*TheParser
)
2753 : Parser(TheParser
),
2754 OldNumTemplateParamLists(TheParser
->TemplateParams
.size()) {
2755 Parser
->TemplateParams
.push_back(&Params
);
2757 ~ScopedTemplateParamList() {
2758 DEMANGLE_ASSERT(Parser
->TemplateParams
.size() >= OldNumTemplateParamLists
,
2760 Parser
->TemplateParams
.shrinkToSize(OldNumTemplateParamLists
);
2762 TemplateParamList
*params() { return &Params
; }
2765 // Template parameter table. Like the above, but referenced like "T42_".
2766 // This has a smaller size compared to Subs and Names because it can be
2767 // stored on the stack.
2768 TemplateParamList OuterTemplateParams
;
2770 // Lists of template parameters indexed by template parameter depth,
2771 // referenced like "TL2_4_". If nonempty, element 0 is always
2772 // OuterTemplateParams; inner elements are always template parameter lists of
2773 // lambda expressions. For a generic lambda with no explicit template
2774 // parameter list, the corresponding parameter list pointer will be null.
2775 PODSmallVector
<TemplateParamList
*, 4> TemplateParams
;
2777 class SaveTemplateParams
{
2778 AbstractManglingParser
*Parser
;
2779 decltype(TemplateParams
) OldParams
;
2780 decltype(OuterTemplateParams
) OldOuterParams
;
2783 SaveTemplateParams(AbstractManglingParser
*TheParser
) : Parser(TheParser
) {
2784 OldParams
= std::move(Parser
->TemplateParams
);
2785 OldOuterParams
= std::move(Parser
->OuterTemplateParams
);
2786 Parser
->TemplateParams
.clear();
2787 Parser
->OuterTemplateParams
.clear();
2789 ~SaveTemplateParams() {
2790 Parser
->TemplateParams
= std::move(OldParams
);
2791 Parser
->OuterTemplateParams
= std::move(OldOuterParams
);
2795 // Set of unresolved forward <template-param> references. These can occur in a
2796 // conversion operator's type, and are resolved in the enclosing <encoding>.
2797 PODSmallVector
<ForwardTemplateReference
*, 4> ForwardTemplateRefs
;
2799 bool TryToParseTemplateArgs
= true;
2800 bool PermitForwardTemplateReferences
= false;
2801 bool HasIncompleteTemplateParameterTracking
= false;
2802 size_t ParsingLambdaParamsAtLevel
= (size_t)-1;
2804 unsigned NumSyntheticTemplateParameters
[3] = {};
2808 AbstractManglingParser(const char *First_
, const char *Last_
)
2809 : First(First_
), Last(Last_
) {}
2811 Derived
&getDerived() { return static_cast<Derived
&>(*this); }
2813 void reset(const char *First_
, const char *Last_
) {
2818 TemplateParams
.clear();
2819 ParsingLambdaParamsAtLevel
= (size_t)-1;
2820 TryToParseTemplateArgs
= true;
2821 PermitForwardTemplateReferences
= false;
2822 for (int I
= 0; I
!= 3; ++I
)
2823 NumSyntheticTemplateParameters
[I
] = 0;
2824 ASTAllocator
.reset();
2827 template <class T
, class... Args
> Node
*make(Args
&&... args
) {
2828 return ASTAllocator
.template makeNode
<T
>(std::forward
<Args
>(args
)...);
2831 template <class It
> NodeArray
makeNodeArray(It begin
, It end
) {
2832 size_t sz
= static_cast<size_t>(end
- begin
);
2833 void *mem
= ASTAllocator
.allocateNodeArray(sz
);
2834 Node
**data
= new (mem
) Node
*[sz
];
2835 std::copy(begin
, end
, data
);
2836 return NodeArray(data
, sz
);
2839 NodeArray
popTrailingNodeArray(size_t FromPosition
) {
2840 DEMANGLE_ASSERT(FromPosition
<= Names
.size(), "");
2842 makeNodeArray(Names
.begin() + (long)FromPosition
, Names
.end());
2843 Names
.shrinkToSize(FromPosition
);
2847 bool consumeIf(std::string_view S
) {
2848 if (starts_with(std::string_view(First
, Last
- First
), S
)) {
2855 bool consumeIf(char C
) {
2856 if (First
!= Last
&& *First
== C
) {
2863 char consume() { return First
!= Last
? *First
++ : '\0'; }
2865 char look(unsigned Lookahead
= 0) const {
2866 if (static_cast<size_t>(Last
- First
) <= Lookahead
)
2868 return First
[Lookahead
];
2871 size_t numLeft() const { return static_cast<size_t>(Last
- First
); }
2873 std::string_view
parseNumber(bool AllowNegative
= false);
2874 Qualifiers
parseCVQualifiers();
2875 bool parsePositiveInteger(size_t *Out
);
2876 std::string_view
parseBareSourceName();
2878 bool parseSeqId(size_t *Out
);
2879 Node
*parseSubstitution();
2880 Node
*parseTemplateParam();
2881 Node
*parseTemplateParamDecl(TemplateParamList
*Params
);
2882 Node
*parseTemplateArgs(bool TagTemplates
= false);
2883 Node
*parseTemplateArg();
2885 bool isTemplateParamDecl() {
2886 return look() == 'T' &&
2887 std::string_view("yptnk").find(look(1)) != std::string_view::npos
;
2890 /// Parse the <expression> production.
2892 Node
*parsePrefixExpr(std::string_view Kind
, Node::Prec Prec
);
2893 Node
*parseBinaryExpr(std::string_view Kind
, Node::Prec Prec
);
2894 Node
*parseIntegerLiteral(std::string_view Lit
);
2895 Node
*parseExprPrimary();
2896 template <class Float
> Node
*parseFloatingLiteral();
2897 Node
*parseFunctionParam();
2898 Node
*parseConversionExpr();
2899 Node
*parseBracedExpr();
2900 Node
*parseFoldExpr();
2901 Node
*parsePointerToMemberConversionExpr(Node::Prec Prec
);
2902 Node
*parseSubobjectExpr();
2903 Node
*parseConstraintExpr();
2904 Node
*parseRequiresExpr();
2906 /// Parse the <type> production.
2908 Node
*parseFunctionType();
2909 Node
*parseVectorType();
2910 Node
*parseDecltype();
2911 Node
*parseArrayType();
2912 Node
*parsePointerToMemberType();
2913 Node
*parseClassEnumType();
2914 Node
*parseQualifiedType();
2916 Node
*parseEncoding(bool ParseParams
= true);
2917 bool parseCallOffset();
2918 Node
*parseSpecialName();
2920 /// Holds some extra information about a <name> that is being parsed. This
2921 /// information is only pertinent if the <name> refers to an <encoding>.
2923 bool CtorDtorConversion
= false;
2924 bool EndsWithTemplateArgs
= false;
2925 Qualifiers CVQualifiers
= QualNone
;
2926 FunctionRefQual ReferenceQualifier
= FrefQualNone
;
2927 size_t ForwardTemplateRefsBegin
;
2928 bool HasExplicitObjectParameter
= false;
2930 NameState(AbstractManglingParser
*Enclosing
)
2931 : ForwardTemplateRefsBegin(Enclosing
->ForwardTemplateRefs
.size()) {}
2934 bool resolveForwardTemplateRefs(NameState
&State
) {
2935 size_t I
= State
.ForwardTemplateRefsBegin
;
2936 size_t E
= ForwardTemplateRefs
.size();
2937 for (; I
< E
; ++I
) {
2938 size_t Idx
= ForwardTemplateRefs
[I
]->Index
;
2939 if (TemplateParams
.empty() || !TemplateParams
[0] ||
2940 Idx
>= TemplateParams
[0]->size())
2942 ForwardTemplateRefs
[I
]->Ref
= (*TemplateParams
[0])[Idx
];
2944 ForwardTemplateRefs
.shrinkToSize(State
.ForwardTemplateRefsBegin
);
2948 /// Parse the <name> production>
2949 Node
*parseName(NameState
*State
= nullptr);
2950 Node
*parseLocalName(NameState
*State
);
2951 Node
*parseOperatorName(NameState
*State
);
2952 bool parseModuleNameOpt(ModuleName
*&Module
);
2953 Node
*parseUnqualifiedName(NameState
*State
, Node
*Scope
, ModuleName
*Module
);
2954 Node
*parseUnnamedTypeName(NameState
*State
);
2955 Node
*parseSourceName(NameState
*State
);
2956 Node
*parseUnscopedName(NameState
*State
, bool *isSubstName
);
2957 Node
*parseNestedName(NameState
*State
);
2958 Node
*parseCtorDtorName(Node
*&SoFar
, NameState
*State
);
2960 Node
*parseAbiTags(Node
*N
);
2962 struct OperatorInfo
{
2963 enum OIKind
: unsigned char {
2964 Prefix
, // Prefix unary: @ expr
2965 Postfix
, // Postfix unary: expr @
2966 Binary
, // Binary: lhs @ rhs
2967 Array
, // Array index: lhs [ rhs ]
2968 Member
, // Member access: lhs @ rhs
2971 Call
, // Function call: expr (expr*)
2972 CCast
, // C cast: (type)expr
2973 Conditional
, // Conditional: expr ? expr : expr
2974 NameOnly
, // Overload only, not allowed in expression.
2975 // Below do not have operator names
2976 NamedCast
, // Named cast, @<type>(expr)
2977 OfIdOp
, // alignof, sizeof, typeid
2979 Unnameable
= NamedCast
,
2981 char Enc
[2]; // Encoding
2982 OIKind Kind
; // Kind of operator
2983 bool Flag
: 1; // Entry-specific flag
2984 Node::Prec Prec
: 7; // Precedence
2985 const char *Name
; // Spelling
2988 constexpr OperatorInfo(const char (&E
)[3], OIKind K
, bool F
, Node::Prec P
,
2990 : Enc
{E
[0], E
[1]}, Kind
{K
}, Flag
{F
}, Prec
{P
}, Name
{N
} {}
2993 bool operator<(const OperatorInfo
&Other
) const {
2994 return *this < Other
.Enc
;
2996 bool operator<(const char *Peek
) const {
2997 return Enc
[0] < Peek
[0] || (Enc
[0] == Peek
[0] && Enc
[1] < Peek
[1]);
2999 bool operator==(const char *Peek
) const {
3000 return Enc
[0] == Peek
[0] && Enc
[1] == Peek
[1];
3002 bool operator!=(const char *Peek
) const { return !this->operator==(Peek
); }
3005 std::string_view
getSymbol() const {
3006 std::string_view Res
= Name
;
3007 if (Kind
< Unnameable
) {
3008 DEMANGLE_ASSERT(starts_with(Res
, "operator"),
3009 "operator name does not start with 'operator'");
3010 Res
.remove_prefix(sizeof("operator") - 1);
3011 if (starts_with(Res
, ' '))
3012 Res
.remove_prefix(1);
3016 std::string_view
getName() const { return Name
; }
3017 OIKind
getKind() const { return Kind
; }
3018 bool getFlag() const { return Flag
; }
3019 Node::Prec
getPrecedence() const { return Prec
; }
3021 static const OperatorInfo Ops
[];
3022 static const size_t NumOps
;
3023 const OperatorInfo
*parseOperatorEncoding();
3025 /// Parse the <unresolved-name> production.
3026 Node
*parseUnresolvedName(bool Global
);
3027 Node
*parseSimpleId();
3028 Node
*parseBaseUnresolvedName();
3029 Node
*parseUnresolvedType();
3030 Node
*parseDestructorName();
3032 /// Top-level entry point into the parser.
3033 Node
*parse(bool ParseParams
= true);
3036 const char* parse_discriminator(const char* first
, const char* last
);
3038 // <name> ::= <nested-name> // N
3039 // ::= <local-name> # See Scope Encoding below // Z
3040 // ::= <unscoped-template-name> <template-args>
3041 // ::= <unscoped-name>
3043 // <unscoped-template-name> ::= <unscoped-name>
3044 // ::= <substitution>
3045 template <typename Derived
, typename Alloc
>
3046 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseName(NameState
*State
) {
3048 return getDerived().parseNestedName(State
);
3050 return getDerived().parseLocalName(State
);
3052 Node
*Result
= nullptr;
3053 bool IsSubst
= false;
3055 Result
= getDerived().parseUnscopedName(State
, &IsSubst
);
3059 if (look() == 'I') {
3060 // ::= <unscoped-template-name> <template-args>
3062 // An unscoped-template-name is substitutable.
3063 Subs
.push_back(Result
);
3064 Node
*TA
= getDerived().parseTemplateArgs(State
!= nullptr);
3068 State
->EndsWithTemplateArgs
= true;
3069 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
3070 } else if (IsSubst
) {
3071 // The substitution case must be followed by <template-args>.
3078 // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
3079 // := Z <function encoding> E s [<discriminator>]
3080 // := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
3081 template <typename Derived
, typename Alloc
>
3082 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseLocalName(NameState
*State
) {
3083 if (!consumeIf('Z'))
3085 Node
*Encoding
= getDerived().parseEncoding();
3086 if (Encoding
== nullptr || !consumeIf('E'))
3089 if (consumeIf('s')) {
3090 First
= parse_discriminator(First
, Last
);
3091 auto *StringLitName
= make
<NameType
>("string literal");
3094 return make
<LocalName
>(Encoding
, StringLitName
);
3097 // The template parameters of the inner name are unrelated to those of the
3098 // enclosing context.
3099 SaveTemplateParams
SaveTemplateParamsScope(this);
3101 if (consumeIf('d')) {
3103 if (!consumeIf('_'))
3105 Node
*N
= getDerived().parseName(State
);
3108 return make
<LocalName
>(Encoding
, N
);
3111 Node
*Entity
= getDerived().parseName(State
);
3112 if (Entity
== nullptr)
3114 First
= parse_discriminator(First
, Last
);
3115 return make
<LocalName
>(Encoding
, Entity
);
3118 // <unscoped-name> ::= <unqualified-name>
3119 // ::= St <unqualified-name> # ::std::
3121 template <typename Derived
, typename Alloc
>
3123 AbstractManglingParser
<Derived
, Alloc
>::parseUnscopedName(NameState
*State
,
3126 Node
*Std
= nullptr;
3127 if (consumeIf("St")) {
3128 Std
= make
<NameType
>("std");
3133 Node
*Res
= nullptr;
3134 ModuleName
*Module
= nullptr;
3135 if (look() == 'S') {
3136 Node
*S
= getDerived().parseSubstitution();
3139 if (S
->getKind() == Node::KModuleName
)
3140 Module
= static_cast<ModuleName
*>(S
);
3141 else if (IsSubst
&& Std
== nullptr) {
3149 if (Res
== nullptr || Std
!= nullptr) {
3150 Res
= getDerived().parseUnqualifiedName(State
, Std
, Module
);
3156 // <unqualified-name> ::= [<module-name>] F? L? <operator-name> [<abi-tags>]
3157 // ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
3158 // ::= [<module-name>] F? L? <source-name> [<abi-tags>]
3159 // ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
3160 // # structured binding declaration
3161 // ::= [<module-name>] L? DC <source-name>+ E
3162 template <typename Derived
, typename Alloc
>
3163 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnqualifiedName(
3164 NameState
*State
, Node
*Scope
, ModuleName
*Module
) {
3165 if (getDerived().parseModuleNameOpt(Module
))
3168 bool IsMemberLikeFriend
= Scope
&& consumeIf('F');
3173 if (look() >= '1' && look() <= '9') {
3174 Result
= getDerived().parseSourceName(State
);
3175 } else if (look() == 'U') {
3176 Result
= getDerived().parseUnnamedTypeName(State
);
3177 } else if (consumeIf("DC")) {
3178 // Structured binding
3179 size_t BindingsBegin
= Names
.size();
3181 Node
*Binding
= getDerived().parseSourceName(State
);
3182 if (Binding
== nullptr)
3184 Names
.push_back(Binding
);
3185 } while (!consumeIf('E'));
3186 Result
= make
<StructuredBindingName
>(popTrailingNodeArray(BindingsBegin
));
3187 } else if (look() == 'C' || look() == 'D') {
3188 // A <ctor-dtor-name>.
3189 if (Scope
== nullptr || Module
!= nullptr)
3191 Result
= getDerived().parseCtorDtorName(Scope
, State
);
3193 Result
= getDerived().parseOperatorName(State
);
3196 if (Result
!= nullptr && Module
!= nullptr)
3197 Result
= make
<ModuleEntity
>(Module
, Result
);
3198 if (Result
!= nullptr)
3199 Result
= getDerived().parseAbiTags(Result
);
3200 if (Result
!= nullptr && IsMemberLikeFriend
)
3201 Result
= make
<MemberLikeFriendName
>(Scope
, Result
);
3202 else if (Result
!= nullptr && Scope
!= nullptr)
3203 Result
= make
<NestedName
>(Scope
, Result
);
3208 // <module-name> ::= <module-subname>
3209 // ::= <module-name> <module-subname>
3210 // ::= <substitution> # passed in by caller
3211 // <module-subname> ::= W <source-name>
3212 // ::= W P <source-name>
3213 template <typename Derived
, typename Alloc
>
3214 bool AbstractManglingParser
<Derived
, Alloc
>::parseModuleNameOpt(
3215 ModuleName
*&Module
) {
3216 while (consumeIf('W')) {
3217 bool IsPartition
= consumeIf('P');
3218 Node
*Sub
= getDerived().parseSourceName(nullptr);
3222 static_cast<ModuleName
*>(make
<ModuleName
>(Module
, Sub
, IsPartition
));
3223 Subs
.push_back(Module
);
3229 // <unnamed-type-name> ::= Ut [<nonnegative number>] _
3230 // ::= <closure-type-name>
3232 // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
3234 // <lambda-sig> ::= <template-param-decl>* [Q <requires-clause expression>]
3235 // <parameter type>+ # or "v" if the lambda has no parameters
3236 template <typename Derived
, typename Alloc
>
3238 AbstractManglingParser
<Derived
, Alloc
>::parseUnnamedTypeName(NameState
*State
) {
3239 // <template-params> refer to the innermost <template-args>. Clear out any
3240 // outer args that we may have inserted into TemplateParams.
3241 if (State
!= nullptr)
3242 TemplateParams
.clear();
3244 if (consumeIf("Ut")) {
3245 std::string_view Count
= parseNumber();
3246 if (!consumeIf('_'))
3248 return make
<UnnamedTypeName
>(Count
);
3250 if (consumeIf("Ul")) {
3251 ScopedOverride
<size_t> SwapParams(ParsingLambdaParamsAtLevel
,
3252 TemplateParams
.size());
3253 ScopedTemplateParamList
LambdaTemplateParams(this);
3255 size_t ParamsBegin
= Names
.size();
3256 while (getDerived().isTemplateParamDecl()) {
3258 getDerived().parseTemplateParamDecl(LambdaTemplateParams
.params());
3263 NodeArray TempParams
= popTrailingNodeArray(ParamsBegin
);
3265 // FIXME: If TempParams is empty and none of the function parameters
3266 // includes 'auto', we should remove LambdaTemplateParams from the
3267 // TemplateParams list. Unfortunately, we don't find out whether there are
3268 // any 'auto' parameters until too late in an example such as:
3270 // template<typename T> void f(
3271 // decltype([](decltype([]<typename T>(T v) {}),
3273 // template<typename T> void f(
3274 // decltype([](decltype([]<typename T>(T w) {}),
3277 // Here, the type of v is at level 2 but the type of w is at level 1. We
3278 // don't find this out until we encounter the type of the next parameter.
3280 // However, compilers can't actually cope with the former example in
3281 // practice, and it's likely to be made ill-formed in future, so we don't
3282 // need to support it here.
3284 // If we encounter an 'auto' in the function parameter types, we will
3285 // recreate a template parameter scope for it, but any intervening lambdas
3286 // will be parsed in the 'wrong' template parameter depth.
3287 if (TempParams
.empty())
3288 TemplateParams
.pop_back();
3290 Node
*Requires1
= nullptr;
3291 if (consumeIf('Q')) {
3292 Requires1
= getDerived().parseConstraintExpr();
3293 if (Requires1
== nullptr)
3297 if (!consumeIf("v")) {
3299 Node
*P
= getDerived().parseType();
3303 } while (look() != 'E' && look() != 'Q');
3305 NodeArray Params
= popTrailingNodeArray(ParamsBegin
);
3307 Node
*Requires2
= nullptr;
3308 if (consumeIf('Q')) {
3309 Requires2
= getDerived().parseConstraintExpr();
3310 if (Requires2
== nullptr)
3314 if (!consumeIf('E'))
3317 std::string_view Count
= parseNumber();
3318 if (!consumeIf('_'))
3320 return make
<ClosureTypeName
>(TempParams
, Requires1
, Params
, Requires2
,
3323 if (consumeIf("Ub")) {
3324 (void)parseNumber();
3325 if (!consumeIf('_'))
3327 return make
<NameType
>("'block-literal'");
3332 // <source-name> ::= <positive length number> <identifier>
3333 template <typename Derived
, typename Alloc
>
3334 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSourceName(NameState
*) {
3336 if (parsePositiveInteger(&Length
))
3338 if (numLeft() < Length
|| Length
== 0)
3340 std::string_view
Name(First
, Length
);
3342 if (starts_with(Name
, "_GLOBAL__N"))
3343 return make
<NameType
>("(anonymous namespace)");
3344 return make
<NameType
>(Name
);
3347 // Operator encodings
3348 template <typename Derived
, typename Alloc
>
3349 const typename AbstractManglingParser
<
3350 Derived
, Alloc
>::OperatorInfo AbstractManglingParser
<Derived
,
3352 // Keep ordered by encoding
3353 {"aN", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator&="},
3354 {"aS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator="},
3355 {"aa", OperatorInfo::Binary
, false, Node::Prec::AndIf
, "operator&&"},
3356 {"ad", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator&"},
3357 {"an", OperatorInfo::Binary
, false, Node::Prec::And
, "operator&"},
3358 {"at", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Unary
, "alignof "},
3359 {"aw", OperatorInfo::NameOnly
, false, Node::Prec::Primary
,
3360 "operator co_await"},
3361 {"az", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Unary
, "alignof "},
3362 {"cc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "const_cast"},
3363 {"cl", OperatorInfo::Call
, /*Paren*/ false, Node::Prec::Postfix
,
3365 {"cm", OperatorInfo::Binary
, false, Node::Prec::Comma
, "operator,"},
3366 {"co", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator~"},
3367 {"cp", OperatorInfo::Call
, /*Paren*/ true, Node::Prec::Postfix
,
3369 {"cv", OperatorInfo::CCast
, false, Node::Prec::Cast
, "operator"}, // C Cast
3370 {"dV", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator/="},
3371 {"da", OperatorInfo::Del
, /*Ary*/ true, Node::Prec::Unary
,
3372 "operator delete[]"},
3373 {"dc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "dynamic_cast"},
3374 {"de", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator*"},
3375 {"dl", OperatorInfo::Del
, /*Ary*/ false, Node::Prec::Unary
,
3377 {"ds", OperatorInfo::Member
, /*Named*/ false, Node::Prec::PtrMem
,
3379 {"dt", OperatorInfo::Member
, /*Named*/ false, Node::Prec::Postfix
,
3381 {"dv", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator/"},
3382 {"eO", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator^="},
3383 {"eo", OperatorInfo::Binary
, false, Node::Prec::Xor
, "operator^"},
3384 {"eq", OperatorInfo::Binary
, false, Node::Prec::Equality
, "operator=="},
3385 {"ge", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator>="},
3386 {"gt", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator>"},
3387 {"ix", OperatorInfo::Array
, false, Node::Prec::Postfix
, "operator[]"},
3388 {"lS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator<<="},
3389 {"le", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator<="},
3390 {"ls", OperatorInfo::Binary
, false, Node::Prec::Shift
, "operator<<"},
3391 {"lt", OperatorInfo::Binary
, false, Node::Prec::Relational
, "operator<"},
3392 {"mI", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator-="},
3393 {"mL", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator*="},
3394 {"mi", OperatorInfo::Binary
, false, Node::Prec::Additive
, "operator-"},
3395 {"ml", OperatorInfo::Binary
, false, Node::Prec::Multiplicative
,
3397 {"mm", OperatorInfo::Postfix
, false, Node::Prec::Postfix
, "operator--"},
3398 {"na", OperatorInfo::New
, /*Ary*/ true, Node::Prec::Unary
,
3400 {"ne", OperatorInfo::Binary
, false, Node::Prec::Equality
, "operator!="},
3401 {"ng", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator-"},
3402 {"nt", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator!"},
3403 {"nw", OperatorInfo::New
, /*Ary*/ false, Node::Prec::Unary
, "operator new"},
3404 {"oR", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator|="},
3405 {"oo", OperatorInfo::Binary
, false, Node::Prec::OrIf
, "operator||"},
3406 {"or", OperatorInfo::Binary
, false, Node::Prec::Ior
, "operator|"},
3407 {"pL", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator+="},
3408 {"pl", OperatorInfo::Binary
, false, Node::Prec::Additive
, "operator+"},
3409 {"pm", OperatorInfo::Member
, /*Named*/ false, Node::Prec::PtrMem
,
3411 {"pp", OperatorInfo::Postfix
, false, Node::Prec::Postfix
, "operator++"},
3412 {"ps", OperatorInfo::Prefix
, false, Node::Prec::Unary
, "operator+"},
3413 {"pt", OperatorInfo::Member
, /*Named*/ true, Node::Prec::Postfix
,
3415 {"qu", OperatorInfo::Conditional
, false, Node::Prec::Conditional
,
3417 {"rM", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator%="},
3418 {"rS", OperatorInfo::Binary
, false, Node::Prec::Assign
, "operator>>="},
3419 {"rc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
,
3420 "reinterpret_cast"},
3421 {"rm", OperatorInfo::Binary
, false, Node::Prec::Multiplicative
,
3423 {"rs", OperatorInfo::Binary
, false, Node::Prec::Shift
, "operator>>"},
3424 {"sc", OperatorInfo::NamedCast
, false, Node::Prec::Postfix
, "static_cast"},
3425 {"ss", OperatorInfo::Binary
, false, Node::Prec::Spaceship
, "operator<=>"},
3426 {"st", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Unary
, "sizeof "},
3427 {"sz", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Unary
, "sizeof "},
3428 {"te", OperatorInfo::OfIdOp
, /*Type*/ false, Node::Prec::Postfix
,
3430 {"ti", OperatorInfo::OfIdOp
, /*Type*/ true, Node::Prec::Postfix
, "typeid "},
3432 template <typename Derived
, typename Alloc
>
3433 const size_t AbstractManglingParser
<Derived
, Alloc
>::NumOps
= sizeof(Ops
) /
3436 // If the next 2 chars are an operator encoding, consume them and return their
3437 // OperatorInfo. Otherwise return nullptr.
3438 template <typename Derived
, typename Alloc
>
3439 const typename AbstractManglingParser
<Derived
, Alloc
>::OperatorInfo
*
3440 AbstractManglingParser
<Derived
, Alloc
>::parseOperatorEncoding() {
3444 // We can't use lower_bound as that can link to symbols in the C++ library,
3445 // and this must remain independent of that.
3446 size_t lower
= 0u, upper
= NumOps
- 1; // Inclusive bounds.
3447 while (upper
!= lower
) {
3448 size_t middle
= (upper
+ lower
) / 2;
3449 if (Ops
[middle
] < First
)
3454 if (Ops
[lower
] != First
)
3461 // <operator-name> ::= See parseOperatorEncoding()
3462 // ::= li <source-name> # operator ""
3463 // ::= v <digit> <source-name> # vendor extended operator
3464 template <typename Derived
, typename Alloc
>
3466 AbstractManglingParser
<Derived
, Alloc
>::parseOperatorName(NameState
*State
) {
3467 if (const auto *Op
= parseOperatorEncoding()) {
3468 if (Op
->getKind() == OperatorInfo::CCast
) {
3469 // ::= cv <type> # (cast)
3470 ScopedOverride
<bool> SaveTemplate(TryToParseTemplateArgs
, false);
3471 // If we're parsing an encoding, State != nullptr and the conversion
3472 // operators' <type> could have a <template-param> that refers to some
3473 // <template-arg>s further ahead in the mangled name.
3474 ScopedOverride
<bool> SavePermit(PermitForwardTemplateReferences
,
3475 PermitForwardTemplateReferences
||
3477 Node
*Ty
= getDerived().parseType();
3480 if (State
) State
->CtorDtorConversion
= true;
3481 return make
<ConversionOperatorType
>(Ty
);
3484 if (Op
->getKind() >= OperatorInfo::Unnameable
)
3485 /* Not a nameable operator. */
3487 if (Op
->getKind() == OperatorInfo::Member
&& !Op
->getFlag())
3488 /* Not a nameable MemberExpr */
3491 return make
<NameType
>(Op
->getName());
3494 if (consumeIf("li")) {
3495 // ::= li <source-name> # operator ""
3496 Node
*SN
= getDerived().parseSourceName(State
);
3499 return make
<LiteralOperator
>(SN
);
3502 if (consumeIf('v')) {
3503 // ::= v <digit> <source-name> # vendor extended operator
3504 if (look() >= '0' && look() <= '9') {
3506 Node
*SN
= getDerived().parseSourceName(State
);
3509 return make
<ConversionOperatorType
>(SN
);
3517 // <ctor-dtor-name> ::= C1 # complete object constructor
3518 // ::= C2 # base object constructor
3519 // ::= C3 # complete object allocating constructor
3520 // extension ::= C4 # gcc old-style "[unified]" constructor
3521 // extension ::= C5 # the COMDAT used for ctors
3522 // ::= D0 # deleting destructor
3523 // ::= D1 # complete object destructor
3524 // ::= D2 # base object destructor
3525 // extension ::= D4 # gcc old-style "[unified]" destructor
3526 // extension ::= D5 # the COMDAT used for dtors
3527 template <typename Derived
, typename Alloc
>
3529 AbstractManglingParser
<Derived
, Alloc
>::parseCtorDtorName(Node
*&SoFar
,
3531 if (SoFar
->getKind() == Node::KSpecialSubstitution
) {
3532 // Expand the special substitution.
3533 SoFar
= make
<ExpandedSpecialSubstitution
>(
3534 static_cast<SpecialSubstitution
*>(SoFar
));
3539 if (consumeIf('C')) {
3540 bool IsInherited
= consumeIf('I');
3541 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3544 int Variant
= look() - '0';
3546 if (State
) State
->CtorDtorConversion
= true;
3548 if (getDerived().parseName(State
) == nullptr)
3551 return make
<CtorDtorName
>(SoFar
, /*IsDtor=*/false, Variant
);
3554 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3555 look(1) == '4' || look(1) == '5')) {
3556 int Variant
= look(1) - '0';
3558 if (State
) State
->CtorDtorConversion
= true;
3559 return make
<CtorDtorName
>(SoFar
, /*IsDtor=*/true, Variant
);
3565 // <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3566 // <unqualified-name> E
3567 // ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3568 // <template-args> E
3570 // <prefix> ::= <prefix> <unqualified-name>
3571 // ::= <template-prefix> <template-args>
3572 // ::= <template-param>
3575 // ::= <substitution>
3576 // ::= <prefix> <data-member-prefix>
3579 // <data-member-prefix> := <member source-name> [<template-args>] M
3581 // <template-prefix> ::= <prefix> <template unqualified-name>
3582 // ::= <template-param>
3583 // ::= <substitution>
3584 template <typename Derived
, typename Alloc
>
3586 AbstractManglingParser
<Derived
, Alloc
>::parseNestedName(NameState
*State
) {
3587 if (!consumeIf('N'))
3590 // 'H' specifies that the encoding that follows
3591 // has an explicit object parameter.
3592 if (!consumeIf('H')) {
3593 Qualifiers CVTmp
= parseCVQualifiers();
3595 State
->CVQualifiers
= CVTmp
;
3597 if (consumeIf('O')) {
3599 State
->ReferenceQualifier
= FrefQualRValue
;
3600 } else if (consumeIf('R')) {
3602 State
->ReferenceQualifier
= FrefQualLValue
;
3605 State
->ReferenceQualifier
= FrefQualNone
;
3608 State
->HasExplicitObjectParameter
= true;
3611 Node
*SoFar
= nullptr;
3612 while (!consumeIf('E')) {
3614 // Only set end-with-template on the case that does that.
3615 State
->EndsWithTemplateArgs
= false;
3617 if (look() == 'T') {
3618 // ::= <template-param>
3619 if (SoFar
!= nullptr)
3620 return nullptr; // Cannot have a prefix.
3621 SoFar
= getDerived().parseTemplateParam();
3622 } else if (look() == 'I') {
3623 // ::= <template-prefix> <template-args>
3624 if (SoFar
== nullptr)
3625 return nullptr; // Must have a prefix.
3626 Node
*TA
= getDerived().parseTemplateArgs(State
!= nullptr);
3629 if (SoFar
->getKind() == Node::KNameWithTemplateArgs
)
3630 // Semantically <template-args> <template-args> cannot be generated by a
3631 // C++ entity. There will always be [something like] a name between
3635 State
->EndsWithTemplateArgs
= true;
3636 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3637 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3639 if (SoFar
!= nullptr)
3640 return nullptr; // Cannot have a prefix.
3641 SoFar
= getDerived().parseDecltype();
3643 ModuleName
*Module
= nullptr;
3645 if (look() == 'S') {
3646 // ::= <substitution>
3648 if (look(1) == 't') {
3650 S
= make
<NameType
>("std");
3652 S
= getDerived().parseSubstitution();
3656 if (S
->getKind() == Node::KModuleName
) {
3657 Module
= static_cast<ModuleName
*>(S
);
3658 } else if (SoFar
!= nullptr) {
3659 return nullptr; // Cannot have a prefix.
3662 continue; // Do not push a new substitution.
3666 // ::= [<prefix>] <unqualified-name>
3667 SoFar
= getDerived().parseUnqualifiedName(State
, SoFar
, Module
);
3670 if (SoFar
== nullptr)
3672 Subs
.push_back(SoFar
);
3675 // <data-member-prefix> := <member source-name> [<template-args>] M
3679 if (SoFar
== nullptr || Subs
.empty())
3686 // <simple-id> ::= <source-name> [ <template-args> ]
3687 template <typename Derived
, typename Alloc
>
3688 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSimpleId() {
3689 Node
*SN
= getDerived().parseSourceName(/*NameState=*/nullptr);
3692 if (look() == 'I') {
3693 Node
*TA
= getDerived().parseTemplateArgs();
3696 return make
<NameWithTemplateArgs
>(SN
, TA
);
3701 // <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3702 // ::= <simple-id> # e.g., ~A<2*N>
3703 template <typename Derived
, typename Alloc
>
3704 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseDestructorName() {
3706 if (std::isdigit(look()))
3707 Result
= getDerived().parseSimpleId();
3709 Result
= getDerived().parseUnresolvedType();
3710 if (Result
== nullptr)
3712 return make
<DtorName
>(Result
);
3715 // <unresolved-type> ::= <template-param>
3717 // ::= <substitution>
3718 template <typename Derived
, typename Alloc
>
3719 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnresolvedType() {
3720 if (look() == 'T') {
3721 Node
*TP
= getDerived().parseTemplateParam();
3727 if (look() == 'D') {
3728 Node
*DT
= getDerived().parseDecltype();
3734 return getDerived().parseSubstitution();
3737 // <base-unresolved-name> ::= <simple-id> # unresolved name
3738 // extension ::= <operator-name> # unresolved operator-function-id
3739 // extension ::= <operator-name> <template-args> # unresolved operator template-id
3740 // ::= on <operator-name> # unresolved operator-function-id
3741 // ::= on <operator-name> <template-args> # unresolved operator template-id
3742 // ::= dn <destructor-name> # destructor or pseudo-destructor;
3743 // # e.g. ~X or ~X<N-1>
3744 template <typename Derived
, typename Alloc
>
3745 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseBaseUnresolvedName() {
3746 if (std::isdigit(look()))
3747 return getDerived().parseSimpleId();
3749 if (consumeIf("dn"))
3750 return getDerived().parseDestructorName();
3754 Node
*Oper
= getDerived().parseOperatorName(/*NameState=*/nullptr);
3755 if (Oper
== nullptr)
3757 if (look() == 'I') {
3758 Node
*TA
= getDerived().parseTemplateArgs();
3761 return make
<NameWithTemplateArgs
>(Oper
, TA
);
3766 // <unresolved-name>
3767 // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3768 // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3769 // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3770 // # A::x, N::y, A<T>::z; "gs" means leading "::"
3771 // [gs] has been parsed by caller.
3772 // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3773 // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3774 // # T::N::x /decltype(p)::N::x
3775 // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3777 // <unresolved-qualifier-level> ::= <simple-id>
3778 template <typename Derived
, typename Alloc
>
3779 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseUnresolvedName(bool Global
) {
3780 Node
*SoFar
= nullptr;
3782 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3783 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3784 if (consumeIf("srN")) {
3785 SoFar
= getDerived().parseUnresolvedType();
3786 if (SoFar
== nullptr)
3789 if (look() == 'I') {
3790 Node
*TA
= getDerived().parseTemplateArgs();
3793 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3798 while (!consumeIf('E')) {
3799 Node
*Qual
= getDerived().parseSimpleId();
3800 if (Qual
== nullptr)
3802 SoFar
= make
<QualifiedName
>(SoFar
, Qual
);
3807 Node
*Base
= getDerived().parseBaseUnresolvedName();
3808 if (Base
== nullptr)
3810 return make
<QualifiedName
>(SoFar
, Base
);
3813 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3814 if (!consumeIf("sr")) {
3815 SoFar
= getDerived().parseBaseUnresolvedName();
3816 if (SoFar
== nullptr)
3819 SoFar
= make
<GlobalQualifiedName
>(SoFar
);
3823 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3824 if (std::isdigit(look())) {
3826 Node
*Qual
= getDerived().parseSimpleId();
3827 if (Qual
== nullptr)
3830 SoFar
= make
<QualifiedName
>(SoFar
, Qual
);
3832 SoFar
= make
<GlobalQualifiedName
>(Qual
);
3837 } while (!consumeIf('E'));
3839 // sr <unresolved-type> <base-unresolved-name>
3840 // sr <unresolved-type> <template-args> <base-unresolved-name>
3842 SoFar
= getDerived().parseUnresolvedType();
3843 if (SoFar
== nullptr)
3846 if (look() == 'I') {
3847 Node
*TA
= getDerived().parseTemplateArgs();
3850 SoFar
= make
<NameWithTemplateArgs
>(SoFar
, TA
);
3856 DEMANGLE_ASSERT(SoFar
!= nullptr, "");
3858 Node
*Base
= getDerived().parseBaseUnresolvedName();
3859 if (Base
== nullptr)
3861 return make
<QualifiedName
>(SoFar
, Base
);
3864 // <abi-tags> ::= <abi-tag> [<abi-tags>]
3865 // <abi-tag> ::= B <source-name>
3866 template <typename Derived
, typename Alloc
>
3867 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseAbiTags(Node
*N
) {
3868 while (consumeIf('B')) {
3869 std::string_view SN
= parseBareSourceName();
3872 N
= make
<AbiTagAttr
>(N
, SN
);
3879 // <number> ::= [n] <non-negative decimal integer>
3880 template <typename Alloc
, typename Derived
>
3882 AbstractManglingParser
<Alloc
, Derived
>::parseNumber(bool AllowNegative
) {
3883 const char *Tmp
= First
;
3886 if (numLeft() == 0 || !std::isdigit(*First
))
3887 return std::string_view();
3888 while (numLeft() != 0 && std::isdigit(*First
))
3890 return std::string_view(Tmp
, First
- Tmp
);
3893 // <positive length number> ::= [0-9]*
3894 template <typename Alloc
, typename Derived
>
3895 bool AbstractManglingParser
<Alloc
, Derived
>::parsePositiveInteger(size_t *Out
) {
3897 if (look() < '0' || look() > '9')
3899 while (look() >= '0' && look() <= '9') {
3901 *Out
+= static_cast<size_t>(consume() - '0');
3906 template <typename Alloc
, typename Derived
>
3907 std::string_view AbstractManglingParser
<Alloc
, Derived
>::parseBareSourceName() {
3909 if (parsePositiveInteger(&Int
) || numLeft() < Int
)
3911 std::string_view
R(First
, Int
);
3916 // <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3918 // <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3919 // ::= DO <expression> E # computed (instantiation-dependent) noexcept
3920 // ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3922 // <ref-qualifier> ::= R # & ref-qualifier
3923 // <ref-qualifier> ::= O # && ref-qualifier
3924 template <typename Derived
, typename Alloc
>
3925 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFunctionType() {
3926 Qualifiers CVQuals
= parseCVQualifiers();
3928 Node
*ExceptionSpec
= nullptr;
3929 if (consumeIf("Do")) {
3930 ExceptionSpec
= make
<NameType
>("noexcept");
3933 } else if (consumeIf("DO")) {
3934 Node
*E
= getDerived().parseExpr();
3935 if (E
== nullptr || !consumeIf('E'))
3937 ExceptionSpec
= make
<NoexceptSpec
>(E
);
3940 } else if (consumeIf("Dw")) {
3941 size_t SpecsBegin
= Names
.size();
3942 while (!consumeIf('E')) {
3943 Node
*T
= getDerived().parseType();
3949 make
<DynamicExceptionSpec
>(popTrailingNodeArray(SpecsBegin
));
3954 consumeIf("Dx"); // transaction safe
3956 if (!consumeIf('F'))
3958 consumeIf('Y'); // extern "C"
3959 Node
*ReturnType
= getDerived().parseType();
3960 if (ReturnType
== nullptr)
3963 FunctionRefQual ReferenceQualifier
= FrefQualNone
;
3964 size_t ParamsBegin
= Names
.size();
3970 if (consumeIf("RE")) {
3971 ReferenceQualifier
= FrefQualLValue
;
3974 if (consumeIf("OE")) {
3975 ReferenceQualifier
= FrefQualRValue
;
3978 Node
*T
= getDerived().parseType();
3984 NodeArray Params
= popTrailingNodeArray(ParamsBegin
);
3985 return make
<FunctionType
>(ReturnType
, Params
, CVQuals
,
3986 ReferenceQualifier
, ExceptionSpec
);
3990 // <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3991 // ::= Dv [<dimension expression>] _ <element type>
3992 // <extended element type> ::= <element type>
3993 // ::= p # AltiVec vector pixel
3994 template <typename Derived
, typename Alloc
>
3995 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseVectorType() {
3996 if (!consumeIf("Dv"))
3998 if (look() >= '1' && look() <= '9') {
3999 Node
*DimensionNumber
= make
<NameType
>(parseNumber());
4000 if (!DimensionNumber
)
4002 if (!consumeIf('_'))
4005 return make
<PixelVectorType
>(DimensionNumber
);
4006 Node
*ElemType
= getDerived().parseType();
4007 if (ElemType
== nullptr)
4009 return make
<VectorType
>(ElemType
, DimensionNumber
);
4012 if (!consumeIf('_')) {
4013 Node
*DimExpr
= getDerived().parseExpr();
4016 if (!consumeIf('_'))
4018 Node
*ElemType
= getDerived().parseType();
4021 return make
<VectorType
>(ElemType
, DimExpr
);
4023 Node
*ElemType
= getDerived().parseType();
4026 return make
<VectorType
>(ElemType
, /*Dimension=*/nullptr);
4029 // <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
4030 // ::= DT <expression> E # decltype of an expression (C++0x)
4031 template <typename Derived
, typename Alloc
>
4032 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseDecltype() {
4033 if (!consumeIf('D'))
4035 if (!consumeIf('t') && !consumeIf('T'))
4037 Node
*E
= getDerived().parseExpr();
4040 if (!consumeIf('E'))
4042 return make
<EnclosingExpr
>("decltype", E
);
4045 // <array-type> ::= A <positive dimension number> _ <element type>
4046 // ::= A [<dimension expression>] _ <element type>
4047 template <typename Derived
, typename Alloc
>
4048 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseArrayType() {
4049 if (!consumeIf('A'))
4052 Node
*Dimension
= nullptr;
4054 if (std::isdigit(look())) {
4055 Dimension
= make
<NameType
>(parseNumber());
4058 if (!consumeIf('_'))
4060 } else if (!consumeIf('_')) {
4061 Node
*DimExpr
= getDerived().parseExpr();
4062 if (DimExpr
== nullptr)
4064 if (!consumeIf('_'))
4066 Dimension
= DimExpr
;
4069 Node
*Ty
= getDerived().parseType();
4072 return make
<ArrayType
>(Ty
, Dimension
);
4075 // <pointer-to-member-type> ::= M <class type> <member type>
4076 template <typename Derived
, typename Alloc
>
4077 Node
*AbstractManglingParser
<Derived
, Alloc
>::parsePointerToMemberType() {
4078 if (!consumeIf('M'))
4080 Node
*ClassType
= getDerived().parseType();
4081 if (ClassType
== nullptr)
4083 Node
*MemberType
= getDerived().parseType();
4084 if (MemberType
== nullptr)
4086 return make
<PointerToMemberType
>(ClassType
, MemberType
);
4089 // <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
4090 // ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
4091 // ::= Tu <name> # dependent elaborated type specifier using 'union'
4092 // ::= Te <name> # dependent elaborated type specifier using 'enum'
4093 template <typename Derived
, typename Alloc
>
4094 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseClassEnumType() {
4095 std::string_view ElabSpef
;
4096 if (consumeIf("Ts"))
4097 ElabSpef
= "struct";
4098 else if (consumeIf("Tu"))
4100 else if (consumeIf("Te"))
4103 Node
*Name
= getDerived().parseName();
4104 if (Name
== nullptr)
4107 if (!ElabSpef
.empty())
4108 return make
<ElaboratedTypeSpefType
>(ElabSpef
, Name
);
4113 // <qualified-type> ::= <qualifiers> <type>
4114 // <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
4115 // <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
4116 template <typename Derived
, typename Alloc
>
4117 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseQualifiedType() {
4118 if (consumeIf('U')) {
4119 std::string_view Qual
= parseBareSourceName();
4123 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
4124 if (starts_with(Qual
, "objcproto")) {
4125 constexpr size_t Len
= sizeof("objcproto") - 1;
4126 std::string_view
ProtoSourceName(Qual
.data() + Len
, Qual
.size() - Len
);
4127 std::string_view Proto
;
4129 ScopedOverride
<const char *> SaveFirst(First
, ProtoSourceName
.data()),
4130 SaveLast(Last
, &*ProtoSourceName
.rbegin() + 1);
4131 Proto
= parseBareSourceName();
4135 Node
*Child
= getDerived().parseQualifiedType();
4136 if (Child
== nullptr)
4138 return make
<ObjCProtoName
>(Child
, Proto
);
4142 if (look() == 'I') {
4143 TA
= getDerived().parseTemplateArgs();
4148 Node
*Child
= getDerived().parseQualifiedType();
4149 if (Child
== nullptr)
4151 return make
<VendorExtQualType
>(Child
, Qual
, TA
);
4154 Qualifiers Quals
= parseCVQualifiers();
4155 Node
*Ty
= getDerived().parseType();
4158 if (Quals
!= QualNone
)
4159 Ty
= make
<QualType
>(Ty
, Quals
);
4163 // <type> ::= <builtin-type>
4164 // ::= <qualified-type>
4165 // ::= <function-type>
4166 // ::= <class-enum-type>
4168 // ::= <pointer-to-member-type>
4169 // ::= <template-param>
4170 // ::= <template-template-param> <template-args>
4172 // ::= P <type> # pointer
4173 // ::= R <type> # l-value reference
4174 // ::= O <type> # r-value reference (C++11)
4175 // ::= C <type> # complex pair (C99)
4176 // ::= G <type> # imaginary (C99)
4177 // ::= <substitution> # See Compression below
4178 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
4179 // extension ::= <vector-type> # <vector-type> starts with Dv
4181 // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
4182 // <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
4183 template <typename Derived
, typename Alloc
>
4184 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseType() {
4185 Node
*Result
= nullptr;
4188 // ::= <qualified-type>
4192 unsigned AfterQuals
= 0;
4193 if (look(AfterQuals
) == 'r') ++AfterQuals
;
4194 if (look(AfterQuals
) == 'V') ++AfterQuals
;
4195 if (look(AfterQuals
) == 'K') ++AfterQuals
;
4197 if (look(AfterQuals
) == 'F' ||
4198 (look(AfterQuals
) == 'D' &&
4199 (look(AfterQuals
+ 1) == 'o' || look(AfterQuals
+ 1) == 'O' ||
4200 look(AfterQuals
+ 1) == 'w' || look(AfterQuals
+ 1) == 'x'))) {
4201 Result
= getDerived().parseFunctionType();
4204 DEMANGLE_FALLTHROUGH
;
4207 Result
= getDerived().parseQualifiedType();
4210 // <builtin-type> ::= v # void
4213 return make
<NameType
>("void");
4217 return make
<NameType
>("wchar_t");
4221 return make
<NameType
>("bool");
4225 return make
<NameType
>("char");
4226 // ::= a # signed char
4229 return make
<NameType
>("signed char");
4230 // ::= h # unsigned char
4233 return make
<NameType
>("unsigned char");
4237 return make
<NameType
>("short");
4238 // ::= t # unsigned short
4241 return make
<NameType
>("unsigned short");
4245 return make
<NameType
>("int");
4246 // ::= j # unsigned int
4249 return make
<NameType
>("unsigned int");
4253 return make
<NameType
>("long");
4254 // ::= m # unsigned long
4257 return make
<NameType
>("unsigned long");
4258 // ::= x # long long, __int64
4261 return make
<NameType
>("long long");
4262 // ::= y # unsigned long long, __int64
4265 return make
<NameType
>("unsigned long long");
4269 return make
<NameType
>("__int128");
4270 // ::= o # unsigned __int128
4273 return make
<NameType
>("unsigned __int128");
4277 return make
<NameType
>("float");
4281 return make
<NameType
>("double");
4282 // ::= e # long double, __float80
4285 return make
<NameType
>("long double");
4286 // ::= g # __float128
4289 return make
<NameType
>("__float128");
4293 return make
<NameType
>("...");
4295 // <builtin-type> ::= u <source-name> # vendor extended type
4298 std::string_view Res
= parseBareSourceName();
4301 // Typically, <builtin-type>s are not considered substitution candidates,
4302 // but the exception to that exception is vendor extended types (Itanium C++
4304 if (consumeIf('I')) {
4305 Node
*BaseType
= parseType();
4306 if (BaseType
== nullptr)
4308 if (!consumeIf('E'))
4310 Result
= make
<TransformedType
>(Res
, BaseType
);
4312 Result
= make
<NameType
>(Res
);
4317 // ::= Dd # IEEE 754r decimal floating point (64 bits)
4320 return make
<NameType
>("decimal64");
4321 // ::= De # IEEE 754r decimal floating point (128 bits)
4324 return make
<NameType
>("decimal128");
4325 // ::= Df # IEEE 754r decimal floating point (32 bits)
4328 return make
<NameType
>("decimal32");
4329 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
4332 return make
<NameType
>("half");
4333 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
4336 Node
*DimensionNumber
= make
<NameType
>(parseNumber());
4337 if (!DimensionNumber
)
4339 if (!consumeIf('_'))
4341 return make
<BinaryFPType
>(DimensionNumber
);
4343 // ::= [DS] DA # N1169 fixed-point [_Sat] T _Accum
4344 // ::= [DS] DR # N1169 fixed-point [_Sat] T _Frac
4345 // <fixed-point-size>
4347 // ::= t # unsigned short
4351 // ::= m # unsigned long
4357 return make
<NameType
>("short _Accum");
4359 return make
<NameType
>("unsigned short _Accum");
4361 return make
<NameType
>("_Accum");
4363 return make
<NameType
>("unsigned _Accum");
4365 return make
<NameType
>("long _Accum");
4367 return make
<NameType
>("unsigned long _Accum");
4377 return make
<NameType
>("short _Fract");
4379 return make
<NameType
>("unsigned short _Fract");
4381 return make
<NameType
>("_Fract");
4383 return make
<NameType
>("unsigned _Fract");
4385 return make
<NameType
>("long _Fract");
4387 return make
<NameType
>("unsigned long _Fract");
4396 if (look(1) == 'A') {
4401 return make
<NameType
>("_Sat short _Accum");
4403 return make
<NameType
>("_Sat unsigned short _Accum");
4405 return make
<NameType
>("_Sat _Accum");
4407 return make
<NameType
>("_Sat unsigned _Accum");
4409 return make
<NameType
>("_Sat long _Accum");
4411 return make
<NameType
>("_Sat unsigned long _Accum");
4416 if (look(1) == 'R') {
4421 return make
<NameType
>("_Sat short _Fract");
4423 return make
<NameType
>("_Sat unsigned short _Fract");
4425 return make
<NameType
>("_Sat _Fract");
4427 return make
<NameType
>("_Sat unsigned _Fract");
4429 return make
<NameType
>("_Sat long _Fract");
4431 return make
<NameType
>("_Sat unsigned long _Fract");
4438 // ::= DB <number> _ # C23 signed _BitInt(N)
4439 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
4440 // ::= DU <number> _ # C23 unsigned _BitInt(N)
4441 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
4444 bool Signed
= look(1) == 'B';
4446 Node
*Size
= std::isdigit(look()) ? make
<NameType
>(parseNumber())
4447 : getDerived().parseExpr();
4450 if (!consumeIf('_'))
4452 return make
<BitIntType
>(Size
, Signed
);
4454 // ::= Di # char32_t
4457 return make
<NameType
>("char32_t");
4458 // ::= Ds # char16_t
4461 return make
<NameType
>("char16_t");
4462 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
4465 return make
<NameType
>("char8_t");
4466 // ::= Da # auto (in dependent new-expressions)
4469 return make
<NameType
>("auto");
4470 // ::= Dc # decltype(auto)
4473 return make
<NameType
>("decltype(auto)");
4474 // ::= Dk <type-constraint> # constrained auto
4475 // ::= DK <type-constraint> # constrained decltype(auto)
4478 std::string_view Kind
= look(1) == 'k' ? " auto" : " decltype(auto)";
4480 Node
*Constraint
= getDerived().parseName();
4483 return make
<PostfixQualifiedType
>(Constraint
, Kind
);
4485 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
4488 return make
<NameType
>("std::nullptr_t");
4493 Result
= getDerived().parseDecltype();
4496 // extension ::= <vector-type> # <vector-type> starts with Dv
4498 Result
= getDerived().parseVectorType();
4501 // ::= Dp <type> # pack expansion (C++0x)
4504 Node
*Child
= getDerived().parseType();
4507 Result
= make
<ParameterPackExpansion
>(Child
);
4510 // Exception specifier on a function type.
4514 // Transaction safe function type.
4516 Result
= getDerived().parseFunctionType();
4520 // ::= <function-type>
4522 Result
= getDerived().parseFunctionType();
4527 Result
= getDerived().parseArrayType();
4530 // ::= <pointer-to-member-type>
4532 Result
= getDerived().parsePointerToMemberType();
4535 // ::= <template-param>
4537 // This could be an elaborate type specifier on a <class-enum-type>.
4538 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
4539 Result
= getDerived().parseClassEnumType();
4543 Result
= getDerived().parseTemplateParam();
4544 if (Result
== nullptr)
4547 // Result could be either of:
4548 // <type> ::= <template-param>
4549 // <type> ::= <template-template-param> <template-args>
4551 // <template-template-param> ::= <template-param>
4552 // ::= <substitution>
4554 // If this is followed by some <template-args>, and we're permitted to
4555 // parse them, take the second production.
4557 if (TryToParseTemplateArgs
&& look() == 'I') {
4558 Subs
.push_back(Result
);
4559 Node
*TA
= getDerived().parseTemplateArgs();
4562 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
4566 // ::= P <type> # pointer
4569 Node
*Ptr
= getDerived().parseType();
4572 Result
= make
<PointerType
>(Ptr
);
4575 // ::= R <type> # l-value reference
4578 Node
*Ref
= getDerived().parseType();
4581 Result
= make
<ReferenceType
>(Ref
, ReferenceKind::LValue
);
4584 // ::= O <type> # r-value reference (C++11)
4587 Node
*Ref
= getDerived().parseType();
4590 Result
= make
<ReferenceType
>(Ref
, ReferenceKind::RValue
);
4593 // ::= C <type> # complex pair (C99)
4596 Node
*P
= getDerived().parseType();
4599 Result
= make
<PostfixQualifiedType
>(P
, " complex");
4602 // ::= G <type> # imaginary (C99)
4605 Node
*P
= getDerived().parseType();
4608 Result
= make
<PostfixQualifiedType
>(P
, " imaginary");
4611 // ::= <substitution> # See Compression below
4613 if (look(1) != 't') {
4614 bool IsSubst
= false;
4615 Result
= getDerived().parseUnscopedName(nullptr, &IsSubst
);
4619 // Sub could be either of:
4620 // <type> ::= <substitution>
4621 // <type> ::= <template-template-param> <template-args>
4623 // <template-template-param> ::= <template-param>
4624 // ::= <substitution>
4626 // If this is followed by some <template-args>, and we're permitted to
4627 // parse them, take the second production.
4629 if (look() == 'I' && (!IsSubst
|| TryToParseTemplateArgs
)) {
4631 Subs
.push_back(Result
);
4632 Node
*TA
= getDerived().parseTemplateArgs();
4635 Result
= make
<NameWithTemplateArgs
>(Result
, TA
);
4636 } else if (IsSubst
) {
4637 // If all we parsed was a substitution, don't re-insert into the
4638 // substitution table.
4643 DEMANGLE_FALLTHROUGH
;
4645 // ::= <class-enum-type>
4647 Result
= getDerived().parseClassEnumType();
4652 // If we parsed a type, insert it into the substitution table. Note that all
4653 // <builtin-type>s and <substitution>s have already bailed out, because they
4654 // don't get substitutions.
4655 if (Result
!= nullptr)
4656 Subs
.push_back(Result
);
4660 template <typename Derived
, typename Alloc
>
4662 AbstractManglingParser
<Derived
, Alloc
>::parsePrefixExpr(std::string_view Kind
,
4664 Node
*E
= getDerived().parseExpr();
4667 return make
<PrefixExpr
>(Kind
, E
, Prec
);
4670 template <typename Derived
, typename Alloc
>
4672 AbstractManglingParser
<Derived
, Alloc
>::parseBinaryExpr(std::string_view Kind
,
4674 Node
*LHS
= getDerived().parseExpr();
4677 Node
*RHS
= getDerived().parseExpr();
4680 return make
<BinaryExpr
>(LHS
, Kind
, RHS
, Prec
);
4683 template <typename Derived
, typename Alloc
>
4684 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseIntegerLiteral(
4685 std::string_view Lit
) {
4686 std::string_view Tmp
= parseNumber(true);
4687 if (!Tmp
.empty() && consumeIf('E'))
4688 return make
<IntegerLiteral
>(Lit
, Tmp
);
4692 // <CV-Qualifiers> ::= [r] [V] [K]
4693 template <typename Alloc
, typename Derived
>
4694 Qualifiers AbstractManglingParser
<Alloc
, Derived
>::parseCVQualifiers() {
4695 Qualifiers CVR
= QualNone
;
4697 CVR
|= QualRestrict
;
4699 CVR
|= QualVolatile
;
4705 // <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4706 // ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4707 // ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4708 // ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
4709 // ::= fpT # 'this' expression (not part of standard?)
4710 template <typename Derived
, typename Alloc
>
4711 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFunctionParam() {
4712 if (consumeIf("fpT"))
4713 return make
<NameType
>("this");
4714 if (consumeIf("fp")) {
4715 parseCVQualifiers();
4716 std::string_view Num
= parseNumber();
4717 if (!consumeIf('_'))
4719 return make
<FunctionParam
>(Num
);
4721 if (consumeIf("fL")) {
4722 if (parseNumber().empty())
4724 if (!consumeIf('p'))
4726 parseCVQualifiers();
4727 std::string_view Num
= parseNumber();
4728 if (!consumeIf('_'))
4730 return make
<FunctionParam
>(Num
);
4735 // cv <type> <expression> # conversion with one argument
4736 // cv <type> _ <expression>* E # conversion with a different number of arguments
4737 template <typename Derived
, typename Alloc
>
4738 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseConversionExpr() {
4739 if (!consumeIf("cv"))
4743 ScopedOverride
<bool> SaveTemp(TryToParseTemplateArgs
, false);
4744 Ty
= getDerived().parseType();
4750 if (consumeIf('_')) {
4751 size_t ExprsBegin
= Names
.size();
4752 while (!consumeIf('E')) {
4753 Node
*E
= getDerived().parseExpr();
4758 NodeArray Exprs
= popTrailingNodeArray(ExprsBegin
);
4759 return make
<ConversionExpr
>(Ty
, Exprs
);
4762 Node
*E
[1] = {getDerived().parseExpr()};
4763 if (E
[0] == nullptr)
4765 return make
<ConversionExpr
>(Ty
, makeNodeArray(E
, E
+ 1));
4768 // <expr-primary> ::= L <type> <value number> E # integer literal
4769 // ::= L <type> <value float> E # floating literal
4770 // ::= L <string type> E # string literal
4771 // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
4772 // ::= L <lambda type> E # lambda expression
4773 // FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4774 // ::= L <mangled-name> E # external name
4775 template <typename Derived
, typename Alloc
>
4776 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseExprPrimary() {
4777 if (!consumeIf('L'))
4782 return getDerived().parseIntegerLiteral("wchar_t");
4784 if (consumeIf("b0E"))
4785 return make
<BoolExpr
>(0);
4786 if (consumeIf("b1E"))
4787 return make
<BoolExpr
>(1);
4791 return getDerived().parseIntegerLiteral("char");
4794 return getDerived().parseIntegerLiteral("signed char");
4797 return getDerived().parseIntegerLiteral("unsigned char");
4800 return getDerived().parseIntegerLiteral("short");
4803 return getDerived().parseIntegerLiteral("unsigned short");
4806 return getDerived().parseIntegerLiteral("");
4809 return getDerived().parseIntegerLiteral("u");
4812 return getDerived().parseIntegerLiteral("l");
4815 return getDerived().parseIntegerLiteral("ul");
4818 return getDerived().parseIntegerLiteral("ll");
4821 return getDerived().parseIntegerLiteral("ull");
4824 return getDerived().parseIntegerLiteral("__int128");
4827 return getDerived().parseIntegerLiteral("unsigned __int128");
4830 return getDerived().template parseFloatingLiteral
<float>();
4833 return getDerived().template parseFloatingLiteral
<double>();
4836 #if defined(__powerpc__) || defined(__s390__)
4837 // Handle cases where long doubles encoded with e have the same size
4838 // and representation as doubles.
4839 return getDerived().template parseFloatingLiteral
<double>();
4841 return getDerived().template parseFloatingLiteral
<long double>();
4844 if (consumeIf("_Z")) {
4845 Node
*R
= getDerived().parseEncoding();
4846 if (R
!= nullptr && consumeIf('E'))
4851 Node
*T
= getDerived().parseType();
4854 // FIXME: We need to include the string contents in the mangling.
4856 return make
<StringLiteral
>(T
);
4860 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
4861 return make
<NameType
>("nullptr");
4864 // Invalid mangled name per
4865 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4868 // FIXME: Should we support LUb... for block literals?
4871 Node
*T
= parseUnnamedTypeName(nullptr);
4872 if (!T
|| !consumeIf('E'))
4874 return make
<LambdaExpr
>(T
);
4877 // might be named type
4878 Node
*T
= getDerived().parseType();
4881 std::string_view N
= parseNumber(/*AllowNegative=*/true);
4884 if (!consumeIf('E'))
4886 return make
<EnumLiteral
>(T
, N
);
4891 // <braced-expression> ::= <expression>
4892 // ::= di <field source-name> <braced-expression> # .name = expr
4893 // ::= dx <index expression> <braced-expression> # [expr] = expr
4894 // ::= dX <range begin expression> <range end expression> <braced-expression>
4895 template <typename Derived
, typename Alloc
>
4896 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseBracedExpr() {
4897 if (look() == 'd') {
4901 Node
*Field
= getDerived().parseSourceName(/*NameState=*/nullptr);
4902 if (Field
== nullptr)
4904 Node
*Init
= getDerived().parseBracedExpr();
4905 if (Init
== nullptr)
4907 return make
<BracedExpr
>(Field
, Init
, /*isArray=*/false);
4911 Node
*Index
= getDerived().parseExpr();
4912 if (Index
== nullptr)
4914 Node
*Init
= getDerived().parseBracedExpr();
4915 if (Init
== nullptr)
4917 return make
<BracedExpr
>(Index
, Init
, /*isArray=*/true);
4921 Node
*RangeBegin
= getDerived().parseExpr();
4922 if (RangeBegin
== nullptr)
4924 Node
*RangeEnd
= getDerived().parseExpr();
4925 if (RangeEnd
== nullptr)
4927 Node
*Init
= getDerived().parseBracedExpr();
4928 if (Init
== nullptr)
4930 return make
<BracedRangeExpr
>(RangeBegin
, RangeEnd
, Init
);
4934 return getDerived().parseExpr();
4937 // (not yet in the spec)
4938 // <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4939 // ::= fR <binary-operator-name> <expression> <expression>
4940 // ::= fl <binary-operator-name> <expression>
4941 // ::= fr <binary-operator-name> <expression>
4942 template <typename Derived
, typename Alloc
>
4943 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseFoldExpr() {
4944 if (!consumeIf('f'))
4947 bool IsLeftFold
= false, HasInitializer
= false;
4953 HasInitializer
= true;
4956 HasInitializer
= true;
4966 const auto *Op
= parseOperatorEncoding();
4969 if (!(Op
->getKind() == OperatorInfo::Binary
4970 || (Op
->getKind() == OperatorInfo::Member
4971 && Op
->getName().back() == '*')))
4974 Node
*Pack
= getDerived().parseExpr();
4975 if (Pack
== nullptr)
4978 Node
*Init
= nullptr;
4979 if (HasInitializer
) {
4980 Init
= getDerived().parseExpr();
4981 if (Init
== nullptr)
4985 if (IsLeftFold
&& Init
)
4986 std::swap(Pack
, Init
);
4988 return make
<FoldExpr
>(IsLeftFold
, Op
->getSymbol(), Pack
, Init
);
4991 // <expression> ::= mc <parameter type> <expr> [<offset number>] E
4993 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4994 template <typename Derived
, typename Alloc
>
4996 AbstractManglingParser
<Derived
, Alloc
>::parsePointerToMemberConversionExpr(
4998 Node
*Ty
= getDerived().parseType();
5001 Node
*Expr
= getDerived().parseExpr();
5004 std::string_view Offset
= getDerived().parseNumber(true);
5005 if (!consumeIf('E'))
5007 return make
<PointerToMemberConversionExpr
>(Ty
, Expr
, Offset
, Prec
);
5010 // <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
5011 // <union-selector> ::= _ [<number>]
5013 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
5014 template <typename Derived
, typename Alloc
>
5015 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSubobjectExpr() {
5016 Node
*Ty
= getDerived().parseType();
5019 Node
*Expr
= getDerived().parseExpr();
5022 std::string_view Offset
= getDerived().parseNumber(true);
5023 size_t SelectorsBegin
= Names
.size();
5024 while (consumeIf('_')) {
5025 Node
*Selector
= make
<NameType
>(parseNumber());
5028 Names
.push_back(Selector
);
5030 bool OnePastTheEnd
= consumeIf('p');
5031 if (!consumeIf('E'))
5033 return make
<SubobjectExpr
>(
5034 Ty
, Expr
, Offset
, popTrailingNodeArray(SelectorsBegin
), OnePastTheEnd
);
5037 template <typename Derived
, typename Alloc
>
5038 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseConstraintExpr() {
5039 // Within this expression, all enclosing template parameter lists are in
5041 ScopedOverride
<bool> SaveIncompleteTemplateParameterTracking(
5042 HasIncompleteTemplateParameterTracking
, true);
5043 return getDerived().parseExpr();
5046 template <typename Derived
, typename Alloc
>
5047 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseRequiresExpr() {
5049 if (consumeIf("rQ")) {
5050 // <expression> ::= rQ <bare-function-type> _ <requirement>+ E
5051 size_t ParamsBegin
= Names
.size();
5052 while (!consumeIf('_')) {
5053 Node
*Type
= getDerived().parseType();
5054 if (Type
== nullptr)
5056 Names
.push_back(Type
);
5058 Params
= popTrailingNodeArray(ParamsBegin
);
5059 } else if (!consumeIf("rq")) {
5060 // <expression> ::= rq <requirement>+ E
5064 size_t ReqsBegin
= Names
.size();
5066 Node
*Constraint
= nullptr;
5067 if (consumeIf('X')) {
5068 // <requirement> ::= X <expression> [N] [R <type-constraint>]
5069 Node
*Expr
= getDerived().parseExpr();
5070 if (Expr
== nullptr)
5072 bool Noexcept
= consumeIf('N');
5073 Node
*TypeReq
= nullptr;
5074 if (consumeIf('R')) {
5075 TypeReq
= getDerived().parseName();
5076 if (TypeReq
== nullptr)
5079 Constraint
= make
<ExprRequirement
>(Expr
, Noexcept
, TypeReq
);
5080 } else if (consumeIf('T')) {
5081 // <requirement> ::= T <type>
5082 Node
*Type
= getDerived().parseType();
5083 if (Type
== nullptr)
5085 Constraint
= make
<TypeRequirement
>(Type
);
5086 } else if (consumeIf('Q')) {
5087 // <requirement> ::= Q <constraint-expression>
5089 // FIXME: We use <expression> instead of <constraint-expression>. Either
5090 // the requires expression is already inside a constraint expression, in
5091 // which case it makes no difference, or we're in a requires-expression
5092 // that might be partially-substituted, where the language behavior is
5093 // not yet settled and clang mangles after substitution.
5094 Node
*NestedReq
= getDerived().parseExpr();
5095 if (NestedReq
== nullptr)
5097 Constraint
= make
<NestedRequirement
>(NestedReq
);
5099 if (Constraint
== nullptr)
5101 Names
.push_back(Constraint
);
5102 } while (!consumeIf('E'));
5104 return make
<RequiresExpr
>(Params
, popTrailingNodeArray(ReqsBegin
));
5107 // <expression> ::= <unary operator-name> <expression>
5108 // ::= <binary operator-name> <expression> <expression>
5109 // ::= <ternary operator-name> <expression> <expression> <expression>
5110 // ::= cl <expression>+ E # call
5111 // ::= cp <base-unresolved-name> <expression>* E # (name) (expr-list), call that would use argument-dependent lookup but for the parentheses
5112 // ::= cv <type> <expression> # conversion with one argument
5113 // ::= cv <type> _ <expression>* E # conversion with a different number of arguments
5114 // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
5115 // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
5116 // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
5117 // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
5118 // ::= [gs] dl <expression> # delete expression
5119 // ::= [gs] da <expression> # delete[] expression
5120 // ::= pp_ <expression> # prefix ++
5121 // ::= mm_ <expression> # prefix --
5122 // ::= ti <type> # typeid (type)
5123 // ::= te <expression> # typeid (expression)
5124 // ::= dc <type> <expression> # dynamic_cast<type> (expression)
5125 // ::= sc <type> <expression> # static_cast<type> (expression)
5126 // ::= cc <type> <expression> # const_cast<type> (expression)
5127 // ::= rc <type> <expression> # reinterpret_cast<type> (expression)
5128 // ::= st <type> # sizeof (a type)
5129 // ::= sz <expression> # sizeof (an expression)
5130 // ::= at <type> # alignof (a type)
5131 // ::= az <expression> # alignof (an expression)
5132 // ::= nx <expression> # noexcept (expression)
5133 // ::= <template-param>
5134 // ::= <function-param>
5135 // ::= dt <expression> <unresolved-name> # expr.name
5136 // ::= pt <expression> <unresolved-name> # expr->name
5137 // ::= ds <expression> <expression> # expr.*expr
5138 // ::= sZ <template-param> # size of a parameter pack
5139 // ::= sZ <function-param> # size of a function parameter pack
5140 // ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
5141 // ::= sp <expression> # pack expansion
5142 // ::= tw <expression> # throw expression
5143 // ::= tr # throw with no operand (rethrow)
5144 // ::= <unresolved-name> # f(p), N::f(p), ::f(p),
5145 // # freestanding dependent name (e.g., T::x),
5146 // # objectless nonstatic member reference
5147 // ::= fL <binary-operator-name> <expression> <expression>
5148 // ::= fR <binary-operator-name> <expression> <expression>
5149 // ::= fl <binary-operator-name> <expression>
5150 // ::= fr <binary-operator-name> <expression>
5151 // ::= <expr-primary>
5152 template <typename Derived
, typename Alloc
>
5153 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseExpr() {
5154 bool Global
= consumeIf("gs");
5156 const auto *Op
= parseOperatorEncoding();
5158 auto Sym
= Op
->getSymbol();
5159 switch (Op
->getKind()) {
5160 case OperatorInfo::Binary
:
5161 // Binary operator: lhs @ rhs
5162 return getDerived().parseBinaryExpr(Sym
, Op
->getPrecedence());
5163 case OperatorInfo::Prefix
:
5164 // Prefix unary operator: @ expr
5165 return getDerived().parsePrefixExpr(Sym
, Op
->getPrecedence());
5166 case OperatorInfo::Postfix
: {
5167 // Postfix unary operator: expr @
5169 return getDerived().parsePrefixExpr(Sym
, Op
->getPrecedence());
5170 Node
*Ex
= getDerived().parseExpr();
5173 return make
<PostfixExpr
>(Ex
, Sym
, Op
->getPrecedence());
5175 case OperatorInfo::Array
: {
5176 // Array Index: lhs [ rhs ]
5177 Node
*Base
= getDerived().parseExpr();
5178 if (Base
== nullptr)
5180 Node
*Index
= getDerived().parseExpr();
5181 if (Index
== nullptr)
5183 return make
<ArraySubscriptExpr
>(Base
, Index
, Op
->getPrecedence());
5185 case OperatorInfo::Member
: {
5186 // Member access lhs @ rhs
5187 Node
*LHS
= getDerived().parseExpr();
5190 Node
*RHS
= getDerived().parseExpr();
5193 return make
<MemberExpr
>(LHS
, Sym
, RHS
, Op
->getPrecedence());
5195 case OperatorInfo::New
: {
5197 // # new (expr-list) type [(init)]
5198 // [gs] nw <expression>* _ <type> [pi <expression>*] E
5199 // # new[] (expr-list) type [(init)]
5200 // [gs] na <expression>* _ <type> [pi <expression>*] E
5201 size_t Exprs
= Names
.size();
5202 while (!consumeIf('_')) {
5203 Node
*Ex
= getDerived().parseExpr();
5206 Names
.push_back(Ex
);
5208 NodeArray ExprList
= popTrailingNodeArray(Exprs
);
5209 Node
*Ty
= getDerived().parseType();
5212 bool HaveInits
= consumeIf("pi");
5213 size_t InitsBegin
= Names
.size();
5214 while (!consumeIf('E')) {
5217 Node
*Init
= getDerived().parseExpr();
5218 if (Init
== nullptr)
5220 Names
.push_back(Init
);
5222 NodeArray Inits
= popTrailingNodeArray(InitsBegin
);
5223 return make
<NewExpr
>(ExprList
, Ty
, Inits
, Global
,
5224 /*IsArray=*/Op
->getFlag(), Op
->getPrecedence());
5226 case OperatorInfo::Del
: {
5228 Node
*Ex
= getDerived().parseExpr();
5231 return make
<DeleteExpr
>(Ex
, Global
, /*IsArray=*/Op
->getFlag(),
5232 Op
->getPrecedence());
5234 case OperatorInfo::Call
: {
5236 Node
*Callee
= getDerived().parseExpr();
5237 if (Callee
== nullptr)
5239 size_t ExprsBegin
= Names
.size();
5240 while (!consumeIf('E')) {
5241 Node
*E
= getDerived().parseExpr();
5246 return make
<CallExpr
>(Callee
, popTrailingNodeArray(ExprsBegin
),
5247 /*IsParen=*/Op
->getFlag(), Op
->getPrecedence());
5249 case OperatorInfo::CCast
: {
5250 // C Cast: (type)expr
5253 ScopedOverride
<bool> SaveTemp(TryToParseTemplateArgs
, false);
5254 Ty
= getDerived().parseType();
5259 size_t ExprsBegin
= Names
.size();
5260 bool IsMany
= consumeIf('_');
5261 while (!consumeIf('E')) {
5262 Node
*E
= getDerived().parseExpr();
5269 NodeArray Exprs
= popTrailingNodeArray(ExprsBegin
);
5270 if (!IsMany
&& Exprs
.size() != 1)
5272 return make
<ConversionExpr
>(Ty
, Exprs
, Op
->getPrecedence());
5274 case OperatorInfo::Conditional
: {
5275 // Conditional operator: expr ? expr : expr
5276 Node
*Cond
= getDerived().parseExpr();
5277 if (Cond
== nullptr)
5279 Node
*LHS
= getDerived().parseExpr();
5282 Node
*RHS
= getDerived().parseExpr();
5285 return make
<ConditionalExpr
>(Cond
, LHS
, RHS
, Op
->getPrecedence());
5287 case OperatorInfo::NamedCast
: {
5288 // Named cast operation, @<type>(expr)
5289 Node
*Ty
= getDerived().parseType();
5292 Node
*Ex
= getDerived().parseExpr();
5295 return make
<CastExpr
>(Sym
, Ty
, Ex
, Op
->getPrecedence());
5297 case OperatorInfo::OfIdOp
: {
5298 // [sizeof/alignof/typeid] ( <type>|<expr> )
5300 Op
->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
5303 return make
<EnclosingExpr
>(Sym
, Arg
, Op
->getPrecedence());
5305 case OperatorInfo::NameOnly
: {
5306 // Not valid as an expression operand.
5310 DEMANGLE_UNREACHABLE
;
5317 return getDerived().parseExprPrimary();
5319 return getDerived().parseTemplateParam();
5320 if (look() == 'f') {
5321 // Disambiguate a fold expression from a <function-param>.
5322 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
5323 return getDerived().parseFunctionParam();
5324 return getDerived().parseFoldExpr();
5326 if (consumeIf("il")) {
5327 size_t InitsBegin
= Names
.size();
5328 while (!consumeIf('E')) {
5329 Node
*E
= getDerived().parseBracedExpr();
5334 return make
<InitListExpr
>(nullptr, popTrailingNodeArray(InitsBegin
));
5336 if (consumeIf("mc"))
5337 return parsePointerToMemberConversionExpr(Node::Prec::Unary
);
5338 if (consumeIf("nx")) {
5339 Node
*Ex
= getDerived().parseExpr();
5342 return make
<EnclosingExpr
>("noexcept ", Ex
, Node::Prec::Unary
);
5344 if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q'))
5345 return parseRequiresExpr();
5346 if (consumeIf("so"))
5347 return parseSubobjectExpr();
5348 if (consumeIf("sp")) {
5349 Node
*Child
= getDerived().parseExpr();
5350 if (Child
== nullptr)
5352 return make
<ParameterPackExpansion
>(Child
);
5354 if (consumeIf("sZ")) {
5355 if (look() == 'T') {
5356 Node
*R
= getDerived().parseTemplateParam();
5359 return make
<SizeofParamPackExpr
>(R
);
5361 Node
*FP
= getDerived().parseFunctionParam();
5364 return make
<EnclosingExpr
>("sizeof... ", FP
);
5366 if (consumeIf("sP")) {
5367 size_t ArgsBegin
= Names
.size();
5368 while (!consumeIf('E')) {
5369 Node
*Arg
= getDerived().parseTemplateArg();
5372 Names
.push_back(Arg
);
5374 auto *Pack
= make
<NodeArrayNode
>(popTrailingNodeArray(ArgsBegin
));
5377 return make
<EnclosingExpr
>("sizeof... ", Pack
);
5379 if (consumeIf("tl")) {
5380 Node
*Ty
= getDerived().parseType();
5383 size_t InitsBegin
= Names
.size();
5384 while (!consumeIf('E')) {
5385 Node
*E
= getDerived().parseBracedExpr();
5390 return make
<InitListExpr
>(Ty
, popTrailingNodeArray(InitsBegin
));
5392 if (consumeIf("tr"))
5393 return make
<NameType
>("throw");
5394 if (consumeIf("tw")) {
5395 Node
*Ex
= getDerived().parseExpr();
5398 return make
<ThrowExpr
>(Ex
);
5400 if (consumeIf('u')) {
5401 Node
*Name
= getDerived().parseSourceName(/*NameState=*/nullptr);
5404 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
5405 // standard encoding expects a <template-arg>, and would be otherwise be
5406 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
5407 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
5408 // actual conflict here.
5409 bool IsUUID
= false;
5410 Node
*UUID
= nullptr;
5411 if (Name
->getBaseName() == "__uuidof") {
5412 if (consumeIf('t')) {
5413 UUID
= getDerived().parseType();
5415 } else if (consumeIf('z')) {
5416 UUID
= getDerived().parseExpr();
5420 size_t ExprsBegin
= Names
.size();
5422 if (UUID
== nullptr)
5424 Names
.push_back(UUID
);
5426 while (!consumeIf('E')) {
5427 Node
*E
= getDerived().parseTemplateArg();
5433 return make
<CallExpr
>(Name
, popTrailingNodeArray(ExprsBegin
),
5434 /*IsParen=*/false, Node::Prec::Postfix
);
5437 // Only unresolved names remain.
5438 return getDerived().parseUnresolvedName(Global
);
5441 // <call-offset> ::= h <nv-offset> _
5442 // ::= v <v-offset> _
5444 // <nv-offset> ::= <offset number>
5445 // # non-virtual base override
5447 // <v-offset> ::= <offset number> _ <virtual offset number>
5448 // # virtual base override, with vcall offset
5449 template <typename Alloc
, typename Derived
>
5450 bool AbstractManglingParser
<Alloc
, Derived
>::parseCallOffset() {
5451 // Just scan through the call offset, we never add this information into the
5454 return parseNumber(true).empty() || !consumeIf('_');
5456 return parseNumber(true).empty() || !consumeIf('_') ||
5457 parseNumber(true).empty() || !consumeIf('_');
5461 // <special-name> ::= TV <type> # virtual table
5462 // ::= TT <type> # VTT structure (construction vtable index)
5463 // ::= TI <type> # typeinfo structure
5464 // ::= TS <type> # typeinfo name (null-terminated byte string)
5465 // ::= Tc <call-offset> <call-offset> <base encoding>
5466 // # base is the nominal target function of thunk
5467 // # first call-offset is 'this' adjustment
5468 // # second call-offset is result adjustment
5469 // ::= T <call-offset> <base encoding>
5470 // # base is the nominal target function of thunk
5471 // # Guard variable for one-time initialization
5472 // ::= GV <object name>
5474 // ::= TW <object name> # Thread-local wrapper
5475 // ::= TH <object name> # Thread-local initialization
5476 // ::= GR <object name> _ # First temporary
5477 // ::= GR <object name> <seq-id> _ # Subsequent temporaries
5478 // # construction vtable for second-in-first
5479 // extension ::= TC <first type> <number> _ <second type>
5480 // extension ::= GR <object name> # reference temporary for object
5481 // extension ::= GI <module name> # module global initializer
5482 template <typename Derived
, typename Alloc
>
5483 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSpecialName() {
5487 // TA <template-arg> # template parameter object
5489 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
5492 Node
*Arg
= getDerived().parseTemplateArg();
5495 return make
<SpecialName
>("template parameter object for ", Arg
);
5497 // TV <type> # virtual table
5500 Node
*Ty
= getDerived().parseType();
5503 return make
<SpecialName
>("vtable for ", Ty
);
5505 // TT <type> # VTT structure (construction vtable index)
5508 Node
*Ty
= getDerived().parseType();
5511 return make
<SpecialName
>("VTT for ", Ty
);
5513 // TI <type> # typeinfo structure
5516 Node
*Ty
= getDerived().parseType();
5519 return make
<SpecialName
>("typeinfo for ", Ty
);
5521 // TS <type> # typeinfo name (null-terminated byte string)
5524 Node
*Ty
= getDerived().parseType();
5527 return make
<SpecialName
>("typeinfo name for ", Ty
);
5529 // Tc <call-offset> <call-offset> <base encoding>
5532 if (parseCallOffset() || parseCallOffset())
5534 Node
*Encoding
= getDerived().parseEncoding();
5535 if (Encoding
== nullptr)
5537 return make
<SpecialName
>("covariant return thunk to ", Encoding
);
5539 // extension ::= TC <first type> <number> _ <second type>
5540 // # construction vtable for second-in-first
5543 Node
*FirstType
= getDerived().parseType();
5544 if (FirstType
== nullptr)
5546 if (parseNumber(true).empty() || !consumeIf('_'))
5548 Node
*SecondType
= getDerived().parseType();
5549 if (SecondType
== nullptr)
5551 return make
<CtorVtableSpecialName
>(SecondType
, FirstType
);
5553 // TW <object name> # Thread-local wrapper
5556 Node
*Name
= getDerived().parseName();
5557 if (Name
== nullptr)
5559 return make
<SpecialName
>("thread-local wrapper routine for ", Name
);
5561 // TH <object name> # Thread-local initialization
5564 Node
*Name
= getDerived().parseName();
5565 if (Name
== nullptr)
5567 return make
<SpecialName
>("thread-local initialization routine for ", Name
);
5569 // T <call-offset> <base encoding>
5572 bool IsVirt
= look() == 'v';
5573 if (parseCallOffset())
5575 Node
*BaseEncoding
= getDerived().parseEncoding();
5576 if (BaseEncoding
== nullptr)
5579 return make
<SpecialName
>("virtual thunk to ", BaseEncoding
);
5581 return make
<SpecialName
>("non-virtual thunk to ", BaseEncoding
);
5586 // GV <object name> # Guard variable for one-time initialization
5589 Node
*Name
= getDerived().parseName();
5590 if (Name
== nullptr)
5592 return make
<SpecialName
>("guard variable for ", Name
);
5594 // GR <object name> # reference temporary for object
5595 // GR <object name> _ # First temporary
5596 // GR <object name> <seq-id> _ # Subsequent temporaries
5599 Node
*Name
= getDerived().parseName();
5600 if (Name
== nullptr)
5603 bool ParsedSeqId
= !parseSeqId(&Count
);
5604 if (!consumeIf('_') && ParsedSeqId
)
5606 return make
<SpecialName
>("reference temporary for ", Name
);
5608 // GI <module-name> v
5611 ModuleName
*Module
= nullptr;
5612 if (getDerived().parseModuleNameOpt(Module
))
5614 if (Module
== nullptr)
5616 return make
<SpecialName
>("initializer for module ", Module
);
5623 // <encoding> ::= <function name> <bare-function-type>
5624 // [`Q` <requires-clause expr>]
5626 // ::= <special-name>
5627 template <typename Derived
, typename Alloc
>
5628 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseEncoding(bool ParseParams
) {
5629 // The template parameters of an encoding are unrelated to those of the
5630 // enclosing context.
5631 SaveTemplateParams
SaveTemplateParamsScope(this);
5633 if (look() == 'G' || look() == 'T')
5634 return getDerived().parseSpecialName();
5636 auto IsEndOfEncoding
= [&] {
5637 // The set of chars that can potentially follow an <encoding> (none of which
5638 // can start a <type>). Enumerating these allows us to avoid speculative
5640 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5643 NameState
NameInfo(this);
5644 Node
*Name
= getDerived().parseName(&NameInfo
);
5645 if (Name
== nullptr)
5648 if (resolveForwardTemplateRefs(NameInfo
))
5651 if (IsEndOfEncoding())
5654 // ParseParams may be false at the top level only, when called from parse().
5655 // For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be
5656 // false when demangling 3fooILZ3BarEET_f but is always true when demangling
5664 Node
*Attrs
= nullptr;
5665 if (consumeIf("Ua9enable_ifI")) {
5666 size_t BeforeArgs
= Names
.size();
5667 while (!consumeIf('E')) {
5668 Node
*Arg
= getDerived().parseTemplateArg();
5671 Names
.push_back(Arg
);
5673 Attrs
= make
<EnableIfAttr
>(popTrailingNodeArray(BeforeArgs
));
5678 Node
*ReturnType
= nullptr;
5679 if (!NameInfo
.CtorDtorConversion
&& NameInfo
.EndsWithTemplateArgs
) {
5680 ReturnType
= getDerived().parseType();
5681 if (ReturnType
== nullptr)
5686 if (!consumeIf('v')) {
5687 size_t ParamsBegin
= Names
.size();
5689 Node
*Ty
= getDerived().parseType();
5693 const bool IsFirstParam
= ParamsBegin
== Names
.size();
5694 if (NameInfo
.HasExplicitObjectParameter
&& IsFirstParam
)
5695 Ty
= make
<ExplicitObjectParameter
>(Ty
);
5700 Names
.push_back(Ty
);
5701 } while (!IsEndOfEncoding() && look() != 'Q');
5702 Params
= popTrailingNodeArray(ParamsBegin
);
5705 Node
*Requires
= nullptr;
5706 if (consumeIf('Q')) {
5707 Requires
= getDerived().parseConstraintExpr();
5712 return make
<FunctionEncoding
>(ReturnType
, Name
, Params
, Attrs
, Requires
,
5713 NameInfo
.CVQualifiers
,
5714 NameInfo
.ReferenceQualifier
);
5717 template <class Float
>
5721 struct FloatData
<float>
5723 static const size_t mangled_size
= 8;
5724 static const size_t max_demangled_size
= 24;
5725 static constexpr const char* spec
= "%af";
5729 struct FloatData
<double>
5731 static const size_t mangled_size
= 16;
5732 static const size_t max_demangled_size
= 32;
5733 static constexpr const char* spec
= "%a";
5737 struct FloatData
<long double>
5739 #if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5740 defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \
5742 static const size_t mangled_size
= 32;
5743 #elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5744 static const size_t mangled_size
= 16;
5746 static const size_t mangled_size
= 20; // May need to be adjusted to 16 or 24 on other platforms
5748 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5749 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5750 // Negatives are one character longer than positives.
5751 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5752 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5753 static const size_t max_demangled_size
= 42;
5754 static constexpr const char *spec
= "%LaL";
5757 template <typename Alloc
, typename Derived
>
5758 template <class Float
>
5759 Node
*AbstractManglingParser
<Alloc
, Derived
>::parseFloatingLiteral() {
5760 const size_t N
= FloatData
<Float
>::mangled_size
;
5763 std::string_view
Data(First
, N
);
5765 if (!(C
>= '0' && C
<= '9') && !(C
>= 'a' && C
<= 'f'))
5768 if (!consumeIf('E'))
5770 return make
<FloatLiteralImpl
<Float
>>(Data
);
5773 // <seq-id> ::= <0-9A-Z>+
5774 template <typename Alloc
, typename Derived
>
5775 bool AbstractManglingParser
<Alloc
, Derived
>::parseSeqId(size_t *Out
) {
5776 if (!(look() >= '0' && look() <= '9') &&
5777 !(look() >= 'A' && look() <= 'Z'))
5782 if (look() >= '0' && look() <= '9') {
5784 Id
+= static_cast<size_t>(look() - '0');
5785 } else if (look() >= 'A' && look() <= 'Z') {
5787 Id
+= static_cast<size_t>(look() - 'A') + 10;
5796 // <substitution> ::= S <seq-id> _
5798 // <substitution> ::= Sa # ::std::allocator
5799 // <substitution> ::= Sb # ::std::basic_string
5800 // <substitution> ::= Ss # ::std::basic_string < char,
5801 // ::std::char_traits<char>,
5802 // ::std::allocator<char> >
5803 // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5804 // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5805 // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
5806 // The St case is handled specially in parseNestedName.
5807 template <typename Derived
, typename Alloc
>
5808 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseSubstitution() {
5809 if (!consumeIf('S'))
5812 if (look() >= 'a' && look() <= 'z') {
5813 SpecialSubKind Kind
;
5816 Kind
= SpecialSubKind::allocator
;
5819 Kind
= SpecialSubKind::basic_string
;
5822 Kind
= SpecialSubKind::iostream
;
5825 Kind
= SpecialSubKind::istream
;
5828 Kind
= SpecialSubKind::ostream
;
5831 Kind
= SpecialSubKind::string
;
5837 auto *SpecialSub
= make
<SpecialSubstitution
>(Kind
);
5841 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5842 // has ABI tags, the tags are appended to the substitution; the result is a
5843 // substitutable component.
5844 Node
*WithTags
= getDerived().parseAbiTags(SpecialSub
);
5845 if (WithTags
!= SpecialSub
) {
5846 Subs
.push_back(WithTags
);
5847 SpecialSub
= WithTags
;
5853 if (consumeIf('_')) {
5861 if (parseSeqId(&Index
))
5864 if (!consumeIf('_') || Index
>= Subs
.size())
5869 // <template-param> ::= T_ # first template parameter
5870 // ::= T <parameter-2 non-negative number> _
5871 // ::= TL <level-1> __
5872 // ::= TL <level-1> _ <parameter-2 non-negative number> _
5873 template <typename Derived
, typename Alloc
>
5874 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateParam() {
5875 const char *Begin
= First
;
5876 if (!consumeIf('T'))
5880 if (consumeIf('L')) {
5881 if (parsePositiveInteger(&Level
))
5884 if (!consumeIf('_'))
5889 if (!consumeIf('_')) {
5890 if (parsePositiveInteger(&Index
))
5893 if (!consumeIf('_'))
5897 // We don't track enclosing template parameter levels well enough to reliably
5898 // substitute them all within a <constraint-expression>, so print the
5899 // parameter numbering instead for now.
5900 // TODO: Track all enclosing template parameters and substitute them here.
5901 if (HasIncompleteTemplateParameterTracking
) {
5902 return make
<NameType
>(std::string_view(Begin
, First
- 1 - Begin
));
5905 // If we're in a context where this <template-param> refers to a
5906 // <template-arg> further ahead in the mangled name (currently just conversion
5907 // operator types), then we should only look it up in the right context.
5908 // This can only happen at the outermost level.
5909 if (PermitForwardTemplateReferences
&& Level
== 0) {
5910 Node
*ForwardRef
= make
<ForwardTemplateReference
>(Index
);
5913 DEMANGLE_ASSERT(ForwardRef
->getKind() == Node::KForwardTemplateReference
,
5915 ForwardTemplateRefs
.push_back(
5916 static_cast<ForwardTemplateReference
*>(ForwardRef
));
5920 if (Level
>= TemplateParams
.size() || !TemplateParams
[Level
] ||
5921 Index
>= TemplateParams
[Level
]->size()) {
5922 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5923 // list are mangled as the corresponding artificial template type parameter.
5924 if (ParsingLambdaParamsAtLevel
== Level
&& Level
<= TemplateParams
.size()) {
5925 // This will be popped by the ScopedTemplateParamList in
5926 // parseUnnamedTypeName.
5927 if (Level
== TemplateParams
.size())
5928 TemplateParams
.push_back(nullptr);
5929 return make
<NameType
>("auto");
5935 return (*TemplateParams
[Level
])[Index
];
5938 // <template-param-decl> ::= Ty # type parameter
5939 // ::= Tk <concept name> [<template-args>] # constrained type parameter
5940 // ::= Tn <type> # non-type parameter
5941 // ::= Tt <template-param-decl>* E # template parameter
5942 // ::= Tp <template-param-decl> # parameter pack
5943 template <typename Derived
, typename Alloc
>
5944 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateParamDecl(
5945 TemplateParamList
*Params
) {
5946 auto InventTemplateParamName
= [&](TemplateParamKind Kind
) {
5947 unsigned Index
= NumSyntheticTemplateParameters
[(int)Kind
]++;
5948 Node
*N
= make
<SyntheticTemplateParamName
>(Kind
, Index
);
5950 Params
->push_back(N
);
5954 if (consumeIf("Ty")) {
5955 Node
*Name
= InventTemplateParamName(TemplateParamKind::Type
);
5958 return make
<TypeTemplateParamDecl
>(Name
);
5961 if (consumeIf("Tk")) {
5962 // We don't track enclosing template parameter levels well enough to
5963 // reliably demangle template parameter substitutions, so print an arbitrary
5964 // string in place of a parameter for now.
5965 // TODO: Track all enclosing template parameters and demangle substitutions.
5966 ScopedOverride
<bool> SaveIncompleteTemplateParameterTrackingExpr(
5967 HasIncompleteTemplateParameterTracking
, true);
5968 Node
*Constraint
= getDerived().parseName();
5971 Node
*Name
= InventTemplateParamName(TemplateParamKind::Type
);
5974 return make
<ConstrainedTypeTemplateParamDecl
>(Constraint
, Name
);
5977 if (consumeIf("Tn")) {
5978 Node
*Name
= InventTemplateParamName(TemplateParamKind::NonType
);
5981 Node
*Type
= parseType();
5984 return make
<NonTypeTemplateParamDecl
>(Name
, Type
);
5987 if (consumeIf("Tt")) {
5988 Node
*Name
= InventTemplateParamName(TemplateParamKind::Template
);
5991 size_t ParamsBegin
= Names
.size();
5992 ScopedTemplateParamList
TemplateTemplateParamParams(this);
5993 Node
*Requires
= nullptr;
5994 while (!consumeIf('E')) {
5995 Node
*P
= parseTemplateParamDecl(TemplateTemplateParamParams
.params());
5999 if (consumeIf('Q')) {
6000 Requires
= getDerived().parseConstraintExpr();
6001 if (Requires
== nullptr || !consumeIf('E'))
6006 NodeArray InnerParams
= popTrailingNodeArray(ParamsBegin
);
6007 return make
<TemplateTemplateParamDecl
>(Name
, InnerParams
, Requires
);
6010 if (consumeIf("Tp")) {
6011 Node
*P
= parseTemplateParamDecl(Params
);
6014 return make
<TemplateParamPackDecl
>(P
);
6020 // <template-arg> ::= <type> # type or template
6021 // ::= X <expression> E # expression
6022 // ::= <expr-primary> # simple expressions
6023 // ::= J <template-arg>* E # argument pack
6024 // ::= LZ <encoding> E # extension
6025 // ::= <template-param-decl> <template-arg>
6026 template <typename Derived
, typename Alloc
>
6027 Node
*AbstractManglingParser
<Derived
, Alloc
>::parseTemplateArg() {
6031 Node
*Arg
= getDerived().parseExpr();
6032 if (Arg
== nullptr || !consumeIf('E'))
6038 size_t ArgsBegin
= Names
.size();
6039 while (!consumeIf('E')) {
6040 Node
*Arg
= getDerived().parseTemplateArg();
6043 Names
.push_back(Arg
);
6045 NodeArray Args
= popTrailingNodeArray(ArgsBegin
);
6046 return make
<TemplateArgumentPack
>(Args
);
6049 // ::= LZ <encoding> E # extension
6050 if (look(1) == 'Z') {
6052 Node
*Arg
= getDerived().parseEncoding();
6053 if (Arg
== nullptr || !consumeIf('E'))
6057 // ::= <expr-primary> # simple expressions
6058 return getDerived().parseExprPrimary();
6061 // Either <template-param> or a <template-param-decl> <template-arg>.
6062 if (!getDerived().isTemplateParamDecl())
6063 return getDerived().parseType();
6064 Node
*Param
= getDerived().parseTemplateParamDecl(nullptr);
6067 Node
*Arg
= getDerived().parseTemplateArg();
6070 return make
<TemplateParamQualifiedArg
>(Param
, Arg
);
6073 return getDerived().parseType();
6077 // <template-args> ::= I <template-arg>* [Q <requires-clause expr>] E
6078 // extension, the abi says <template-arg>+
6079 template <typename Derived
, typename Alloc
>
6081 AbstractManglingParser
<Derived
, Alloc
>::parseTemplateArgs(bool TagTemplates
) {
6082 if (!consumeIf('I'))
6085 // <template-params> refer to the innermost <template-args>. Clear out any
6086 // outer args that we may have inserted into TemplateParams.
6088 TemplateParams
.clear();
6089 TemplateParams
.push_back(&OuterTemplateParams
);
6090 OuterTemplateParams
.clear();
6093 size_t ArgsBegin
= Names
.size();
6094 Node
*Requires
= nullptr;
6095 while (!consumeIf('E')) {
6097 Node
*Arg
= getDerived().parseTemplateArg();
6100 Names
.push_back(Arg
);
6101 Node
*TableEntry
= Arg
;
6102 if (Arg
->getKind() == Node::KTemplateParamQualifiedArg
) {
6104 static_cast<TemplateParamQualifiedArg
*>(TableEntry
)->getArg();
6106 if (Arg
->getKind() == Node::KTemplateArgumentPack
) {
6107 TableEntry
= make
<ParameterPack
>(
6108 static_cast<TemplateArgumentPack
*>(TableEntry
)->getElements());
6112 OuterTemplateParams
.push_back(TableEntry
);
6114 Node
*Arg
= getDerived().parseTemplateArg();
6117 Names
.push_back(Arg
);
6119 if (consumeIf('Q')) {
6120 Requires
= getDerived().parseConstraintExpr();
6121 if (!Requires
|| !consumeIf('E'))
6126 return make
<TemplateArgs
>(popTrailingNodeArray(ArgsBegin
), Requires
);
6129 // <mangled-name> ::= _Z <encoding>
6131 // extension ::= ___Z <encoding> _block_invoke
6132 // extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
6133 // extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
6134 template <typename Derived
, typename Alloc
>
6135 Node
*AbstractManglingParser
<Derived
, Alloc
>::parse(bool ParseParams
) {
6136 if (consumeIf("_Z") || consumeIf("__Z")) {
6137 Node
*Encoding
= getDerived().parseEncoding(ParseParams
);
6138 if (Encoding
== nullptr)
6140 if (look() == '.') {
6142 make
<DotSuffix
>(Encoding
, std::string_view(First
, Last
- First
));
6150 if (consumeIf("___Z") || consumeIf("____Z")) {
6151 Node
*Encoding
= getDerived().parseEncoding(ParseParams
);
6152 if (Encoding
== nullptr || !consumeIf("_block_invoke"))
6154 bool RequireNumber
= consumeIf('_');
6155 if (parseNumber().empty() && RequireNumber
)
6161 return make
<SpecialName
>("invocation function for block in ", Encoding
);
6164 Node
*Ty
= getDerived().parseType();
6170 template <typename Alloc
>
6171 struct ManglingParser
: AbstractManglingParser
<ManglingParser
<Alloc
>, Alloc
> {
6172 using AbstractManglingParser
<ManglingParser
<Alloc
>,
6173 Alloc
>::AbstractManglingParser
;
6176 DEMANGLE_NAMESPACE_END
6178 #if defined(__clang__)
6179 #pragma clang diagnostic pop
6182 #endif // DEMANGLE_ITANIUMDEMANGLE_H