1//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
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.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef DEMANGLE_ITANIUMDEMANGLE_H
17#define DEMANGLE_ITANIUMDEMANGLE_H
18
19#include "DemangleConfig.h"
20#include "StringViewExtras.h"
21#include "Utility.h"
22#include <__cxxabi_config.h>
23#include <algorithm>
24#include <cctype>
25#include <cstdio>
26#include <cstdlib>
27#include <cstring>
28#include <limits>
29#include <new>
30#include <string_view>
31#include <type_traits>
32#include <utility>
33
34#ifdef _LIBCXXABI_COMPILER_CLANG
35#pragma clang diagnostic push
36#pragma clang diagnostic ignored "-Wunused-template"
37#endif
38
39DEMANGLE_NAMESPACE_BEGIN
40
41template <class T, size_t N> class PODSmallVector {
42 static_assert(std::is_trivial<T>::value,
43 "T is required to be a trivial type");
44 T *First = nullptr;
45 T *Last = nullptr;
46 T *Cap = nullptr;
47 T Inline[N] = {};
48
49 bool isInline() const { return First == Inline; }
50
51 void clearInline() {
52 First = Inline;
53 Last = Inline;
54 Cap = Inline + N;
55 }
56
57 void reserve(size_t NewCap) {
58 size_t S = size();
59 if (isInline()) {
60 auto *Tmp = static_cast<T *>(std::malloc(size: NewCap * sizeof(T)));
61 if (Tmp == nullptr)
62 std::abort();
63 std::copy(First, Last, Tmp);
64 First = Tmp;
65 } else {
66 First = static_cast<T *>(std::realloc(ptr: First, size: NewCap * sizeof(T)));
67 if (First == nullptr)
68 std::abort();
69 }
70 Last = First + S;
71 Cap = First + NewCap;
72 }
73
74public:
75 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
76
77 PODSmallVector(const PODSmallVector &) = delete;
78 PODSmallVector &operator=(const PODSmallVector &) = delete;
79
80 PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {
81 if (Other.isInline()) {
82 std::copy(Other.begin(), Other.end(), First);
83 Last = First + Other.size();
84 Other.clear();
85 return;
86 }
87
88 First = Other.First;
89 Last = Other.Last;
90 Cap = Other.Cap;
91 Other.clearInline();
92 }
93
94 PODSmallVector &operator=(PODSmallVector &&Other) {
95 if (Other.isInline()) {
96 if (!isInline()) {
97 std::free(ptr: First);
98 clearInline();
99 }
100 std::copy(Other.begin(), Other.end(), First);
101 Last = First + Other.size();
102 Other.clear();
103 return *this;
104 }
105
106 if (isInline()) {
107 First = Other.First;
108 Last = Other.Last;
109 Cap = Other.Cap;
110 Other.clearInline();
111 return *this;
112 }
113
114 std::swap(First, Other.First);
115 std::swap(Last, Other.Last);
116 std::swap(Cap, Other.Cap);
117 Other.clear();
118 return *this;
119 }
120
121 // NOLINTNEXTLINE(readability-identifier-naming)
122 void push_back(const T &Elem) {
123 if (Last == Cap)
124 reserve(NewCap: size() * 2);
125 *Last++ = Elem;
126 }
127
128 // NOLINTNEXTLINE(readability-identifier-naming)
129 void pop_back() {
130 DEMANGLE_ASSERT(Last != First, "Popping empty vector!");
131 --Last;
132 }
133
134 void shrinkToSize(size_t Index) {
135 DEMANGLE_ASSERT(Index <= size(), "shrinkToSize() can't expand!");
136 Last = First + Index;
137 }
138
139 T *begin() { return First; }
140 T *end() { return Last; }
141
142 bool empty() const { return First == Last; }
143 size_t size() const { return static_cast<size_t>(Last - First); }
144 T &back() {
145 DEMANGLE_ASSERT(Last != First, "Calling back() on empty vector!");
146 return *(Last - 1);
147 }
148 T &operator[](size_t Index) {
149 DEMANGLE_ASSERT(Index < size(), "Invalid access!");
150 return *(begin() + Index);
151 }
152 void clear() { Last = First; }
153
154 ~PODSmallVector() {
155 if (!isInline())
156 std::free(ptr: First);
157 }
158};
159
160// Base class of all AST nodes. The AST is built by the parser, then is
161// traversed by the printLeft/Right functions to produce a demangled string.
162class Node {
163public:
164 enum Kind : unsigned char {
165#define NODE(NodeKind) K##NodeKind,
166#include "ItaniumNodes.def"
167 };
168
169 /// Three-way bool to track a cached value. Unknown is possible if this node
170 /// has an unexpanded parameter pack below it that may affect this cache.
171 enum class Cache : unsigned char { Yes, No, Unknown, };
172
173 /// Operator precedence for expression nodes. Used to determine required
174 /// parens in expression emission.
175 enum class Prec {
176 Primary,
177 Postfix,
178 Unary,
179 Cast,
180 PtrMem,
181 Multiplicative,
182 Additive,
183 Shift,
184 Spaceship,
185 Relational,
186 Equality,
187 And,
188 Xor,
189 Ior,
190 AndIf,
191 OrIf,
192 Conditional,
193 Assign,
194 Comma,
195 Default,
196 };
197
198private:
199 Kind K;
200
201 Prec Precedence : 6;
202
203 // FIXME: Make these protected.
204public:
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;
208
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;
212
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;
216
217public:
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_,
226 FunctionCache_) {}
227
228 /// Visit the most-derived object corresponding to this object.
229 template<typename Fn> void visit(Fn F) const;
230
231 // The following function is provided by all derived classes:
232 //
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;
236
237 bool hasRHSComponent(OutputBuffer &OB) const {
238 if (RHSComponentCache != Cache::Unknown)
239 return RHSComponentCache == Cache::Yes;
240 return hasRHSComponentSlow(OB);
241 }
242
243 bool hasArray(OutputBuffer &OB) const {
244 if (ArrayCache != Cache::Unknown)
245 return ArrayCache == Cache::Yes;
246 return hasArraySlow(OB);
247 }
248
249 bool hasFunction(OutputBuffer &OB) const {
250 if (FunctionCache != Cache::Unknown)
251 return FunctionCache == Cache::Yes;
252 return hasFunctionSlow(OB);
253 }
254
255 Kind getKind() const { return K; }
256
257 Prec getPrecedence() const { return Precedence; }
258
259 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
260 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
261 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
262
263 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
264 // get at a node that actually represents some concrete syntax.
265 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }
266
267 // Print this node as an expression operand, surrounding it in parentheses if
268 // its precedence is [Strictly] weaker than P.
269 void printAsOperand(OutputBuffer &OB, Prec P = Prec::Default,
270 bool StrictlyWorse = false) const {
271 bool Paren =
272 unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse);
273 if (Paren)
274 OB.printOpen();
275 print(OB);
276 if (Paren)
277 OB.printClose();
278 }
279
280 void print(OutputBuffer &OB) const {
281 printLeft(OB);
282 if (RHSComponentCache != Cache::No)
283 printRight(OB);
284 }
285
286 // Print the "left" side of this Node into OutputBuffer.
287 virtual void printLeft(OutputBuffer &) const = 0;
288
289 // Print the "right". This distinction is necessary to represent C++ types
290 // that appear on the RHS of their subtype, such as arrays or functions.
291 // Since most types don't have such a component, provide a default
292 // implementation.
293 virtual void printRight(OutputBuffer &) const {}
294
295 virtual std::string_view getBaseName() const { return {}; }
296
297 // Silence compiler warnings, this dtor will never be called.
298 virtual ~Node() = default;
299
300#ifndef NDEBUG
301 DEMANGLE_DUMP_METHOD void dump() const;
302#endif
303};
304
305class NodeArray {
306 Node **Elements;
307 size_t NumElements;
308
309public:
310 NodeArray() : Elements(nullptr), NumElements(0) {}
311 NodeArray(Node **Elements_, size_t NumElements_)
312 : Elements(Elements_), NumElements(NumElements_) {}
313
314 bool empty() const { return NumElements == 0; }
315 size_t size() const { return NumElements; }
316
317 Node **begin() const { return Elements; }
318 Node **end() const { return Elements + NumElements; }
319
320 Node *operator[](size_t Idx) const { return Elements[Idx]; }
321
322 void printWithComma(OutputBuffer &OB) const {
323 bool FirstElement = true;
324 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
325 size_t BeforeComma = OB.getCurrentPosition();
326 if (!FirstElement)
327 OB += ", ";
328 size_t AfterComma = OB.getCurrentPosition();
329 Elements[Idx]->printAsOperand(OB, P: Node::Prec::Comma);
330
331 // Elements[Idx] is an empty parameter pack expansion, we should erase the
332 // comma we just printed.
333 if (AfterComma == OB.getCurrentPosition()) {
334 OB.setCurrentPosition(BeforeComma);
335 continue;
336 }
337
338 FirstElement = false;
339 }
340 }
341};
342
343struct NodeArrayNode : Node {
344 NodeArray Array;
345 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
346
347 template<typename Fn> void match(Fn F) const { F(Array); }
348
349 void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
350};
351
352class DotSuffix final : public Node {
353 const Node *Prefix;
354 const std::string_view Suffix;
355
356public:
357 DotSuffix(const Node *Prefix_, std::string_view Suffix_)
358 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
359
360 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
361
362 void printLeft(OutputBuffer &OB) const override {
363 Prefix->print(OB);
364 OB += " (";
365 OB += Suffix;
366 OB += ")";
367 }
368};
369
370class VendorExtQualType final : public Node {
371 const Node *Ty;
372 std::string_view Ext;
373 const Node *TA;
374
375public:
376 VendorExtQualType(const Node *Ty_, std::string_view Ext_, const Node *TA_)
377 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
378
379 const Node *getTy() const { return Ty; }
380 std::string_view getExt() const { return Ext; }
381 const Node *getTA() const { return TA; }
382
383 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
384
385 void printLeft(OutputBuffer &OB) const override {
386 Ty->print(OB);
387 OB += " ";
388 OB += Ext;
389 if (TA != nullptr)
390 TA->print(OB);
391 }
392};
393
394enum FunctionRefQual : unsigned char {
395 FrefQualNone,
396 FrefQualLValue,
397 FrefQualRValue,
398};
399
400enum Qualifiers {
401 QualNone = 0,
402 QualConst = 0x1,
403 QualVolatile = 0x2,
404 QualRestrict = 0x4,
405};
406
407inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
408 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
409}
410
411class QualType final : public Node {
412protected:
413 const Qualifiers Quals;
414 const Node *Child;
415
416 void printQuals(OutputBuffer &OB) const {
417 if (Quals & QualConst)
418 OB += " const";
419 if (Quals & QualVolatile)
420 OB += " volatile";
421 if (Quals & QualRestrict)
422 OB += " restrict";
423 }
424
425public:
426 QualType(const Node *Child_, Qualifiers Quals_)
427 : Node(KQualType, Child_->RHSComponentCache,
428 Child_->ArrayCache, Child_->FunctionCache),
429 Quals(Quals_), Child(Child_) {}
430
431 Qualifiers getQuals() const { return Quals; }
432 const Node *getChild() const { return Child; }
433
434 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
435
436 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
437 return Child->hasRHSComponent(OB);
438 }
439 bool hasArraySlow(OutputBuffer &OB) const override {
440 return Child->hasArray(OB);
441 }
442 bool hasFunctionSlow(OutputBuffer &OB) const override {
443 return Child->hasFunction(OB);
444 }
445
446 void printLeft(OutputBuffer &OB) const override {
447 Child->printLeft(OB);
448 printQuals(OB);
449 }
450
451 void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
452};
453
454class ConversionOperatorType final : public Node {
455 const Node *Ty;
456
457public:
458 ConversionOperatorType(const Node *Ty_)
459 : Node(KConversionOperatorType), Ty(Ty_) {}
460
461 template<typename Fn> void match(Fn F) const { F(Ty); }
462
463 void printLeft(OutputBuffer &OB) const override {
464 OB += "operator ";
465 Ty->print(OB);
466 }
467};
468
469class PostfixQualifiedType final : public Node {
470 const Node *Ty;
471 const std::string_view Postfix;
472
473public:
474 PostfixQualifiedType(const Node *Ty_, std::string_view Postfix_)
475 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
476
477 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
478
479 void printLeft(OutputBuffer &OB) const override {
480 Ty->printLeft(OB);
481 OB += Postfix;
482 }
483};
484
485class NameType final : public Node {
486 const std::string_view Name;
487
488public:
489 NameType(std::string_view Name_) : Node(KNameType), Name(Name_) {}
490
491 template<typename Fn> void match(Fn F) const { F(Name); }
492
493 std::string_view getName() const { return Name; }
494 std::string_view getBaseName() const override { return Name; }
495
496 void printLeft(OutputBuffer &OB) const override { OB += Name; }
497};
498
499class BitIntType final : public Node {
500 const Node *Size;
501 bool Signed;
502
503public:
504 BitIntType(const Node *Size_, bool Signed_)
505 : Node(KBitIntType), Size(Size_), Signed(Signed_) {}
506
507 template <typename Fn> void match(Fn F) const { F(Size, Signed); }
508
509 void printLeft(OutputBuffer &OB) const override {
510 if (!Signed)
511 OB += "unsigned ";
512 OB += "_BitInt";
513 OB.printOpen();
514 Size->printAsOperand(OB);
515 OB.printClose();
516 }
517};
518
519class ElaboratedTypeSpefType : public Node {
520 std::string_view Kind;
521 Node *Child;
522public:
523 ElaboratedTypeSpefType(std::string_view Kind_, Node *Child_)
524 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
525
526 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
527
528 void printLeft(OutputBuffer &OB) const override {
529 OB += Kind;
530 OB += ' ';
531 Child->print(OB);
532 }
533};
534
535class TransformedType : public Node {
536 std::string_view Transform;
537 Node *BaseType;
538public:
539 TransformedType(std::string_view Transform_, Node *BaseType_)
540 : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}
541
542 template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }
543
544 void printLeft(OutputBuffer &OB) const override {
545 OB += Transform;
546 OB += '(';
547 BaseType->print(OB);
548 OB += ')';
549 }
550};
551
552struct AbiTagAttr : Node {
553 Node *Base;
554 std::string_view Tag;
555
556 AbiTagAttr(Node *Base_, std::string_view Tag_)
557 : Node(KAbiTagAttr, Base_->RHSComponentCache, Base_->ArrayCache,
558 Base_->FunctionCache),
559 Base(Base_), Tag(Tag_) {}
560
561 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
562
563 std::string_view getBaseName() const override { return Base->getBaseName(); }
564
565 void printLeft(OutputBuffer &OB) const override {
566 Base->printLeft(OB);
567 OB += "[abi:";
568 OB += Tag;
569 OB += "]";
570 }
571};
572
573class EnableIfAttr : public Node {
574 NodeArray Conditions;
575public:
576 EnableIfAttr(NodeArray Conditions_)
577 : Node(KEnableIfAttr), Conditions(Conditions_) {}
578
579 template<typename Fn> void match(Fn F) const { F(Conditions); }
580
581 void printLeft(OutputBuffer &OB) const override {
582 OB += " [enable_if:";
583 Conditions.printWithComma(OB);
584 OB += ']';
585 }
586};
587
588class ObjCProtoName : public Node {
589 const Node *Ty;
590 std::string_view Protocol;
591
592 friend class PointerType;
593
594public:
595 ObjCProtoName(const Node *Ty_, std::string_view Protocol_)
596 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
597
598 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
599
600 bool isObjCObject() const {
601 return Ty->getKind() == KNameType &&
602 static_cast<const NameType *>(Ty)->getName() == "objc_object";
603 }
604
605 void printLeft(OutputBuffer &OB) const override {
606 Ty->print(OB);
607 OB += "<";
608 OB += Protocol;
609 OB += ">";
610 }
611};
612
613class PointerType final : public Node {
614 const Node *Pointee;
615
616public:
617 PointerType(const Node *Pointee_)
618 : Node(KPointerType, Pointee_->RHSComponentCache),
619 Pointee(Pointee_) {}
620
621 const Node *getPointee() const { return Pointee; }
622
623 template<typename Fn> void match(Fn F) const { F(Pointee); }
624
625 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
626 return Pointee->hasRHSComponent(OB);
627 }
628
629 void printLeft(OutputBuffer &OB) const override {
630 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
631 if (Pointee->getKind() != KObjCProtoName ||
632 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
633 Pointee->printLeft(OB);
634 if (Pointee->hasArray(OB))
635 OB += " ";
636 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
637 OB += "(";
638 OB += "*";
639 } else {
640 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
641 OB += "id<";
642 OB += objcProto->Protocol;
643 OB += ">";
644 }
645 }
646
647 void printRight(OutputBuffer &OB) const override {
648 if (Pointee->getKind() != KObjCProtoName ||
649 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
650 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
651 OB += ")";
652 Pointee->printRight(OB);
653 }
654 }
655};
656
657enum class ReferenceKind {
658 LValue,
659 RValue,
660};
661
662// Represents either a LValue or an RValue reference type.
663class ReferenceType : public Node {
664 const Node *Pointee;
665 ReferenceKind RK;
666
667 mutable bool Printing = false;
668
669 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
670 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
671 // other combination collapses to a lvalue ref.
672 //
673 // A combination of a TemplateForwardReference and a back-ref Substitution
674 // from an ill-formed string may have created a cycle; use cycle detection to
675 // avoid looping forever.
676 std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {
677 auto SoFar = std::make_pair(x: RK, y: Pointee);
678 // Track the chain of nodes for the Floyd's 'tortoise and hare'
679 // cycle-detection algorithm, since getSyntaxNode(S) is impure
680 PODSmallVector<const Node *, 8> Prev;
681 for (;;) {
682 const Node *SN = SoFar.second->getSyntaxNode(OB);
683 if (SN->getKind() != KReferenceType)
684 break;
685 auto *RT = static_cast<const ReferenceType *>(SN);
686 SoFar.second = RT->Pointee;
687 SoFar.first = std::min(a: SoFar.first, b: RT->RK);
688
689 // The middle of Prev is the 'slow' pointer moving at half speed
690 Prev.push_back(Elem: SoFar.second);
691 if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {
692 // Cycle detected
693 SoFar.second = nullptr;
694 break;
695 }
696 }
697 return SoFar;
698 }
699
700public:
701 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
702 : Node(KReferenceType, Pointee_->RHSComponentCache),
703 Pointee(Pointee_), RK(RK_) {}
704
705 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
706
707 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
708 return Pointee->hasRHSComponent(OB);
709 }
710
711 void printLeft(OutputBuffer &OB) const override {
712 if (Printing)
713 return;
714 ScopedOverride<bool> SavePrinting(Printing, true);
715 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
716 if (!Collapsed.second)
717 return;
718 Collapsed.second->printLeft(OB);
719 if (Collapsed.second->hasArray(OB))
720 OB += " ";
721 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
722 OB += "(";
723
724 OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
725 }
726 void printRight(OutputBuffer &OB) const override {
727 if (Printing)
728 return;
729 ScopedOverride<bool> SavePrinting(Printing, true);
730 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
731 if (!Collapsed.second)
732 return;
733 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
734 OB += ")";
735 Collapsed.second->printRight(OB);
736 }
737};
738
739class PointerToMemberType final : public Node {
740 const Node *ClassType;
741 const Node *MemberType;
742
743public:
744 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
745 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
746 ClassType(ClassType_), MemberType(MemberType_) {}
747
748 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
749
750 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
751 return MemberType->hasRHSComponent(OB);
752 }
753
754 void printLeft(OutputBuffer &OB) const override {
755 MemberType->printLeft(OB);
756 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
757 OB += "(";
758 else
759 OB += " ";
760 ClassType->print(OB);
761 OB += "::*";
762 }
763
764 void printRight(OutputBuffer &OB) const override {
765 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
766 OB += ")";
767 MemberType->printRight(OB);
768 }
769};
770
771class ArrayType final : public Node {
772 const Node *Base;
773 Node *Dimension;
774
775public:
776 ArrayType(const Node *Base_, Node *Dimension_)
777 : Node(KArrayType,
778 /*RHSComponentCache=*/Cache::Yes,
779 /*ArrayCache=*/Cache::Yes),
780 Base(Base_), Dimension(Dimension_) {}
781
782 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
783
784 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
785 bool hasArraySlow(OutputBuffer &) const override { return true; }
786
787 void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
788
789 void printRight(OutputBuffer &OB) const override {
790 if (OB.back() != ']')
791 OB += " ";
792 OB += "[";
793 if (Dimension)
794 Dimension->print(OB);
795 OB += "]";
796 Base->printRight(OB);
797 }
798};
799
800class FunctionType final : public Node {
801 const Node *Ret;
802 NodeArray Params;
803 Qualifiers CVQuals;
804 FunctionRefQual RefQual;
805 const Node *ExceptionSpec;
806
807public:
808 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
809 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
810 : Node(KFunctionType,
811 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
812 /*FunctionCache=*/Cache::Yes),
813 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
814 ExceptionSpec(ExceptionSpec_) {}
815
816 template<typename Fn> void match(Fn F) const {
817 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
818 }
819
820 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
821 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
822
823 // Handle C++'s ... quirky decl grammar by using the left & right
824 // distinction. Consider:
825 // int (*f(float))(char) {}
826 // f is a function that takes a float and returns a pointer to a function
827 // that takes a char and returns an int. If we're trying to print f, start
828 // by printing out the return types's left, then print our parameters, then
829 // finally print right of the return type.
830 void printLeft(OutputBuffer &OB) const override {
831 Ret->printLeft(OB);
832 OB += " ";
833 }
834
835 void printRight(OutputBuffer &OB) const override {
836 OB.printOpen();
837 Params.printWithComma(OB);
838 OB.printClose();
839 Ret->printRight(OB);
840
841 if (CVQuals & QualConst)
842 OB += " const";
843 if (CVQuals & QualVolatile)
844 OB += " volatile";
845 if (CVQuals & QualRestrict)
846 OB += " restrict";
847
848 if (RefQual == FrefQualLValue)
849 OB += " &";
850 else if (RefQual == FrefQualRValue)
851 OB += " &&";
852
853 if (ExceptionSpec != nullptr) {
854 OB += ' ';
855 ExceptionSpec->print(OB);
856 }
857 }
858};
859
860class NoexceptSpec : public Node {
861 const Node *E;
862public:
863 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
864
865 template<typename Fn> void match(Fn F) const { F(E); }
866
867 void printLeft(OutputBuffer &OB) const override {
868 OB += "noexcept";
869 OB.printOpen();
870 E->printAsOperand(OB);
871 OB.printClose();
872 }
873};
874
875class DynamicExceptionSpec : public Node {
876 NodeArray Types;
877public:
878 DynamicExceptionSpec(NodeArray Types_)
879 : Node(KDynamicExceptionSpec), Types(Types_) {}
880
881 template<typename Fn> void match(Fn F) const { F(Types); }
882
883 void printLeft(OutputBuffer &OB) const override {
884 OB += "throw";
885 OB.printOpen();
886 Types.printWithComma(OB);
887 OB.printClose();
888 }
889};
890
891/// Represents the explicitly named object parameter.
892/// E.g.,
893/// \code{.cpp}
894/// struct Foo {
895/// void bar(this Foo && self);
896/// };
897/// \endcode
898class ExplicitObjectParameter final : public Node {
899 Node *Base;
900
901public:
902 ExplicitObjectParameter(Node *Base_)
903 : Node(KExplicitObjectParameter), Base(Base_) {
904 DEMANGLE_ASSERT(
905 Base != nullptr,
906 "Creating an ExplicitObjectParameter without a valid Base Node.");
907 }
908
909 template <typename Fn> void match(Fn F) const { F(Base); }
910
911 void printLeft(OutputBuffer &OB) const override {
912 OB += "this ";
913 Base->print(OB);
914 }
915};
916
917class FunctionEncoding final : public Node {
918 const Node *Ret;
919 const Node *Name;
920 NodeArray Params;
921 const Node *Attrs;
922 const Node *Requires;
923 Qualifiers CVQuals;
924 FunctionRefQual RefQual;
925
926public:
927 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
928 const Node *Attrs_, const Node *Requires_,
929 Qualifiers CVQuals_, FunctionRefQual RefQual_)
930 : Node(KFunctionEncoding,
931 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
932 /*FunctionCache=*/Cache::Yes),
933 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
934 Requires(Requires_), CVQuals(CVQuals_), RefQual(RefQual_) {}
935
936 template<typename Fn> void match(Fn F) const {
937 F(Ret, Name, Params, Attrs, Requires, CVQuals, RefQual);
938 }
939
940 Qualifiers getCVQuals() const { return CVQuals; }
941 FunctionRefQual getRefQual() const { return RefQual; }
942 NodeArray getParams() const { return Params; }
943 const Node *getReturnType() const { return Ret; }
944
945 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
946 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
947
948 const Node *getName() const { return Name; }
949
950 void printLeft(OutputBuffer &OB) const override {
951 if (Ret) {
952 Ret->printLeft(OB);
953 if (!Ret->hasRHSComponent(OB))
954 OB += " ";
955 }
956 Name->print(OB);
957 }
958
959 void printRight(OutputBuffer &OB) const override {
960 OB.printOpen();
961 Params.printWithComma(OB);
962 OB.printClose();
963 if (Ret)
964 Ret->printRight(OB);
965
966 if (CVQuals & QualConst)
967 OB += " const";
968 if (CVQuals & QualVolatile)
969 OB += " volatile";
970 if (CVQuals & QualRestrict)
971 OB += " restrict";
972
973 if (RefQual == FrefQualLValue)
974 OB += " &";
975 else if (RefQual == FrefQualRValue)
976 OB += " &&";
977
978 if (Attrs != nullptr)
979 Attrs->print(OB);
980
981 if (Requires != nullptr) {
982 OB += " requires ";
983 Requires->print(OB);
984 }
985 }
986};
987
988class LiteralOperator : public Node {
989 const Node *OpName;
990
991public:
992 LiteralOperator(const Node *OpName_)
993 : Node(KLiteralOperator), OpName(OpName_) {}
994
995 template<typename Fn> void match(Fn F) const { F(OpName); }
996
997 void printLeft(OutputBuffer &OB) const override {
998 OB += "operator\"\" ";
999 OpName->print(OB);
1000 }
1001};
1002
1003class SpecialName final : public Node {
1004 const std::string_view Special;
1005 const Node *Child;
1006
1007public:
1008 SpecialName(std::string_view Special_, const Node *Child_)
1009 : Node(KSpecialName), Special(Special_), Child(Child_) {}
1010
1011 template<typename Fn> void match(Fn F) const { F(Special, Child); }
1012
1013 void printLeft(OutputBuffer &OB) const override {
1014 OB += Special;
1015 Child->print(OB);
1016 }
1017};
1018
1019class CtorVtableSpecialName final : public Node {
1020 const Node *FirstType;
1021 const Node *SecondType;
1022
1023public:
1024 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
1025 : Node(KCtorVtableSpecialName),
1026 FirstType(FirstType_), SecondType(SecondType_) {}
1027
1028 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
1029
1030 void printLeft(OutputBuffer &OB) const override {
1031 OB += "construction vtable for ";
1032 FirstType->print(OB);
1033 OB += "-in-";
1034 SecondType->print(OB);
1035 }
1036};
1037
1038struct NestedName : Node {
1039 Node *Qual;
1040 Node *Name;
1041
1042 NestedName(Node *Qual_, Node *Name_)
1043 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
1044
1045 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
1046
1047 std::string_view getBaseName() const override { return Name->getBaseName(); }
1048
1049 void printLeft(OutputBuffer &OB) const override {
1050 Qual->print(OB);
1051 OB += "::";
1052 Name->print(OB);
1053 }
1054};
1055
1056struct MemberLikeFriendName : Node {
1057 Node *Qual;
1058 Node *Name;
1059
1060 MemberLikeFriendName(Node *Qual_, Node *Name_)
1061 : Node(KMemberLikeFriendName), Qual(Qual_), Name(Name_) {}
1062
1063 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
1064
1065 std::string_view getBaseName() const override { return Name->getBaseName(); }
1066
1067 void printLeft(OutputBuffer &OB) const override {
1068 Qual->print(OB);
1069 OB += "::friend ";
1070 Name->print(OB);
1071 }
1072};
1073
1074struct ModuleName : Node {
1075 ModuleName *Parent;
1076 Node *Name;
1077 bool IsPartition;
1078
1079 ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false)
1080 : Node(KModuleName), Parent(Parent_), Name(Name_),
1081 IsPartition(IsPartition_) {}
1082
1083 template <typename Fn> void match(Fn F) const {
1084 F(Parent, Name, IsPartition);
1085 }
1086
1087 void printLeft(OutputBuffer &OB) const override {
1088 if (Parent)
1089 Parent->print(OB);
1090 if (Parent || IsPartition)
1091 OB += IsPartition ? ':' : '.';
1092 Name->print(OB);
1093 }
1094};
1095
1096struct ModuleEntity : Node {
1097 ModuleName *Module;
1098 Node *Name;
1099
1100 ModuleEntity(ModuleName *Module_, Node *Name_)
1101 : Node(KModuleEntity), Module(Module_), Name(Name_) {}
1102
1103 template <typename Fn> void match(Fn F) const { F(Module, Name); }
1104
1105 std::string_view getBaseName() const override { return Name->getBaseName(); }
1106
1107 void printLeft(OutputBuffer &OB) const override {
1108 Name->print(OB);
1109 OB += '@';
1110 Module->print(OB);
1111 }
1112};
1113
1114struct LocalName : Node {
1115 Node *Encoding;
1116 Node *Entity;
1117
1118 LocalName(Node *Encoding_, Node *Entity_)
1119 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
1120
1121 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
1122
1123 void printLeft(OutputBuffer &OB) const override {
1124 Encoding->print(OB);
1125 OB += "::";
1126 Entity->print(OB);
1127 }
1128};
1129
1130class QualifiedName final : public Node {
1131 // qualifier::name
1132 const Node *Qualifier;
1133 const Node *Name;
1134
1135public:
1136 QualifiedName(const Node *Qualifier_, const Node *Name_)
1137 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
1138
1139 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
1140
1141 std::string_view getBaseName() const override { return Name->getBaseName(); }
1142
1143 void printLeft(OutputBuffer &OB) const override {
1144 Qualifier->print(OB);
1145 OB += "::";
1146 Name->print(OB);
1147 }
1148};
1149
1150class VectorType final : public Node {
1151 const Node *BaseType;
1152 const Node *Dimension;
1153
1154public:
1155 VectorType(const Node *BaseType_, const Node *Dimension_)
1156 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}
1157
1158 const Node *getBaseType() const { return BaseType; }
1159 const Node *getDimension() const { return Dimension; }
1160
1161 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
1162
1163 void printLeft(OutputBuffer &OB) const override {
1164 BaseType->print(OB);
1165 OB += " vector[";
1166 if (Dimension)
1167 Dimension->print(OB);
1168 OB += "]";
1169 }
1170};
1171
1172class PixelVectorType final : public Node {
1173 const Node *Dimension;
1174
1175public:
1176 PixelVectorType(const Node *Dimension_)
1177 : Node(KPixelVectorType), Dimension(Dimension_) {}
1178
1179 template<typename Fn> void match(Fn F) const { F(Dimension); }
1180
1181 void printLeft(OutputBuffer &OB) const override {
1182 // FIXME: This should demangle as "vector pixel".
1183 OB += "pixel vector[";
1184 Dimension->print(OB);
1185 OB += "]";
1186 }
1187};
1188
1189class BinaryFPType final : public Node {
1190 const Node *Dimension;
1191
1192public:
1193 BinaryFPType(const Node *Dimension_)
1194 : Node(KBinaryFPType), Dimension(Dimension_) {}
1195
1196 template<typename Fn> void match(Fn F) const { F(Dimension); }
1197
1198 void printLeft(OutputBuffer &OB) const override {
1199 OB += "_Float";
1200 Dimension->print(OB);
1201 }
1202};
1203
1204enum class TemplateParamKind { Type, NonType, Template };
1205
1206/// An invented name for a template parameter for which we don't have a
1207/// corresponding template argument.
1208///
1209/// This node is created when parsing the <lambda-sig> for a lambda with
1210/// explicit template arguments, which might be referenced in the parameter
1211/// types appearing later in the <lambda-sig>.
1212class SyntheticTemplateParamName final : public Node {
1213 TemplateParamKind Kind;
1214 unsigned Index;
1215
1216public:
1217 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
1218 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
1219
1220 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
1221
1222 void printLeft(OutputBuffer &OB) const override {
1223 switch (Kind) {
1224 case TemplateParamKind::Type:
1225 OB += "$T";
1226 break;
1227 case TemplateParamKind::NonType:
1228 OB += "$N";
1229 break;
1230 case TemplateParamKind::Template:
1231 OB += "$TT";
1232 break;
1233 }
1234 if (Index > 0)
1235 OB << Index - 1;
1236 }
1237};
1238
1239class TemplateParamQualifiedArg final : public Node {
1240 Node *Param;
1241 Node *Arg;
1242
1243public:
1244 TemplateParamQualifiedArg(Node *Param_, Node *Arg_)
1245 : Node(KTemplateParamQualifiedArg), Param(Param_), Arg(Arg_) {}
1246
1247 template <typename Fn> void match(Fn F) const { F(Param, Arg); }
1248
1249 Node *getArg() { return Arg; }
1250
1251 void printLeft(OutputBuffer &OB) const override {
1252 // Don't print Param to keep the output consistent.
1253 Arg->print(OB);
1254 }
1255};
1256
1257/// A template type parameter declaration, 'typename T'.
1258class TypeTemplateParamDecl final : public Node {
1259 Node *Name;
1260
1261public:
1262 TypeTemplateParamDecl(Node *Name_)
1263 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
1264
1265 template<typename Fn> void match(Fn F) const { F(Name); }
1266
1267 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
1268
1269 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
1270};
1271
1272/// A constrained template type parameter declaration, 'C<U> T'.
1273class ConstrainedTypeTemplateParamDecl final : public Node {
1274 Node *Constraint;
1275 Node *Name;
1276
1277public:
1278 ConstrainedTypeTemplateParamDecl(Node *Constraint_, Node *Name_)
1279 : Node(KConstrainedTypeTemplateParamDecl, Cache::Yes),
1280 Constraint(Constraint_), Name(Name_) {}
1281
1282 template<typename Fn> void match(Fn F) const { F(Constraint, Name); }
1283
1284 void printLeft(OutputBuffer &OB) const override {
1285 Constraint->print(OB);
1286 OB += " ";
1287 }
1288
1289 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
1290};
1291
1292/// A non-type template parameter declaration, 'int N'.
1293class NonTypeTemplateParamDecl final : public Node {
1294 Node *Name;
1295 Node *Type;
1296
1297public:
1298 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
1299 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
1300
1301 template<typename Fn> void match(Fn F) const { F(Name, Type); }
1302
1303 void printLeft(OutputBuffer &OB) const override {
1304 Type->printLeft(OB);
1305 if (!Type->hasRHSComponent(OB))
1306 OB += " ";
1307 }
1308
1309 void printRight(OutputBuffer &OB) const override {
1310 Name->print(OB);
1311 Type->printRight(OB);
1312 }
1313};
1314
1315/// A template template parameter declaration,
1316/// 'template<typename T> typename N'.
1317class TemplateTemplateParamDecl final : public Node {
1318 Node *Name;
1319 NodeArray Params;
1320 Node *Requires;
1321
1322public:
1323 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_, Node *Requires_)
1324 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1325 Params(Params_), Requires(Requires_) {}
1326
1327 template <typename Fn> void match(Fn F) const { F(Name, Params, Requires); }
1328
1329 void printLeft(OutputBuffer &OB) const override {
1330 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
1331 OB += "template<";
1332 Params.printWithComma(OB);
1333 OB += "> typename ";
1334 }
1335
1336 void printRight(OutputBuffer &OB) const override {
1337 Name->print(OB);
1338 if (Requires != nullptr) {
1339 OB += " requires ";
1340 Requires->print(OB);
1341 }
1342 }
1343};
1344
1345/// A template parameter pack declaration, 'typename ...T'.
1346class TemplateParamPackDecl final : public Node {
1347 Node *Param;
1348
1349public:
1350 TemplateParamPackDecl(Node *Param_)
1351 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1352
1353 template<typename Fn> void match(Fn F) const { F(Param); }
1354
1355 void printLeft(OutputBuffer &OB) const override {
1356 Param->printLeft(OB);
1357 OB += "...";
1358 }
1359
1360 void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
1361};
1362
1363/// An unexpanded parameter pack (either in the expression or type context). If
1364/// this AST is correct, this node will have a ParameterPackExpansion node above
1365/// it.
1366///
1367/// This node is created when some <template-args> are found that apply to an
1368/// <encoding>, and is stored in the TemplateParams table. In order for this to
1369/// appear in the final AST, it has to referenced via a <template-param> (ie,
1370/// T_).
1371class ParameterPack final : public Node {
1372 NodeArray Data;
1373
1374 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1375 // one.
1376 void initializePackExpansion(OutputBuffer &OB) const {
1377 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1378 OB.CurrentPackMax = static_cast<unsigned>(Data.size());
1379 OB.CurrentPackIndex = 0;
1380 }
1381 }
1382
1383public:
1384 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1385 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
1386 if (std::all_of(first: Data.begin(), last: Data.end(), pred: [](Node* P) {
1387 return P->ArrayCache == Cache::No;
1388 }))
1389 ArrayCache = Cache::No;
1390 if (std::all_of(first: Data.begin(), last: Data.end(), pred: [](Node* P) {
1391 return P->FunctionCache == Cache::No;
1392 }))
1393 FunctionCache = Cache::No;
1394 if (std::all_of(first: Data.begin(), last: Data.end(), pred: [](Node* P) {
1395 return P->RHSComponentCache == Cache::No;
1396 }))
1397 RHSComponentCache = Cache::No;
1398 }
1399
1400 template<typename Fn> void match(Fn F) const { F(Data); }
1401
1402 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1403 initializePackExpansion(OB);
1404 size_t Idx = OB.CurrentPackIndex;
1405 return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);
1406 }
1407 bool hasArraySlow(OutputBuffer &OB) const override {
1408 initializePackExpansion(OB);
1409 size_t Idx = OB.CurrentPackIndex;
1410 return Idx < Data.size() && Data[Idx]->hasArray(OB);
1411 }
1412 bool hasFunctionSlow(OutputBuffer &OB) const override {
1413 initializePackExpansion(OB);
1414 size_t Idx = OB.CurrentPackIndex;
1415 return Idx < Data.size() && Data[Idx]->hasFunction(OB);
1416 }
1417 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1418 initializePackExpansion(OB);
1419 size_t Idx = OB.CurrentPackIndex;
1420 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;
1421 }
1422
1423 void printLeft(OutputBuffer &OB) const override {
1424 initializePackExpansion(OB);
1425 size_t Idx = OB.CurrentPackIndex;
1426 if (Idx < Data.size())
1427 Data[Idx]->printLeft(OB);
1428 }
1429 void printRight(OutputBuffer &OB) const override {
1430 initializePackExpansion(OB);
1431 size_t Idx = OB.CurrentPackIndex;
1432 if (Idx < Data.size())
1433 Data[Idx]->printRight(OB);
1434 }
1435};
1436
1437/// A variadic template argument. This node represents an occurrence of
1438/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1439/// one of its Elements is. The parser inserts a ParameterPack into the
1440/// TemplateParams table if the <template-args> this pack belongs to apply to an
1441/// <encoding>.
1442class TemplateArgumentPack final : public Node {
1443 NodeArray Elements;
1444public:
1445 TemplateArgumentPack(NodeArray Elements_)
1446 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1447
1448 template<typename Fn> void match(Fn F) const { F(Elements); }
1449
1450 NodeArray getElements() const { return Elements; }
1451
1452 void printLeft(OutputBuffer &OB) const override {
1453 Elements.printWithComma(OB);
1454 }
1455};
1456
1457/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1458/// which each have Child->ParameterPackSize elements.
1459class ParameterPackExpansion final : public Node {
1460 const Node *Child;
1461
1462public:
1463 ParameterPackExpansion(const Node *Child_)
1464 : Node(KParameterPackExpansion), Child(Child_) {}
1465
1466 template<typename Fn> void match(Fn F) const { F(Child); }
1467
1468 const Node *getChild() const { return Child; }
1469
1470 void printLeft(OutputBuffer &OB) const override {
1471 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
1472 ScopedOverride<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1473 ScopedOverride<unsigned> SavePackMax(OB.CurrentPackMax, Max);
1474 size_t StreamPos = OB.getCurrentPosition();
1475
1476 // Print the first element in the pack. If Child contains a ParameterPack,
1477 // it will set up S.CurrentPackMax and print the first element.
1478 Child->print(OB);
1479
1480 // No ParameterPack was found in Child. This can occur if we've found a pack
1481 // expansion on a <function-param>.
1482 if (OB.CurrentPackMax == Max) {
1483 OB += "...";
1484 return;
1485 }
1486
1487 // We found a ParameterPack, but it has no elements. Erase whatever we may
1488 // of printed.
1489 if (OB.CurrentPackMax == 0) {
1490 OB.setCurrentPosition(StreamPos);
1491 return;
1492 }
1493
1494 // Else, iterate through the rest of the elements in the pack.
1495 for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {
1496 OB += ", ";
1497 OB.CurrentPackIndex = I;
1498 Child->print(OB);
1499 }
1500 }
1501};
1502
1503class TemplateArgs final : public Node {
1504 NodeArray Params;
1505 Node *Requires;
1506
1507public:
1508 TemplateArgs(NodeArray Params_, Node *Requires_)
1509 : Node(KTemplateArgs), Params(Params_), Requires(Requires_) {}
1510
1511 template<typename Fn> void match(Fn F) const { F(Params, Requires); }
1512
1513 NodeArray getParams() { return Params; }
1514
1515 void printLeft(OutputBuffer &OB) const override {
1516 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
1517 OB += "<";
1518 Params.printWithComma(OB);
1519 OB += ">";
1520 // Don't print the requires clause to keep the output simple.
1521 }
1522};
1523
1524/// A forward-reference to a template argument that was not known at the point
1525/// where the template parameter name was parsed in a mangling.
1526///
1527/// This is created when demangling the name of a specialization of a
1528/// conversion function template:
1529///
1530/// \code
1531/// struct A {
1532/// template<typename T> operator T*();
1533/// };
1534/// \endcode
1535///
1536/// When demangling a specialization of the conversion function template, we
1537/// encounter the name of the template (including the \c T) before we reach
1538/// the template argument list, so we cannot substitute the parameter name
1539/// for the corresponding argument while parsing. Instead, we create a
1540/// \c ForwardTemplateReference node that is resolved after we parse the
1541/// template arguments.
1542struct ForwardTemplateReference : Node {
1543 size_t Index;
1544 Node *Ref = nullptr;
1545
1546 // If we're currently printing this node. It is possible (though invalid) for
1547 // a forward template reference to refer to itself via a substitution. This
1548 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1549 // out if more than one print* function is active.
1550 mutable bool Printing = false;
1551
1552 ForwardTemplateReference(size_t Index_)
1553 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1554 Cache::Unknown),
1555 Index(Index_) {}
1556
1557 // We don't provide a matcher for these, because the value of the node is
1558 // not determined by its construction parameters, and it generally needs
1559 // special handling.
1560 template<typename Fn> void match(Fn F) const = delete;
1561
1562 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1563 if (Printing)
1564 return false;
1565 ScopedOverride<bool> SavePrinting(Printing, true);
1566 return Ref->hasRHSComponent(OB);
1567 }
1568 bool hasArraySlow(OutputBuffer &OB) const override {
1569 if (Printing)
1570 return false;
1571 ScopedOverride<bool> SavePrinting(Printing, true);
1572 return Ref->hasArray(OB);
1573 }
1574 bool hasFunctionSlow(OutputBuffer &OB) const override {
1575 if (Printing)
1576 return false;
1577 ScopedOverride<bool> SavePrinting(Printing, true);
1578 return Ref->hasFunction(OB);
1579 }
1580 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1581 if (Printing)
1582 return this;
1583 ScopedOverride<bool> SavePrinting(Printing, true);
1584 return Ref->getSyntaxNode(OB);
1585 }
1586
1587 void printLeft(OutputBuffer &OB) const override {
1588 if (Printing)
1589 return;
1590 ScopedOverride<bool> SavePrinting(Printing, true);
1591 Ref->printLeft(OB);
1592 }
1593 void printRight(OutputBuffer &OB) const override {
1594 if (Printing)
1595 return;
1596 ScopedOverride<bool> SavePrinting(Printing, true);
1597 Ref->printRight(OB);
1598 }
1599};
1600
1601struct NameWithTemplateArgs : Node {
1602 // name<template_args>
1603 Node *Name;
1604 Node *TemplateArgs;
1605
1606 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1607 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1608
1609 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1610
1611 std::string_view getBaseName() const override { return Name->getBaseName(); }
1612
1613 void printLeft(OutputBuffer &OB) const override {
1614 Name->print(OB);
1615 TemplateArgs->print(OB);
1616 }
1617};
1618
1619class GlobalQualifiedName final : public Node {
1620 Node *Child;
1621
1622public:
1623 GlobalQualifiedName(Node* Child_)
1624 : Node(KGlobalQualifiedName), Child(Child_) {}
1625
1626 template<typename Fn> void match(Fn F) const { F(Child); }
1627
1628 std::string_view getBaseName() const override { return Child->getBaseName(); }
1629
1630 void printLeft(OutputBuffer &OB) const override {
1631 OB += "::";
1632 Child->print(OB);
1633 }
1634};
1635
1636enum class SpecialSubKind {
1637 allocator,
1638 basic_string,
1639 string,
1640 istream,
1641 ostream,
1642 iostream,
1643};
1644
1645class SpecialSubstitution;
1646class ExpandedSpecialSubstitution : public Node {
1647protected:
1648 SpecialSubKind SSK;
1649
1650 ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)
1651 : Node(K_), SSK(SSK_) {}
1652public:
1653 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1654 : ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}
1655 inline ExpandedSpecialSubstitution(SpecialSubstitution const *);
1656
1657 template<typename Fn> void match(Fn F) const { F(SSK); }
1658
1659protected:
1660 bool isInstantiation() const {
1661 return unsigned(SSK) >= unsigned(SpecialSubKind::string);
1662 }
1663
1664 std::string_view getBaseName() const override {
1665 switch (SSK) {
1666 case SpecialSubKind::allocator:
1667 return {"allocator"};
1668 case SpecialSubKind::basic_string:
1669 return {"basic_string"};
1670 case SpecialSubKind::string:
1671 return {"basic_string"};
1672 case SpecialSubKind::istream:
1673 return {"basic_istream"};
1674 case SpecialSubKind::ostream:
1675 return {"basic_ostream"};
1676 case SpecialSubKind::iostream:
1677 return {"basic_iostream"};
1678 }
1679 DEMANGLE_UNREACHABLE;
1680 }
1681
1682private:
1683 void printLeft(OutputBuffer &OB) const override {
1684 OB << "std::" << getBaseName();
1685 if (isInstantiation()) {
1686 OB << "<char, std::char_traits<char>";
1687 if (SSK == SpecialSubKind::string)
1688 OB << ", std::allocator<char>";
1689 OB << ">";
1690 }
1691 }
1692};
1693
1694class SpecialSubstitution final : public ExpandedSpecialSubstitution {
1695public:
1696 SpecialSubstitution(SpecialSubKind SSK_)
1697 : ExpandedSpecialSubstitution(SSK_, KSpecialSubstitution) {}
1698
1699 template<typename Fn> void match(Fn F) const { F(SSK); }
1700
1701 std::string_view getBaseName() const override {
1702 std::string_view SV = ExpandedSpecialSubstitution::getBaseName();
1703 if (isInstantiation()) {
1704 // The instantiations are typedefs that drop the "basic_" prefix.
1705 DEMANGLE_ASSERT(starts_with(SV, "basic_"), "");
1706 SV.remove_prefix(n: sizeof("basic_") - 1);
1707 }
1708 return SV;
1709 }
1710
1711 void printLeft(OutputBuffer &OB) const override {
1712 OB << "std::" << getBaseName();
1713 }
1714};
1715
1716inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(
1717 SpecialSubstitution const *SS)
1718 : ExpandedSpecialSubstitution(SS->SSK) {}
1719
1720class CtorDtorName final : public Node {
1721 const Node *Basename;
1722 const bool IsDtor;
1723 const int Variant;
1724
1725public:
1726 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1727 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1728 Variant(Variant_) {}
1729
1730 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
1731
1732 void printLeft(OutputBuffer &OB) const override {
1733 if (IsDtor)
1734 OB += "~";
1735 OB += Basename->getBaseName();
1736 }
1737};
1738
1739class DtorName : public Node {
1740 const Node *Base;
1741
1742public:
1743 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1744
1745 template<typename Fn> void match(Fn F) const { F(Base); }
1746
1747 void printLeft(OutputBuffer &OB) const override {
1748 OB += "~";
1749 Base->printLeft(OB);
1750 }
1751};
1752
1753class UnnamedTypeName : public Node {
1754 const std::string_view Count;
1755
1756public:
1757 UnnamedTypeName(std::string_view Count_)
1758 : Node(KUnnamedTypeName), Count(Count_) {}
1759
1760 template<typename Fn> void match(Fn F) const { F(Count); }
1761
1762 void printLeft(OutputBuffer &OB) const override {
1763 OB += "'unnamed";
1764 OB += Count;
1765 OB += "\'";
1766 }
1767};
1768
1769class ClosureTypeName : public Node {
1770 NodeArray TemplateParams;
1771 const Node *Requires1;
1772 NodeArray Params;
1773 const Node *Requires2;
1774 std::string_view Count;
1775
1776public:
1777 ClosureTypeName(NodeArray TemplateParams_, const Node *Requires1_,
1778 NodeArray Params_, const Node *Requires2_,
1779 std::string_view Count_)
1780 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1781 Requires1(Requires1_), Params(Params_), Requires2(Requires2_),
1782 Count(Count_) {}
1783
1784 template<typename Fn> void match(Fn F) const {
1785 F(TemplateParams, Requires1, Params, Requires2, Count);
1786 }
1787
1788 void printDeclarator(OutputBuffer &OB) const {
1789 if (!TemplateParams.empty()) {
1790 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
1791 OB += "<";
1792 TemplateParams.printWithComma(OB);
1793 OB += ">";
1794 }
1795 if (Requires1 != nullptr) {
1796 OB += " requires ";
1797 Requires1->print(OB);
1798 OB += " ";
1799 }
1800 OB.printOpen();
1801 Params.printWithComma(OB);
1802 OB.printClose();
1803 if (Requires2 != nullptr) {
1804 OB += " requires ";
1805 Requires2->print(OB);
1806 }
1807 }
1808
1809 void printLeft(OutputBuffer &OB) const override {
1810 // FIXME: This demangling is not particularly readable.
1811 OB += "\'lambda";
1812 OB += Count;
1813 OB += "\'";
1814 printDeclarator(OB);
1815 }
1816};
1817
1818class StructuredBindingName : public Node {
1819 NodeArray Bindings;
1820public:
1821 StructuredBindingName(NodeArray Bindings_)
1822 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1823
1824 template<typename Fn> void match(Fn F) const { F(Bindings); }
1825
1826 void printLeft(OutputBuffer &OB) const override {
1827 OB.printOpen(Open: '[');
1828 Bindings.printWithComma(OB);
1829 OB.printClose(Close: ']');
1830 }
1831};
1832
1833// -- Expression Nodes --
1834
1835class BinaryExpr : public Node {
1836 const Node *LHS;
1837 const std::string_view InfixOperator;
1838 const Node *RHS;
1839
1840public:
1841 BinaryExpr(const Node *LHS_, std::string_view InfixOperator_,
1842 const Node *RHS_, Prec Prec_)
1843 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
1844 RHS(RHS_) {}
1845
1846 template <typename Fn> void match(Fn F) const {
1847 F(LHS, InfixOperator, RHS, getPrecedence());
1848 }
1849
1850 void printLeft(OutputBuffer &OB) const override {
1851 bool ParenAll = OB.isGtInsideTemplateArgs() &&
1852 (InfixOperator == ">" || InfixOperator == ">>");
1853 if (ParenAll)
1854 OB.printOpen();
1855 // Assignment is right associative, with special LHS precedence.
1856 bool IsAssign = getPrecedence() == Prec::Assign;
1857 LHS->printAsOperand(OB, P: IsAssign ? Prec::OrIf : getPrecedence(), StrictlyWorse: !IsAssign);
1858 // No space before comma operator
1859 if (!(InfixOperator == ","))
1860 OB += " ";
1861 OB += InfixOperator;
1862 OB += " ";
1863 RHS->printAsOperand(OB, P: getPrecedence(), StrictlyWorse: IsAssign);
1864 if (ParenAll)
1865 OB.printClose();
1866 }
1867};
1868
1869class ArraySubscriptExpr : public Node {
1870 const Node *Op1;
1871 const Node *Op2;
1872
1873public:
1874 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1875 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
1876
1877 template <typename Fn> void match(Fn F) const {
1878 F(Op1, Op2, getPrecedence());
1879 }
1880
1881 void printLeft(OutputBuffer &OB) const override {
1882 Op1->printAsOperand(OB, P: getPrecedence());
1883 OB.printOpen(Open: '[');
1884 Op2->printAsOperand(OB);
1885 OB.printClose(Close: ']');
1886 }
1887};
1888
1889class PostfixExpr : public Node {
1890 const Node *Child;
1891 const std::string_view Operator;
1892
1893public:
1894 PostfixExpr(const Node *Child_, std::string_view Operator_, Prec Prec_)
1895 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
1896
1897 template <typename Fn> void match(Fn F) const {
1898 F(Child, Operator, getPrecedence());
1899 }
1900
1901 void printLeft(OutputBuffer &OB) const override {
1902 Child->printAsOperand(OB, P: getPrecedence(), StrictlyWorse: true);
1903 OB += Operator;
1904 }
1905};
1906
1907class ConditionalExpr : public Node {
1908 const Node *Cond;
1909 const Node *Then;
1910 const Node *Else;
1911
1912public:
1913 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1914 Prec Prec_)
1915 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
1916
1917 template <typename Fn> void match(Fn F) const {
1918 F(Cond, Then, Else, getPrecedence());
1919 }
1920
1921 void printLeft(OutputBuffer &OB) const override {
1922 Cond->printAsOperand(OB, P: getPrecedence());
1923 OB += " ? ";
1924 Then->printAsOperand(OB);
1925 OB += " : ";
1926 Else->printAsOperand(OB, P: Prec::Assign, StrictlyWorse: true);
1927 }
1928};
1929
1930class MemberExpr : public Node {
1931 const Node *LHS;
1932 const std::string_view Kind;
1933 const Node *RHS;
1934
1935public:
1936 MemberExpr(const Node *LHS_, std::string_view Kind_, const Node *RHS_,
1937 Prec Prec_)
1938 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
1939
1940 template <typename Fn> void match(Fn F) const {
1941 F(LHS, Kind, RHS, getPrecedence());
1942 }
1943
1944 void printLeft(OutputBuffer &OB) const override {
1945 LHS->printAsOperand(OB, P: getPrecedence(), StrictlyWorse: true);
1946 OB += Kind;
1947 RHS->printAsOperand(OB, P: getPrecedence(), StrictlyWorse: false);
1948 }
1949};
1950
1951class SubobjectExpr : public Node {
1952 const Node *Type;
1953 const Node *SubExpr;
1954 std::string_view Offset;
1955 NodeArray UnionSelectors;
1956 bool OnePastTheEnd;
1957
1958public:
1959 SubobjectExpr(const Node *Type_, const Node *SubExpr_,
1960 std::string_view Offset_, NodeArray UnionSelectors_,
1961 bool OnePastTheEnd_)
1962 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1963 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1964
1965 template<typename Fn> void match(Fn F) const {
1966 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1967 }
1968
1969 void printLeft(OutputBuffer &OB) const override {
1970 SubExpr->print(OB);
1971 OB += ".<";
1972 Type->print(OB);
1973 OB += " at offset ";
1974 if (Offset.empty()) {
1975 OB += "0";
1976 } else if (Offset[0] == 'n') {
1977 OB += "-";
1978 OB += std::string_view(Offset.data() + 1, Offset.size() - 1);
1979 } else {
1980 OB += Offset;
1981 }
1982 OB += ">";
1983 }
1984};
1985
1986class EnclosingExpr : public Node {
1987 const std::string_view Prefix;
1988 const Node *Infix;
1989 const std::string_view Postfix;
1990
1991public:
1992 EnclosingExpr(std::string_view Prefix_, const Node *Infix_,
1993 Prec Prec_ = Prec::Primary)
1994 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
1995
1996 template <typename Fn> void match(Fn F) const {
1997 F(Prefix, Infix, getPrecedence());
1998 }
1999
2000 void printLeft(OutputBuffer &OB) const override {
2001 OB += Prefix;
2002 OB.printOpen();
2003 Infix->print(OB);
2004 OB.printClose();
2005 OB += Postfix;
2006 }
2007};
2008
2009class CastExpr : public Node {
2010 // cast_kind<to>(from)
2011 const std::string_view CastKind;
2012 const Node *To;
2013 const Node *From;
2014
2015public:
2016 CastExpr(std::string_view CastKind_, const Node *To_, const Node *From_,
2017 Prec Prec_)
2018 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
2019
2020 template <typename Fn> void match(Fn F) const {
2021 F(CastKind, To, From, getPrecedence());
2022 }
2023
2024 void printLeft(OutputBuffer &OB) const override {
2025 OB += CastKind;
2026 {
2027 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
2028 OB += "<";
2029 To->printLeft(OB);
2030 OB += ">";
2031 }
2032 OB.printOpen();
2033 From->printAsOperand(OB);
2034 OB.printClose();
2035 }
2036};
2037
2038class SizeofParamPackExpr : public Node {
2039 const Node *Pack;
2040
2041public:
2042 SizeofParamPackExpr(const Node *Pack_)
2043 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
2044
2045 template<typename Fn> void match(Fn F) const { F(Pack); }
2046
2047 void printLeft(OutputBuffer &OB) const override {
2048 OB += "sizeof...";
2049 OB.printOpen();
2050 ParameterPackExpansion PPE(Pack);
2051 PPE.printLeft(OB);
2052 OB.printClose();
2053 }
2054};
2055
2056class CallExpr : public Node {
2057 const Node *Callee;
2058 NodeArray Args;
2059
2060public:
2061 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
2062 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
2063
2064 template <typename Fn> void match(Fn F) const {
2065 F(Callee, Args, getPrecedence());
2066 }
2067
2068 void printLeft(OutputBuffer &OB) const override {
2069 Callee->print(OB);
2070 OB.printOpen();
2071 Args.printWithComma(OB);
2072 OB.printClose();
2073 }
2074};
2075
2076class NewExpr : public Node {
2077 // new (expr_list) type(init_list)
2078 NodeArray ExprList;
2079 Node *Type;
2080 NodeArray InitList;
2081 bool IsGlobal; // ::operator new ?
2082 bool IsArray; // new[] ?
2083public:
2084 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
2085 bool IsArray_, Prec Prec_)
2086 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
2087 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
2088
2089 template<typename Fn> void match(Fn F) const {
2090 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
2091 }
2092
2093 void printLeft(OutputBuffer &OB) const override {
2094 if (IsGlobal)
2095 OB += "::";
2096 OB += "new";
2097 if (IsArray)
2098 OB += "[]";
2099 if (!ExprList.empty()) {
2100 OB.printOpen();
2101 ExprList.printWithComma(OB);
2102 OB.printClose();
2103 }
2104 OB += " ";
2105 Type->print(OB);
2106 if (!InitList.empty()) {
2107 OB.printOpen();
2108 InitList.printWithComma(OB);
2109 OB.printClose();
2110 }
2111 }
2112};
2113
2114class DeleteExpr : public Node {
2115 Node *Op;
2116 bool IsGlobal;
2117 bool IsArray;
2118
2119public:
2120 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
2121 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
2122 IsArray(IsArray_) {}
2123
2124 template <typename Fn> void match(Fn F) const {
2125 F(Op, IsGlobal, IsArray, getPrecedence());
2126 }
2127
2128 void printLeft(OutputBuffer &OB) const override {
2129 if (IsGlobal)
2130 OB += "::";
2131 OB += "delete";
2132 if (IsArray)
2133 OB += "[]";
2134 OB += ' ';
2135 Op->print(OB);
2136 }
2137};
2138
2139class PrefixExpr : public Node {
2140 std::string_view Prefix;
2141 Node *Child;
2142
2143public:
2144 PrefixExpr(std::string_view Prefix_, Node *Child_, Prec Prec_)
2145 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
2146
2147 template <typename Fn> void match(Fn F) const {
2148 F(Prefix, Child, getPrecedence());
2149 }
2150
2151 void printLeft(OutputBuffer &OB) const override {
2152 OB += Prefix;
2153 Child->printAsOperand(OB, P: getPrecedence());
2154 }
2155};
2156
2157class FunctionParam : public Node {
2158 std::string_view Number;
2159
2160public:
2161 FunctionParam(std::string_view Number_)
2162 : Node(KFunctionParam), Number(Number_) {}
2163
2164 template<typename Fn> void match(Fn F) const { F(Number); }
2165
2166 void printLeft(OutputBuffer &OB) const override {
2167 OB += "fp";
2168 OB += Number;
2169 }
2170};
2171
2172class ConversionExpr : public Node {
2173 const Node *Type;
2174 NodeArray Expressions;
2175
2176public:
2177 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2178 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
2179
2180 template <typename Fn> void match(Fn F) const {
2181 F(Type, Expressions, getPrecedence());
2182 }
2183
2184 void printLeft(OutputBuffer &OB) const override {
2185 OB.printOpen();
2186 Type->print(OB);
2187 OB.printClose();
2188 OB.printOpen();
2189 Expressions.printWithComma(OB);
2190 OB.printClose();
2191 }
2192};
2193
2194class PointerToMemberConversionExpr : public Node {
2195 const Node *Type;
2196 const Node *SubExpr;
2197 std::string_view Offset;
2198
2199public:
2200 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
2201 std::string_view Offset_, Prec Prec_)
2202 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2203 SubExpr(SubExpr_), Offset(Offset_) {}
2204
2205 template <typename Fn> void match(Fn F) const {
2206 F(Type, SubExpr, Offset, getPrecedence());
2207 }
2208
2209 void printLeft(OutputBuffer &OB) const override {
2210 OB.printOpen();
2211 Type->print(OB);
2212 OB.printClose();
2213 OB.printOpen();
2214 SubExpr->print(OB);
2215 OB.printClose();
2216 }
2217};
2218
2219class InitListExpr : public Node {
2220 const Node *Ty;
2221 NodeArray Inits;
2222public:
2223 InitListExpr(const Node *Ty_, NodeArray Inits_)
2224 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2225
2226 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2227
2228 void printLeft(OutputBuffer &OB) const override {
2229 if (Ty)
2230 Ty->print(OB);
2231 OB += '{';
2232 Inits.printWithComma(OB);
2233 OB += '}';
2234 }
2235};
2236
2237class BracedExpr : public Node {
2238 const Node *Elem;
2239 const Node *Init;
2240 bool IsArray;
2241public:
2242 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2243 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2244
2245 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
2246
2247 void printLeft(OutputBuffer &OB) const override {
2248 if (IsArray) {
2249 OB += '[';
2250 Elem->print(OB);
2251 OB += ']';
2252 } else {
2253 OB += '.';
2254 Elem->print(OB);
2255 }
2256 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
2257 OB += " = ";
2258 Init->print(OB);
2259 }
2260};
2261
2262class BracedRangeExpr : public Node {
2263 const Node *First;
2264 const Node *Last;
2265 const Node *Init;
2266public:
2267 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2268 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2269
2270 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2271
2272 void printLeft(OutputBuffer &OB) const override {
2273 OB += '[';
2274 First->print(OB);
2275 OB += " ... ";
2276 Last->print(OB);
2277 OB += ']';
2278 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
2279 OB += " = ";
2280 Init->print(OB);
2281 }
2282};
2283
2284class FoldExpr : public Node {
2285 const Node *Pack, *Init;
2286 std::string_view OperatorName;
2287 bool IsLeftFold;
2288
2289public:
2290 FoldExpr(bool IsLeftFold_, std::string_view OperatorName_, const Node *Pack_,
2291 const Node *Init_)
2292 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2293 IsLeftFold(IsLeftFold_) {}
2294
2295 template<typename Fn> void match(Fn F) const {
2296 F(IsLeftFold, OperatorName, Pack, Init);
2297 }
2298
2299 void printLeft(OutputBuffer &OB) const override {
2300 auto PrintPack = [&] {
2301 OB.printOpen();
2302 ParameterPackExpansion(Pack).print(OB);
2303 OB.printClose();
2304 };
2305
2306 OB.printOpen();
2307 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2308 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2309 // Fold expr operands are cast-expressions
2310 if (!IsLeftFold || Init != nullptr) {
2311 // '(init|pack) op '
2312 if (IsLeftFold)
2313 Init->printAsOperand(OB, P: Prec::Cast, StrictlyWorse: true);
2314 else
2315 PrintPack();
2316 OB << " " << OperatorName << " ";
2317 }
2318 OB << "...";
2319 if (IsLeftFold || Init != nullptr) {
2320 // ' op (init|pack)'
2321 OB << " " << OperatorName << " ";
2322 if (IsLeftFold)
2323 PrintPack();
2324 else
2325 Init->printAsOperand(OB, P: Prec::Cast, StrictlyWorse: true);
2326 }
2327 OB.printClose();
2328 }
2329};
2330
2331class ThrowExpr : public Node {
2332 const Node *Op;
2333
2334public:
2335 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2336
2337 template<typename Fn> void match(Fn F) const { F(Op); }
2338
2339 void printLeft(OutputBuffer &OB) const override {
2340 OB += "throw ";
2341 Op->print(OB);
2342 }
2343};
2344
2345class BoolExpr : public Node {
2346 bool Value;
2347
2348public:
2349 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2350
2351 template<typename Fn> void match(Fn F) const { F(Value); }
2352
2353 void printLeft(OutputBuffer &OB) const override {
2354 OB += Value ? std::string_view("true") : std::string_view("false");
2355 }
2356};
2357
2358class StringLiteral : public Node {
2359 const Node *Type;
2360
2361public:
2362 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2363
2364 template<typename Fn> void match(Fn F) const { F(Type); }
2365
2366 void printLeft(OutputBuffer &OB) const override {
2367 OB += "\"<";
2368 Type->print(OB);
2369 OB += ">\"";
2370 }
2371};
2372
2373class LambdaExpr : public Node {
2374 const Node *Type;
2375
2376public:
2377 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2378
2379 template<typename Fn> void match(Fn F) const { F(Type); }
2380
2381 void printLeft(OutputBuffer &OB) const override {
2382 OB += "[]";
2383 if (Type->getKind() == KClosureTypeName)
2384 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2385 OB += "{...}";
2386 }
2387};
2388
2389class EnumLiteral : public Node {
2390 // ty(integer)
2391 const Node *Ty;
2392 std::string_view Integer;
2393
2394public:
2395 EnumLiteral(const Node *Ty_, std::string_view Integer_)
2396 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
2397
2398 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2399
2400 void printLeft(OutputBuffer &OB) const override {
2401 OB.printOpen();
2402 Ty->print(OB);
2403 OB.printClose();
2404
2405 if (Integer[0] == 'n')
2406 OB << '-' << std::string_view(Integer.data() + 1, Integer.size() - 1);
2407 else
2408 OB << Integer;
2409 }
2410};
2411
2412class IntegerLiteral : public Node {
2413 std::string_view Type;
2414 std::string_view Value;
2415
2416public:
2417 IntegerLiteral(std::string_view Type_, std::string_view Value_)
2418 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2419
2420 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2421
2422 void printLeft(OutputBuffer &OB) const override {
2423 if (Type.size() > 3) {
2424 OB.printOpen();
2425 OB += Type;
2426 OB.printClose();
2427 }
2428
2429 if (Value[0] == 'n')
2430 OB << '-' << std::string_view(Value.data() + 1, Value.size() - 1);
2431 else
2432 OB += Value;
2433
2434 if (Type.size() <= 3)
2435 OB += Type;
2436 }
2437};
2438
2439class RequiresExpr : public Node {
2440 NodeArray Parameters;
2441 NodeArray Requirements;
2442public:
2443 RequiresExpr(NodeArray Parameters_, NodeArray Requirements_)
2444 : Node(KRequiresExpr), Parameters(Parameters_),
2445 Requirements(Requirements_) {}
2446
2447 template<typename Fn> void match(Fn F) const { F(Parameters, Requirements); }
2448
2449 void printLeft(OutputBuffer &OB) const override {
2450 OB += "requires";
2451 if (!Parameters.empty()) {
2452 OB += ' ';
2453 OB.printOpen();
2454 Parameters.printWithComma(OB);
2455 OB.printClose();
2456 }
2457 OB += ' ';
2458 OB.printOpen(Open: '{');
2459 for (const Node *Req : Requirements) {
2460 Req->print(OB);
2461 }
2462 OB += ' ';
2463 OB.printClose(Close: '}');
2464 }
2465};
2466
2467class ExprRequirement : public Node {
2468 const Node *Expr;
2469 bool IsNoexcept;
2470 const Node *TypeConstraint;
2471public:
2472 ExprRequirement(const Node *Expr_, bool IsNoexcept_,
2473 const Node *TypeConstraint_)
2474 : Node(KExprRequirement), Expr(Expr_), IsNoexcept(IsNoexcept_),
2475 TypeConstraint(TypeConstraint_) {}
2476
2477 template <typename Fn> void match(Fn F) const {
2478 F(Expr, IsNoexcept, TypeConstraint);
2479 }
2480
2481 void printLeft(OutputBuffer &OB) const override {
2482 OB += " ";
2483 if (IsNoexcept || TypeConstraint)
2484 OB.printOpen(Open: '{');
2485 Expr->print(OB);
2486 if (IsNoexcept || TypeConstraint)
2487 OB.printClose(Close: '}');
2488 if (IsNoexcept)
2489 OB += " noexcept";
2490 if (TypeConstraint) {
2491 OB += " -> ";
2492 TypeConstraint->print(OB);
2493 }
2494 OB += ';';
2495 }
2496};
2497
2498class TypeRequirement : public Node {
2499 const Node *Type;
2500public:
2501 TypeRequirement(const Node *Type_)
2502 : Node(KTypeRequirement), Type(Type_) {}
2503
2504 template <typename Fn> void match(Fn F) const { F(Type); }
2505
2506 void printLeft(OutputBuffer &OB) const override {
2507 OB += " typename ";
2508 Type->print(OB);
2509 OB += ';';
2510 }
2511};
2512
2513class NestedRequirement : public Node {
2514 const Node *Constraint;
2515public:
2516 NestedRequirement(const Node *Constraint_)
2517 : Node(KNestedRequirement), Constraint(Constraint_) {}
2518
2519 template <typename Fn> void match(Fn F) const { F(Constraint); }
2520
2521 void printLeft(OutputBuffer &OB) const override {
2522 OB += " requires ";
2523 Constraint->print(OB);
2524 OB += ';';
2525 }
2526};
2527
2528template <class Float> struct FloatData;
2529
2530namespace float_literal_impl {
2531constexpr Node::Kind getFloatLiteralKind(float *) {
2532 return Node::KFloatLiteral;
2533}
2534constexpr Node::Kind getFloatLiteralKind(double *) {
2535 return Node::KDoubleLiteral;
2536}
2537constexpr Node::Kind getFloatLiteralKind(long double *) {
2538 return Node::KLongDoubleLiteral;
2539}
2540}
2541
2542template <class Float> class FloatLiteralImpl : public Node {
2543 const std::string_view Contents;
2544
2545 static constexpr Kind KindForClass =
2546 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2547
2548public:
2549 FloatLiteralImpl(std::string_view Contents_)
2550 : Node(KindForClass), Contents(Contents_) {}
2551
2552 template<typename Fn> void match(Fn F) const { F(Contents); }
2553
2554 void printLeft(OutputBuffer &OB) const override {
2555 const size_t N = FloatData<Float>::mangled_size;
2556 if (Contents.size() >= N) {
2557 union {
2558 Float value;
2559 char buf[sizeof(Float)];
2560 };
2561 const char *t = Contents.data();
2562 const char *last = t + N;
2563 char *e = buf;
2564 for (; t != last; ++t, ++e) {
2565 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2566 : static_cast<unsigned>(*t - 'a' + 10);
2567 ++t;
2568 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2569 : static_cast<unsigned>(*t - 'a' + 10);
2570 *e = static_cast<char>((d1 << 4) + d0);
2571 }
2572#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2573 std::reverse(buf, e);
2574#endif
2575 char num[FloatData<Float>::max_demangled_size] = {0};
2576 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
2577 OB += std::string_view(num, n);
2578 }
2579 }
2580};
2581
2582using FloatLiteral = FloatLiteralImpl<float>;
2583using DoubleLiteral = FloatLiteralImpl<double>;
2584using LongDoubleLiteral = FloatLiteralImpl<long double>;
2585
2586/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2587/// appropriate derived class.
2588template<typename Fn>
2589void Node::visit(Fn F) const {
2590 switch (K) {
2591#define NODE(X) \
2592 case K##X: \
2593 return F(static_cast<const X *>(this));
2594#include "ItaniumNodes.def"
2595 }
2596 DEMANGLE_ASSERT(0, "unknown mangling node kind");
2597}
2598
2599/// Determine the kind of a node from its type.
2600template<typename NodeT> struct NodeKind;
2601#define NODE(X) \
2602 template <> struct NodeKind<X> { \
2603 static constexpr Node::Kind Kind = Node::K##X; \
2604 static constexpr const char *name() { return #X; } \
2605 };
2606#include "ItaniumNodes.def"
2607
2608template <typename Derived, typename Alloc> struct AbstractManglingParser {
2609 const char *First;
2610 const char *Last;
2611
2612 // Name stack, this is used by the parser to hold temporary names that were
2613 // parsed. The parser collapses multiple names into new nodes to construct
2614 // the AST. Once the parser is finished, names.size() == 1.
2615 PODSmallVector<Node *, 32> Names;
2616
2617 // Substitution table. Itanium supports name substitutions as a means of
2618 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2619 // table.
2620 PODSmallVector<Node *, 32> Subs;
2621
2622 // A list of template argument values corresponding to a template parameter
2623 // list.
2624 using TemplateParamList = PODSmallVector<Node *, 8>;
2625
2626 class ScopedTemplateParamList {
2627 AbstractManglingParser *Parser;
2628 size_t OldNumTemplateParamLists;
2629 TemplateParamList Params;
2630
2631 public:
2632 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2633 : Parser(TheParser),
2634 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
2635 Parser->TemplateParams.push_back(&Params);
2636 }
2637 ~ScopedTemplateParamList() {
2638 DEMANGLE_ASSERT(Parser->TemplateParams.size() >= OldNumTemplateParamLists,
2639 "");
2640 Parser->TemplateParams.shrinkToSize(OldNumTemplateParamLists);
2641 }
2642 TemplateParamList *params() { return &Params; }
2643 };
2644
2645 // Template parameter table. Like the above, but referenced like "T42_".
2646 // This has a smaller size compared to Subs and Names because it can be
2647 // stored on the stack.
2648 TemplateParamList OuterTemplateParams;
2649
2650 // Lists of template parameters indexed by template parameter depth,
2651 // referenced like "TL2_4_". If nonempty, element 0 is always
2652 // OuterTemplateParams; inner elements are always template parameter lists of
2653 // lambda expressions. For a generic lambda with no explicit template
2654 // parameter list, the corresponding parameter list pointer will be null.
2655 PODSmallVector<TemplateParamList *, 4> TemplateParams;
2656
2657 class SaveTemplateParams {
2658 AbstractManglingParser *Parser;
2659 decltype(TemplateParams) OldParams;
2660 decltype(OuterTemplateParams) OldOuterParams;
2661
2662 public:
2663 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
2664 OldParams = std::move(Parser->TemplateParams);
2665 OldOuterParams = std::move(Parser->OuterTemplateParams);
2666 Parser->TemplateParams.clear();
2667 Parser->OuterTemplateParams.clear();
2668 }
2669 ~SaveTemplateParams() {
2670 Parser->TemplateParams = std::move(t&: OldParams);
2671 Parser->OuterTemplateParams = std::move(t&: OldOuterParams);
2672 }
2673 };
2674
2675 // Set of unresolved forward <template-param> references. These can occur in a
2676 // conversion operator's type, and are resolved in the enclosing <encoding>.
2677 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2678
2679 bool TryToParseTemplateArgs = true;
2680 bool PermitForwardTemplateReferences = false;
2681 bool InConstraintExpr = false;
2682 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2683
2684 unsigned NumSyntheticTemplateParameters[3] = {};
2685
2686 Alloc ASTAllocator;
2687
2688 AbstractManglingParser(const char *First_, const char *Last_)
2689 : First(First_), Last(Last_) {}
2690
2691 Derived &getDerived() { return static_cast<Derived &>(*this); }
2692
2693 void reset(const char *First_, const char *Last_) {
2694 First = First_;
2695 Last = Last_;
2696 Names.clear();
2697 Subs.clear();
2698 TemplateParams.clear();
2699 ParsingLambdaParamsAtLevel = (size_t)-1;
2700 TryToParseTemplateArgs = true;
2701 PermitForwardTemplateReferences = false;
2702 for (int I = 0; I != 3; ++I)
2703 NumSyntheticTemplateParameters[I] = 0;
2704 ASTAllocator.reset();
2705 }
2706
2707 template <class T, class... Args> Node *make(Args &&... args) {
2708 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2709 }
2710
2711 template <class It> NodeArray makeNodeArray(It begin, It end) {
2712 size_t sz = static_cast<size_t>(end - begin);
2713 void *mem = ASTAllocator.allocateNodeArray(sz);
2714 Node **data = new (mem) Node *[sz];
2715 std::copy(begin, end, data);
2716 return NodeArray(data, sz);
2717 }
2718
2719 NodeArray popTrailingNodeArray(size_t FromPosition) {
2720 DEMANGLE_ASSERT(FromPosition <= Names.size(), "");
2721 NodeArray res =
2722 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2723 Names.shrinkToSize(Index: FromPosition);
2724 return res;
2725 }
2726
2727 bool consumeIf(std::string_view S) {
2728 if (starts_with(haystack: std::string_view(First, Last - First), needle: S)) {
2729 First += S.size();
2730 return true;
2731 }
2732 return false;
2733 }
2734
2735 bool consumeIf(char C) {
2736 if (First != Last && *First == C) {
2737 ++First;
2738 return true;
2739 }
2740 return false;
2741 }
2742
2743 char consume() { return First != Last ? *First++ : '\0'; }
2744
2745 char look(unsigned Lookahead = 0) const {
2746 if (static_cast<size_t>(Last - First) <= Lookahead)
2747 return '\0';
2748 return First[Lookahead];
2749 }
2750
2751 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2752
2753 std::string_view parseNumber(bool AllowNegative = false);
2754 Qualifiers parseCVQualifiers();
2755 bool parsePositiveInteger(size_t *Out);
2756 std::string_view parseBareSourceName();
2757
2758 bool parseSeqId(size_t *Out);
2759 Node *parseSubstitution();
2760 Node *parseTemplateParam();
2761 Node *parseTemplateParamDecl(TemplateParamList *Params);
2762 Node *parseTemplateArgs(bool TagTemplates = false);
2763 Node *parseTemplateArg();
2764
2765 bool isTemplateParamDecl() {
2766 return look() == 'T' &&
2767 std::string_view("yptnk").find(look(Lookahead: 1)) != std::string_view::npos;
2768 }
2769
2770 /// Parse the <expression> production.
2771 Node *parseExpr();
2772 Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);
2773 Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);
2774 Node *parseIntegerLiteral(std::string_view Lit);
2775 Node *parseExprPrimary();
2776 template <class Float> Node *parseFloatingLiteral();
2777 Node *parseFunctionParam();
2778 Node *parseConversionExpr();
2779 Node *parseBracedExpr();
2780 Node *parseFoldExpr();
2781 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
2782 Node *parseSubobjectExpr();
2783 Node *parseConstraintExpr();
2784 Node *parseRequiresExpr();
2785
2786 /// Parse the <type> production.
2787 Node *parseType();
2788 Node *parseFunctionType();
2789 Node *parseVectorType();
2790 Node *parseDecltype();
2791 Node *parseArrayType();
2792 Node *parsePointerToMemberType();
2793 Node *parseClassEnumType();
2794 Node *parseQualifiedType();
2795
2796 Node *parseEncoding(bool ParseParams = true);
2797 bool parseCallOffset();
2798 Node *parseSpecialName();
2799
2800 /// Holds some extra information about a <name> that is being parsed. This
2801 /// information is only pertinent if the <name> refers to an <encoding>.
2802 struct NameState {
2803 bool CtorDtorConversion = false;
2804 bool EndsWithTemplateArgs = false;
2805 Qualifiers CVQualifiers = QualNone;
2806 FunctionRefQual ReferenceQualifier = FrefQualNone;
2807 size_t ForwardTemplateRefsBegin;
2808 bool HasExplicitObjectParameter = false;
2809
2810 NameState(AbstractManglingParser *Enclosing)
2811 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2812 };
2813
2814 bool resolveForwardTemplateRefs(NameState &State) {
2815 size_t I = State.ForwardTemplateRefsBegin;
2816 size_t E = ForwardTemplateRefs.size();
2817 for (; I < E; ++I) {
2818 size_t Idx = ForwardTemplateRefs[I]->Index;
2819 if (TemplateParams.empty() || !TemplateParams[0] ||
2820 Idx >= TemplateParams[0]->size())
2821 return true;
2822 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
2823 }
2824 ForwardTemplateRefs.shrinkToSize(Index: State.ForwardTemplateRefsBegin);
2825 return false;
2826 }
2827
2828 /// Parse the <name> production>
2829 Node *parseName(NameState *State = nullptr);
2830 Node *parseLocalName(NameState *State);
2831 Node *parseOperatorName(NameState *State);
2832 bool parseModuleNameOpt(ModuleName *&Module);
2833 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
2834 Node *parseUnnamedTypeName(NameState *State);
2835 Node *parseSourceName(NameState *State);
2836 Node *parseUnscopedName(NameState *State, bool *isSubstName);
2837 Node *parseNestedName(NameState *State);
2838 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2839
2840 Node *parseAbiTags(Node *N);
2841
2842 struct OperatorInfo {
2843 enum OIKind : unsigned char {
2844 Prefix, // Prefix unary: @ expr
2845 Postfix, // Postfix unary: expr @
2846 Binary, // Binary: lhs @ rhs
2847 Array, // Array index: lhs [ rhs ]
2848 Member, // Member access: lhs @ rhs
2849 New, // New
2850 Del, // Delete
2851 Call, // Function call: expr (expr*)
2852 CCast, // C cast: (type)expr
2853 Conditional, // Conditional: expr ? expr : expr
2854 NameOnly, // Overload only, not allowed in expression.
2855 // Below do not have operator names
2856 NamedCast, // Named cast, @<type>(expr)
2857 OfIdOp, // alignof, sizeof, typeid
2858
2859 Unnameable = NamedCast,
2860 };
2861 char Enc[2]; // Encoding
2862 OIKind Kind; // Kind of operator
2863 bool Flag : 1; // Entry-specific flag
2864 Node::Prec Prec : 7; // Precedence
2865 const char *Name; // Spelling
2866
2867 public:
2868 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2869 const char *N)
2870 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
2871
2872 public:
2873 bool operator<(const OperatorInfo &Other) const {
2874 return *this < Other.Enc;
2875 }
2876 bool operator<(const char *Peek) const {
2877 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2878 }
2879 bool operator==(const char *Peek) const {
2880 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2881 }
2882 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2883
2884 public:
2885 std::string_view getSymbol() const {
2886 std::string_view Res = Name;
2887 if (Kind < Unnameable) {
2888 DEMANGLE_ASSERT(starts_with(Res, "operator"),
2889 "operator name does not start with 'operator'");
2890 Res.remove_prefix(n: sizeof("operator") - 1);
2891 if (starts_with(self: Res, C: ' '))
2892 Res.remove_prefix(n: 1);
2893 }
2894 return Res;
2895 }
2896 std::string_view getName() const { return Name; }
2897 OIKind getKind() const { return Kind; }
2898 bool getFlag() const { return Flag; }
2899 Node::Prec getPrecedence() const { return Prec; }
2900 };
2901 static const OperatorInfo Ops[];
2902 static const size_t NumOps;
2903 const OperatorInfo *parseOperatorEncoding();
2904
2905 /// Parse the <unresolved-name> production.
2906 Node *parseUnresolvedName(bool Global);
2907 Node *parseSimpleId();
2908 Node *parseBaseUnresolvedName();
2909 Node *parseUnresolvedType();
2910 Node *parseDestructorName();
2911
2912 /// Top-level entry point into the parser.
2913 Node *parse(bool ParseParams = true);
2914};
2915
2916const char* parse_discriminator(const char* first, const char* last);
2917
2918// <name> ::= <nested-name> // N
2919// ::= <local-name> # See Scope Encoding below // Z
2920// ::= <unscoped-template-name> <template-args>
2921// ::= <unscoped-name>
2922//
2923// <unscoped-template-name> ::= <unscoped-name>
2924// ::= <substitution>
2925template <typename Derived, typename Alloc>
2926Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
2927 if (look() == 'N')
2928 return getDerived().parseNestedName(State);
2929 if (look() == 'Z')
2930 return getDerived().parseLocalName(State);
2931
2932 Node *Result = nullptr;
2933 bool IsSubst = false;
2934
2935 Result = getDerived().parseUnscopedName(State, &IsSubst);
2936 if (!Result)
2937 return nullptr;
2938
2939 if (look() == 'I') {
2940 // ::= <unscoped-template-name> <template-args>
2941 if (!IsSubst)
2942 // An unscoped-template-name is substitutable.
2943 Subs.push_back(Elem: Result);
2944 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
2945 if (TA == nullptr)
2946 return nullptr;
2947 if (State)
2948 State->EndsWithTemplateArgs = true;
2949 Result = make<NameWithTemplateArgs>(Result, TA);
2950 } else if (IsSubst) {
2951 // The substitution case must be followed by <template-args>.
2952 return nullptr;
2953 }
2954
2955 return Result;
2956}
2957
2958// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2959// := Z <function encoding> E s [<discriminator>]
2960// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
2961template <typename Derived, typename Alloc>
2962Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
2963 if (!consumeIf('Z'))
2964 return nullptr;
2965 Node *Encoding = getDerived().parseEncoding();
2966 if (Encoding == nullptr || !consumeIf('E'))
2967 return nullptr;
2968
2969 if (consumeIf('s')) {
2970 First = parse_discriminator(first: First, last: Last);
2971 auto *StringLitName = make<NameType>("string literal");
2972 if (!StringLitName)
2973 return nullptr;
2974 return make<LocalName>(Encoding, StringLitName);
2975 }
2976
2977 // The template parameters of the inner name are unrelated to those of the
2978 // enclosing context.
2979 SaveTemplateParams SaveTemplateParamsScope(this);
2980
2981 if (consumeIf('d')) {
2982 parseNumber(AllowNegative: true);
2983 if (!consumeIf('_'))
2984 return nullptr;
2985 Node *N = getDerived().parseName(State);
2986 if (N == nullptr)
2987 return nullptr;
2988 return make<LocalName>(Encoding, N);
2989 }
2990
2991 Node *Entity = getDerived().parseName(State);
2992 if (Entity == nullptr)
2993 return nullptr;
2994 First = parse_discriminator(first: First, last: Last);
2995 return make<LocalName>(Encoding, Entity);
2996}
2997
2998// <unscoped-name> ::= <unqualified-name>
2999// ::= St <unqualified-name> # ::std::
3000// [*] extension
3001template <typename Derived, typename Alloc>
3002Node *
3003AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
3004 bool *IsSubst) {
3005
3006 Node *Std = nullptr;
3007 if (consumeIf("St")) {
3008 Std = make<NameType>("std");
3009 if (Std == nullptr)
3010 return nullptr;
3011 }
3012
3013 Node *Res = nullptr;
3014 ModuleName *Module = nullptr;
3015 if (look() == 'S') {
3016 Node *S = getDerived().parseSubstitution();
3017 if (!S)
3018 return nullptr;
3019 if (S->getKind() == Node::KModuleName)
3020 Module = static_cast<ModuleName *>(S);
3021 else if (IsSubst && Std == nullptr) {
3022 Res = S;
3023 *IsSubst = true;
3024 } else {
3025 return nullptr;
3026 }
3027 }
3028
3029 if (Res == nullptr || Std != nullptr) {
3030 Res = getDerived().parseUnqualifiedName(State, Std, Module);
3031 }
3032
3033 return Res;
3034}
3035
3036// <unqualified-name> ::= [<module-name>] F? L? <operator-name> [<abi-tags>]
3037// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
3038// ::= [<module-name>] F? L? <source-name> [<abi-tags>]
3039// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
3040// # structured binding declaration
3041// ::= [<module-name>] L? DC <source-name>+ E
3042template <typename Derived, typename Alloc>
3043Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
3044 NameState *State, Node *Scope, ModuleName *Module) {
3045 if (getDerived().parseModuleNameOpt(Module))
3046 return nullptr;
3047
3048 bool IsMemberLikeFriend = Scope && consumeIf('F');
3049
3050 consumeIf('L');
3051
3052 Node *Result;
3053 if (look() >= '1' && look() <= '9') {
3054 Result = getDerived().parseSourceName(State);
3055 } else if (look() == 'U') {
3056 Result = getDerived().parseUnnamedTypeName(State);
3057 } else if (consumeIf("DC")) {
3058 // Structured binding
3059 size_t BindingsBegin = Names.size();
3060 do {
3061 Node *Binding = getDerived().parseSourceName(State);
3062 if (Binding == nullptr)
3063 return nullptr;
3064 Names.push_back(Elem: Binding);
3065 } while (!consumeIf('E'));
3066 Result = make<StructuredBindingName>(popTrailingNodeArray(FromPosition: BindingsBegin));
3067 } else if (look() == 'C' || look() == 'D') {
3068 // A <ctor-dtor-name>.
3069 if (Scope == nullptr || Module != nullptr)
3070 return nullptr;
3071 Result = getDerived().parseCtorDtorName(Scope, State);
3072 } else {
3073 Result = getDerived().parseOperatorName(State);
3074 }
3075
3076 if (Result != nullptr && Module != nullptr)
3077 Result = make<ModuleEntity>(Module, Result);
3078 if (Result != nullptr)
3079 Result = getDerived().parseAbiTags(Result);
3080 if (Result != nullptr && IsMemberLikeFriend)
3081 Result = make<MemberLikeFriendName>(Scope, Result);
3082 else if (Result != nullptr && Scope != nullptr)
3083 Result = make<NestedName>(Scope, Result);
3084
3085 return Result;
3086}
3087
3088// <module-name> ::= <module-subname>
3089// ::= <module-name> <module-subname>
3090// ::= <substitution> # passed in by caller
3091// <module-subname> ::= W <source-name>
3092// ::= W P <source-name>
3093template <typename Derived, typename Alloc>
3094bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
3095 ModuleName *&Module) {
3096 while (consumeIf('W')) {
3097 bool IsPartition = consumeIf('P');
3098 Node *Sub = getDerived().parseSourceName(nullptr);
3099 if (!Sub)
3100 return true;
3101 Module =
3102 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
3103 Subs.push_back(Elem: Module);
3104 }
3105
3106 return false;
3107}
3108
3109// <unnamed-type-name> ::= Ut [<nonnegative number>] _
3110// ::= <closure-type-name>
3111//
3112// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
3113//
3114// <lambda-sig> ::= <template-param-decl>* [Q <requires-clause expression>]
3115// <parameter type>+ # or "v" if the lambda has no parameters
3116template <typename Derived, typename Alloc>
3117Node *
3118AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
3119 // <template-params> refer to the innermost <template-args>. Clear out any
3120 // outer args that we may have inserted into TemplateParams.
3121 if (State != nullptr)
3122 TemplateParams.clear();
3123
3124 if (consumeIf("Ut")) {
3125 std::string_view Count = parseNumber();
3126 if (!consumeIf('_'))
3127 return nullptr;
3128 return make<UnnamedTypeName>(Count);
3129 }
3130 if (consumeIf("Ul")) {
3131 ScopedOverride<size_t> SwapParams(ParsingLambdaParamsAtLevel,
3132 TemplateParams.size());
3133 ScopedTemplateParamList LambdaTemplateParams(this);
3134
3135 size_t ParamsBegin = Names.size();
3136 while (getDerived().isTemplateParamDecl()) {
3137 Node *T =
3138 getDerived().parseTemplateParamDecl(LambdaTemplateParams.params());
3139 if (T == nullptr)
3140 return nullptr;
3141 Names.push_back(Elem: T);
3142 }
3143 NodeArray TempParams = popTrailingNodeArray(FromPosition: ParamsBegin);
3144
3145 // FIXME: If TempParams is empty and none of the function parameters
3146 // includes 'auto', we should remove LambdaTemplateParams from the
3147 // TemplateParams list. Unfortunately, we don't find out whether there are
3148 // any 'auto' parameters until too late in an example such as:
3149 //
3150 // template<typename T> void f(
3151 // decltype([](decltype([]<typename T>(T v) {}),
3152 // auto) {})) {}
3153 // template<typename T> void f(
3154 // decltype([](decltype([]<typename T>(T w) {}),
3155 // int) {})) {}
3156 //
3157 // Here, the type of v is at level 2 but the type of w is at level 1. We
3158 // don't find this out until we encounter the type of the next parameter.
3159 //
3160 // However, compilers can't actually cope with the former example in
3161 // practice, and it's likely to be made ill-formed in future, so we don't
3162 // need to support it here.
3163 //
3164 // If we encounter an 'auto' in the function parameter types, we will
3165 // recreate a template parameter scope for it, but any intervening lambdas
3166 // will be parsed in the 'wrong' template parameter depth.
3167 if (TempParams.empty())
3168 TemplateParams.pop_back();
3169
3170 Node *Requires1 = nullptr;
3171 if (consumeIf('Q')) {
3172 Requires1 = getDerived().parseConstraintExpr();
3173 if (Requires1 == nullptr)
3174 return nullptr;
3175 }
3176
3177 if (!consumeIf("v")) {
3178 do {
3179 Node *P = getDerived().parseType();
3180 if (P == nullptr)
3181 return nullptr;
3182 Names.push_back(Elem: P);
3183 } while (look() != 'E' && look() != 'Q');
3184 }
3185 NodeArray Params = popTrailingNodeArray(FromPosition: ParamsBegin);
3186
3187 Node *Requires2 = nullptr;
3188 if (consumeIf('Q')) {
3189 Requires2 = getDerived().parseConstraintExpr();
3190 if (Requires2 == nullptr)
3191 return nullptr;
3192 }
3193
3194 if (!consumeIf('E'))
3195 return nullptr;
3196
3197 std::string_view Count = parseNumber();
3198 if (!consumeIf('_'))
3199 return nullptr;
3200 return make<ClosureTypeName>(TempParams, Requires1, Params, Requires2,
3201 Count);
3202 }
3203 if (consumeIf("Ub")) {
3204 (void)parseNumber();
3205 if (!consumeIf('_'))
3206 return nullptr;
3207 return make<NameType>("'block-literal'");
3208 }
3209 return nullptr;
3210}
3211
3212// <source-name> ::= <positive length number> <identifier>
3213template <typename Derived, typename Alloc>
3214Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
3215 size_t Length = 0;
3216 if (parsePositiveInteger(Out: &Length))
3217 return nullptr;
3218 if (numLeft() < Length || Length == 0)
3219 return nullptr;
3220 std::string_view Name(First, Length);
3221 First += Length;
3222 if (starts_with(haystack: Name, needle: "_GLOBAL__N"))
3223 return make<NameType>("(anonymous namespace)");
3224 return make<NameType>(Name);
3225}
3226
3227// Operator encodings
3228template <typename Derived, typename Alloc>
3229const typename AbstractManglingParser<
3230 Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,
3231 Alloc>::Ops[] = {
3232 // Keep ordered by encoding
3233 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
3234 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
3235 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
3236 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
3237 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
3238 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},
3239 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
3240 "operator co_await"},
3241 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},
3242 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
3243 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
3244 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
3245 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
3246 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast
3247 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
3248 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
3249 "operator delete[]"},
3250 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},
3251 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
3252 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
3253 "operator delete"},
3254 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3255 "operator.*"},
3256 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
3257 "operator."},
3258 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
3259 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
3260 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
3261 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
3262 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
3263 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
3264 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
3265 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
3266 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
3267 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
3268 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
3269 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
3270 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
3271 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
3272 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3273 "operator*"},
3274 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
3275 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
3276 "operator new[]"},
3277 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
3278 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
3279 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
3280 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},
3281 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
3282 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
3283 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
3284 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
3285 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
3286 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3287 "operator->*"},
3288 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
3289 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
3290 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
3291 "operator->"},
3292 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
3293 "operator?"},
3294 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
3295 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
3296 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3297 "reinterpret_cast"},
3298 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3299 "operator%"},
3300 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3301 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},
3302 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3303 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3304 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},
3305 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3306 "typeid "},
3307 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
3308};
3309template <typename Derived, typename Alloc>
3310const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /
3311 sizeof(Ops[0]);
3312
3313// If the next 2 chars are an operator encoding, consume them and return their
3314// OperatorInfo. Otherwise return nullptr.
3315template <typename Derived, typename Alloc>
3316const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
3317AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
3318 if (numLeft() < 2)
3319 return nullptr;
3320
3321 // We can't use lower_bound as that can link to symbols in the C++ library,
3322 // and this must remain independant of that.
3323 size_t lower = 0u, upper = NumOps - 1; // Inclusive bounds.
3324 while (upper != lower) {
3325 size_t middle = (upper + lower) / 2;
3326 if (Ops[middle] < First)
3327 lower = middle + 1;
3328 else
3329 upper = middle;
3330 }
3331 if (Ops[lower] != First)
3332 return nullptr;
3333
3334 First += 2;
3335 return &Ops[lower];
3336}
3337
3338// <operator-name> ::= See parseOperatorEncoding()
3339// ::= li <source-name> # operator ""
3340// ::= v <digit> <source-name> # vendor extended operator
3341template <typename Derived, typename Alloc>
3342Node *
3343AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
3344 if (const auto *Op = parseOperatorEncoding()) {
3345 if (Op->getKind() == OperatorInfo::CCast) {
3346 // ::= cv <type> # (cast)
3347 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);
3348 // If we're parsing an encoding, State != nullptr and the conversion
3349 // operators' <type> could have a <template-param> that refers to some
3350 // <template-arg>s further ahead in the mangled name.
3351 ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,
3352 PermitForwardTemplateReferences ||
3353 State != nullptr);
3354 Node *Ty = getDerived().parseType();
3355 if (Ty == nullptr)
3356 return nullptr;
3357 if (State) State->CtorDtorConversion = true;
3358 return make<ConversionOperatorType>(Ty);
3359 }
3360
3361 if (Op->getKind() >= OperatorInfo::Unnameable)
3362 /* Not a nameable operator. */
3363 return nullptr;
3364 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3365 /* Not a nameable MemberExpr */
3366 return nullptr;
3367
3368 return make<NameType>(Op->getName());
3369 }
3370
3371 if (consumeIf("li")) {
3372 // ::= li <source-name> # operator ""
3373 Node *SN = getDerived().parseSourceName(State);
3374 if (SN == nullptr)
3375 return nullptr;
3376 return make<LiteralOperator>(SN);
3377 }
3378
3379 if (consumeIf('v')) {
3380 // ::= v <digit> <source-name> # vendor extended operator
3381 if (look() >= '0' && look() <= '9') {
3382 First++;
3383 Node *SN = getDerived().parseSourceName(State);
3384 if (SN == nullptr)
3385 return nullptr;
3386 return make<ConversionOperatorType>(SN);
3387 }
3388 return nullptr;
3389 }
3390
3391 return nullptr;
3392}
3393
3394// <ctor-dtor-name> ::= C1 # complete object constructor
3395// ::= C2 # base object constructor
3396// ::= C3 # complete object allocating constructor
3397// extension ::= C4 # gcc old-style "[unified]" constructor
3398// extension ::= C5 # the COMDAT used for ctors
3399// ::= D0 # deleting destructor
3400// ::= D1 # complete object destructor
3401// ::= D2 # base object destructor
3402// extension ::= D4 # gcc old-style "[unified]" destructor
3403// extension ::= D5 # the COMDAT used for dtors
3404template <typename Derived, typename Alloc>
3405Node *
3406AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3407 NameState *State) {
3408 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3409 // Expand the special substitution.
3410 SoFar = make<ExpandedSpecialSubstitution>(
3411 static_cast<SpecialSubstitution *>(SoFar));
3412 if (!SoFar)
3413 return nullptr;
3414 }
3415
3416 if (consumeIf('C')) {
3417 bool IsInherited = consumeIf('I');
3418 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3419 look() != '5')
3420 return nullptr;
3421 int Variant = look() - '0';
3422 ++First;
3423 if (State) State->CtorDtorConversion = true;
3424 if (IsInherited) {
3425 if (getDerived().parseName(State) == nullptr)
3426 return nullptr;
3427 }
3428 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
3429 }
3430
3431 if (look() == 'D' && (look(Lookahead: 1) == '0' || look(Lookahead: 1) == '1' || look(Lookahead: 1) == '2' ||
3432 look(Lookahead: 1) == '4' || look(Lookahead: 1) == '5')) {
3433 int Variant = look(Lookahead: 1) - '0';
3434 First += 2;
3435 if (State) State->CtorDtorConversion = true;
3436 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
3437 }
3438
3439 return nullptr;
3440}
3441
3442// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3443// <unqualified-name> E
3444// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3445// <template-args> E
3446//
3447// <prefix> ::= <prefix> <unqualified-name>
3448// ::= <template-prefix> <template-args>
3449// ::= <template-param>
3450// ::= <decltype>
3451// ::= # empty
3452// ::= <substitution>
3453// ::= <prefix> <data-member-prefix>
3454// [*] extension
3455//
3456// <data-member-prefix> := <member source-name> [<template-args>] M
3457//
3458// <template-prefix> ::= <prefix> <template unqualified-name>
3459// ::= <template-param>
3460// ::= <substitution>
3461template <typename Derived, typename Alloc>
3462Node *
3463AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
3464 if (!consumeIf('N'))
3465 return nullptr;
3466
3467 // 'H' specifies that the encoding that follows
3468 // has an explicit object parameter.
3469 if (!consumeIf('H')) {
3470 Qualifiers CVTmp = parseCVQualifiers();
3471 if (State)
3472 State->CVQualifiers = CVTmp;
3473
3474 if (consumeIf('O')) {
3475 if (State)
3476 State->ReferenceQualifier = FrefQualRValue;
3477 } else if (consumeIf('R')) {
3478 if (State)
3479 State->ReferenceQualifier = FrefQualLValue;
3480 } else {
3481 if (State)
3482 State->ReferenceQualifier = FrefQualNone;
3483 }
3484 } else if (State) {
3485 State->HasExplicitObjectParameter = true;
3486 }
3487
3488 Node *SoFar = nullptr;
3489 while (!consumeIf('E')) {
3490 if (State)
3491 // Only set end-with-template on the case that does that.
3492 State->EndsWithTemplateArgs = false;
3493
3494 if (look() == 'T') {
3495 // ::= <template-param>
3496 if (SoFar != nullptr)
3497 return nullptr; // Cannot have a prefix.
3498 SoFar = getDerived().parseTemplateParam();
3499 } else if (look() == 'I') {
3500 // ::= <template-prefix> <template-args>
3501 if (SoFar == nullptr)
3502 return nullptr; // Must have a prefix.
3503 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
3504 if (TA == nullptr)
3505 return nullptr;
3506 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3507 // Semantically <template-args> <template-args> cannot be generated by a
3508 // C++ entity. There will always be [something like] a name between
3509 // them.
3510 return nullptr;
3511 if (State)
3512 State->EndsWithTemplateArgs = true;
3513 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3514 } else if (look() == 'D' && (look(Lookahead: 1) == 't' || look(Lookahead: 1) == 'T')) {
3515 // ::= <decltype>
3516 if (SoFar != nullptr)
3517 return nullptr; // Cannot have a prefix.
3518 SoFar = getDerived().parseDecltype();
3519 } else {
3520 ModuleName *Module = nullptr;
3521
3522 if (look() == 'S') {
3523 // ::= <substitution>
3524 Node *S = nullptr;
3525 if (look(Lookahead: 1) == 't') {
3526 First += 2;
3527 S = make<NameType>("std");
3528 } else {
3529 S = getDerived().parseSubstitution();
3530 }
3531 if (!S)
3532 return nullptr;
3533 if (S->getKind() == Node::KModuleName) {
3534 Module = static_cast<ModuleName *>(S);
3535 } else if (SoFar != nullptr) {
3536 return nullptr; // Cannot have a prefix.
3537 } else {
3538 SoFar = S;
3539 continue; // Do not push a new substitution.
3540 }
3541 }
3542
3543 // ::= [<prefix>] <unqualified-name>
3544 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
3545 }
3546
3547 if (SoFar == nullptr)
3548 return nullptr;
3549 Subs.push_back(Elem: SoFar);
3550
3551 // No longer used.
3552 // <data-member-prefix> := <member source-name> [<template-args>] M
3553 consumeIf('M');
3554 }
3555
3556 if (SoFar == nullptr || Subs.empty())
3557 return nullptr;
3558
3559 Subs.pop_back();
3560 return SoFar;
3561}
3562
3563// <simple-id> ::= <source-name> [ <template-args> ]
3564template <typename Derived, typename Alloc>
3565Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3566 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
3567 if (SN == nullptr)
3568 return nullptr;
3569 if (look() == 'I') {
3570 Node *TA = getDerived().parseTemplateArgs();
3571 if (TA == nullptr)
3572 return nullptr;
3573 return make<NameWithTemplateArgs>(SN, TA);
3574 }
3575 return SN;
3576}
3577
3578// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3579// ::= <simple-id> # e.g., ~A<2*N>
3580template <typename Derived, typename Alloc>
3581Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
3582 Node *Result;
3583 if (std::isdigit(look()))
3584 Result = getDerived().parseSimpleId();
3585 else
3586 Result = getDerived().parseUnresolvedType();
3587 if (Result == nullptr)
3588 return nullptr;
3589 return make<DtorName>(Result);
3590}
3591
3592// <unresolved-type> ::= <template-param>
3593// ::= <decltype>
3594// ::= <substitution>
3595template <typename Derived, typename Alloc>
3596Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
3597 if (look() == 'T') {
3598 Node *TP = getDerived().parseTemplateParam();
3599 if (TP == nullptr)
3600 return nullptr;
3601 Subs.push_back(Elem: TP);
3602 return TP;
3603 }
3604 if (look() == 'D') {
3605 Node *DT = getDerived().parseDecltype();
3606 if (DT == nullptr)
3607 return nullptr;
3608 Subs.push_back(Elem: DT);
3609 return DT;
3610 }
3611 return getDerived().parseSubstitution();
3612}
3613
3614// <base-unresolved-name> ::= <simple-id> # unresolved name
3615// extension ::= <operator-name> # unresolved operator-function-id
3616// extension ::= <operator-name> <template-args> # unresolved operator template-id
3617// ::= on <operator-name> # unresolved operator-function-id
3618// ::= on <operator-name> <template-args> # unresolved operator template-id
3619// ::= dn <destructor-name> # destructor or pseudo-destructor;
3620// # e.g. ~X or ~X<N-1>
3621template <typename Derived, typename Alloc>
3622Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
3623 if (std::isdigit(look()))
3624 return getDerived().parseSimpleId();
3625
3626 if (consumeIf("dn"))
3627 return getDerived().parseDestructorName();
3628
3629 consumeIf("on");
3630
3631 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
3632 if (Oper == nullptr)
3633 return nullptr;
3634 if (look() == 'I') {
3635 Node *TA = getDerived().parseTemplateArgs();
3636 if (TA == nullptr)
3637 return nullptr;
3638 return make<NameWithTemplateArgs>(Oper, TA);
3639 }
3640 return Oper;
3641}
3642
3643// <unresolved-name>
3644// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3645// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3646// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3647// # A::x, N::y, A<T>::z; "gs" means leading "::"
3648// [gs] has been parsed by caller.
3649// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3650// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3651// # T::N::x /decltype(p)::N::x
3652// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3653//
3654// <unresolved-qualifier-level> ::= <simple-id>
3655template <typename Derived, typename Alloc>
3656Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
3657 Node *SoFar = nullptr;
3658
3659 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3660 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3661 if (consumeIf("srN")) {
3662 SoFar = getDerived().parseUnresolvedType();
3663 if (SoFar == nullptr)
3664 return nullptr;
3665
3666 if (look() == 'I') {
3667 Node *TA = getDerived().parseTemplateArgs();
3668 if (TA == nullptr)
3669 return nullptr;
3670 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3671 if (!SoFar)
3672 return nullptr;
3673 }
3674
3675 while (!consumeIf('E')) {
3676 Node *Qual = getDerived().parseSimpleId();
3677 if (Qual == nullptr)
3678 return nullptr;
3679 SoFar = make<QualifiedName>(SoFar, Qual);
3680 if (!SoFar)
3681 return nullptr;
3682 }
3683
3684 Node *Base = getDerived().parseBaseUnresolvedName();
3685 if (Base == nullptr)
3686 return nullptr;
3687 return make<QualifiedName>(SoFar, Base);
3688 }
3689
3690 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3691 if (!consumeIf("sr")) {
3692 SoFar = getDerived().parseBaseUnresolvedName();
3693 if (SoFar == nullptr)
3694 return nullptr;
3695 if (Global)
3696 SoFar = make<GlobalQualifiedName>(SoFar);
3697 return SoFar;
3698 }
3699
3700 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3701 if (std::isdigit(look())) {
3702 do {
3703 Node *Qual = getDerived().parseSimpleId();
3704 if (Qual == nullptr)
3705 return nullptr;
3706 if (SoFar)
3707 SoFar = make<QualifiedName>(SoFar, Qual);
3708 else if (Global)
3709 SoFar = make<GlobalQualifiedName>(Qual);
3710 else
3711 SoFar = Qual;
3712 if (!SoFar)
3713 return nullptr;
3714 } while (!consumeIf('E'));
3715 }
3716 // sr <unresolved-type> <base-unresolved-name>
3717 // sr <unresolved-type> <template-args> <base-unresolved-name>
3718 else {
3719 SoFar = getDerived().parseUnresolvedType();
3720 if (SoFar == nullptr)
3721 return nullptr;
3722
3723 if (look() == 'I') {
3724 Node *TA = getDerived().parseTemplateArgs();
3725 if (TA == nullptr)
3726 return nullptr;
3727 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3728 if (!SoFar)
3729 return nullptr;
3730 }
3731 }
3732
3733 DEMANGLE_ASSERT(SoFar != nullptr, "");
3734
3735 Node *Base = getDerived().parseBaseUnresolvedName();
3736 if (Base == nullptr)
3737 return nullptr;
3738 return make<QualifiedName>(SoFar, Base);
3739}
3740
3741// <abi-tags> ::= <abi-tag> [<abi-tags>]
3742// <abi-tag> ::= B <source-name>
3743template <typename Derived, typename Alloc>
3744Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
3745 while (consumeIf('B')) {
3746 std::string_view SN = parseBareSourceName();
3747 if (SN.empty())
3748 return nullptr;
3749 N = make<AbiTagAttr>(N, SN);
3750 if (!N)
3751 return nullptr;
3752 }
3753 return N;
3754}
3755
3756// <number> ::= [n] <non-negative decimal integer>
3757template <typename Alloc, typename Derived>
3758std::string_view
3759AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
3760 const char *Tmp = First;
3761 if (AllowNegative)
3762 consumeIf('n');
3763 if (numLeft() == 0 || !std::isdigit(*First))
3764 return std::string_view();
3765 while (numLeft() != 0 && std::isdigit(*First))
3766 ++First;
3767 return std::string_view(Tmp, First - Tmp);
3768}
3769
3770// <positive length number> ::= [0-9]*
3771template <typename Alloc, typename Derived>
3772bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
3773 *Out = 0;
3774 if (look() < '0' || look() > '9')
3775 return true;
3776 while (look() >= '0' && look() <= '9') {
3777 *Out *= 10;
3778 *Out += static_cast<size_t>(consume() - '0');
3779 }
3780 return false;
3781}
3782
3783template <typename Alloc, typename Derived>
3784std::string_view AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
3785 size_t Int = 0;
3786 if (parsePositiveInteger(Out: &Int) || numLeft() < Int)
3787 return {};
3788 std::string_view R(First, Int);
3789 First += Int;
3790 return R;
3791}
3792
3793// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3794//
3795// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3796// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3797// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3798//
3799// <ref-qualifier> ::= R # & ref-qualifier
3800// <ref-qualifier> ::= O # && ref-qualifier
3801template <typename Derived, typename Alloc>
3802Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
3803 Qualifiers CVQuals = parseCVQualifiers();
3804
3805 Node *ExceptionSpec = nullptr;
3806 if (consumeIf("Do")) {
3807 ExceptionSpec = make<NameType>("noexcept");
3808 if (!ExceptionSpec)
3809 return nullptr;
3810 } else if (consumeIf("DO")) {
3811 Node *E = getDerived().parseExpr();
3812 if (E == nullptr || !consumeIf('E'))
3813 return nullptr;
3814 ExceptionSpec = make<NoexceptSpec>(E);
3815 if (!ExceptionSpec)
3816 return nullptr;
3817 } else if (consumeIf("Dw")) {
3818 size_t SpecsBegin = Names.size();
3819 while (!consumeIf('E')) {
3820 Node *T = getDerived().parseType();
3821 if (T == nullptr)
3822 return nullptr;
3823 Names.push_back(Elem: T);
3824 }
3825 ExceptionSpec =
3826 make<DynamicExceptionSpec>(popTrailingNodeArray(FromPosition: SpecsBegin));
3827 if (!ExceptionSpec)
3828 return nullptr;
3829 }
3830
3831 consumeIf("Dx"); // transaction safe
3832
3833 if (!consumeIf('F'))
3834 return nullptr;
3835 consumeIf('Y'); // extern "C"
3836 Node *ReturnType = getDerived().parseType();
3837 if (ReturnType == nullptr)
3838 return nullptr;
3839
3840 FunctionRefQual ReferenceQualifier = FrefQualNone;
3841 size_t ParamsBegin = Names.size();
3842 while (true) {
3843 if (consumeIf('E'))
3844 break;
3845 if (consumeIf('v'))
3846 continue;
3847 if (consumeIf("RE")) {
3848 ReferenceQualifier = FrefQualLValue;
3849 break;
3850 }
3851 if (consumeIf("OE")) {
3852 ReferenceQualifier = FrefQualRValue;
3853 break;
3854 }
3855 Node *T = getDerived().parseType();
3856 if (T == nullptr)
3857 return nullptr;
3858 Names.push_back(Elem: T);
3859 }
3860
3861 NodeArray Params = popTrailingNodeArray(FromPosition: ParamsBegin);
3862 return make<FunctionType>(ReturnType, Params, CVQuals,
3863 ReferenceQualifier, ExceptionSpec);
3864}
3865
3866// extension:
3867// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3868// ::= Dv [<dimension expression>] _ <element type>
3869// <extended element type> ::= <element type>
3870// ::= p # AltiVec vector pixel
3871template <typename Derived, typename Alloc>
3872Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
3873 if (!consumeIf("Dv"))
3874 return nullptr;
3875 if (look() >= '1' && look() <= '9') {
3876 Node *DimensionNumber = make<NameType>(parseNumber());
3877 if (!DimensionNumber)
3878 return nullptr;
3879 if (!consumeIf('_'))
3880 return nullptr;
3881 if (consumeIf('p'))
3882 return make<PixelVectorType>(DimensionNumber);
3883 Node *ElemType = getDerived().parseType();
3884 if (ElemType == nullptr)
3885 return nullptr;
3886 return make<VectorType>(ElemType, DimensionNumber);
3887 }
3888
3889 if (!consumeIf('_')) {
3890 Node *DimExpr = getDerived().parseExpr();
3891 if (!DimExpr)
3892 return nullptr;
3893 if (!consumeIf('_'))
3894 return nullptr;
3895 Node *ElemType = getDerived().parseType();
3896 if (!ElemType)
3897 return nullptr;
3898 return make<VectorType>(ElemType, DimExpr);
3899 }
3900 Node *ElemType = getDerived().parseType();
3901 if (!ElemType)
3902 return nullptr;
3903 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
3904}
3905
3906// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3907// ::= DT <expression> E # decltype of an expression (C++0x)
3908template <typename Derived, typename Alloc>
3909Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
3910 if (!consumeIf('D'))
3911 return nullptr;
3912 if (!consumeIf('t') && !consumeIf('T'))
3913 return nullptr;
3914 Node *E = getDerived().parseExpr();
3915 if (E == nullptr)
3916 return nullptr;
3917 if (!consumeIf('E'))
3918 return nullptr;
3919 return make<EnclosingExpr>("decltype", E);
3920}
3921
3922// <array-type> ::= A <positive dimension number> _ <element type>
3923// ::= A [<dimension expression>] _ <element type>
3924template <typename Derived, typename Alloc>
3925Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
3926 if (!consumeIf('A'))
3927 return nullptr;
3928
3929 Node *Dimension = nullptr;
3930
3931 if (std::isdigit(look())) {
3932 Dimension = make<NameType>(parseNumber());
3933 if (!Dimension)
3934 return nullptr;
3935 if (!consumeIf('_'))
3936 return nullptr;
3937 } else if (!consumeIf('_')) {
3938 Node *DimExpr = getDerived().parseExpr();
3939 if (DimExpr == nullptr)
3940 return nullptr;
3941 if (!consumeIf('_'))
3942 return nullptr;
3943 Dimension = DimExpr;
3944 }
3945
3946 Node *Ty = getDerived().parseType();
3947 if (Ty == nullptr)
3948 return nullptr;
3949 return make<ArrayType>(Ty, Dimension);
3950}
3951
3952// <pointer-to-member-type> ::= M <class type> <member type>
3953template <typename Derived, typename Alloc>
3954Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
3955 if (!consumeIf('M'))
3956 return nullptr;
3957 Node *ClassType = getDerived().parseType();
3958 if (ClassType == nullptr)
3959 return nullptr;
3960 Node *MemberType = getDerived().parseType();
3961 if (MemberType == nullptr)
3962 return nullptr;
3963 return make<PointerToMemberType>(ClassType, MemberType);
3964}
3965
3966// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3967// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3968// ::= Tu <name> # dependent elaborated type specifier using 'union'
3969// ::= Te <name> # dependent elaborated type specifier using 'enum'
3970template <typename Derived, typename Alloc>
3971Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
3972 std::string_view ElabSpef;
3973 if (consumeIf("Ts"))
3974 ElabSpef = "struct";
3975 else if (consumeIf("Tu"))
3976 ElabSpef = "union";
3977 else if (consumeIf("Te"))
3978 ElabSpef = "enum";
3979
3980 Node *Name = getDerived().parseName();
3981 if (Name == nullptr)
3982 return nullptr;
3983
3984 if (!ElabSpef.empty())
3985 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3986
3987 return Name;
3988}
3989
3990// <qualified-type> ::= <qualifiers> <type>
3991// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3992// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
3993template <typename Derived, typename Alloc>
3994Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
3995 if (consumeIf('U')) {
3996 std::string_view Qual = parseBareSourceName();
3997 if (Qual.empty())
3998 return nullptr;
3999
4000 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
4001 if (starts_with(haystack: Qual, needle: "objcproto")) {
4002 constexpr size_t Len = sizeof("objcproto") - 1;
4003 std::string_view ProtoSourceName(Qual.data() + Len, Qual.size() - Len);
4004 std::string_view Proto;
4005 {
4006 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.data()),
4007 SaveLast(Last, &*ProtoSourceName.rbegin() + 1);
4008 Proto = parseBareSourceName();
4009 }
4010 if (Proto.empty())
4011 return nullptr;
4012 Node *Child = getDerived().parseQualifiedType();
4013 if (Child == nullptr)
4014 return nullptr;
4015 return make<ObjCProtoName>(Child, Proto);
4016 }
4017
4018 Node *TA = nullptr;
4019 if (look() == 'I') {
4020 TA = getDerived().parseTemplateArgs();
4021 if (TA == nullptr)
4022 return nullptr;
4023 }
4024
4025 Node *Child = getDerived().parseQualifiedType();
4026 if (Child == nullptr)
4027 return nullptr;
4028 return make<VendorExtQualType>(Child, Qual, TA);
4029 }
4030
4031 Qualifiers Quals = parseCVQualifiers();
4032 Node *Ty = getDerived().parseType();
4033 if (Ty == nullptr)
4034 return nullptr;
4035 if (Quals != QualNone)
4036 Ty = make<QualType>(Ty, Quals);
4037 return Ty;
4038}
4039
4040// <type> ::= <builtin-type>
4041// ::= <qualified-type>
4042// ::= <function-type>
4043// ::= <class-enum-type>
4044// ::= <array-type>
4045// ::= <pointer-to-member-type>
4046// ::= <template-param>
4047// ::= <template-template-param> <template-args>
4048// ::= <decltype>
4049// ::= P <type> # pointer
4050// ::= R <type> # l-value reference
4051// ::= O <type> # r-value reference (C++11)
4052// ::= C <type> # complex pair (C99)
4053// ::= G <type> # imaginary (C99)
4054// ::= <substitution> # See Compression below
4055// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
4056// extension ::= <vector-type> # <vector-type> starts with Dv
4057//
4058// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
4059// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
4060template <typename Derived, typename Alloc>
4061Node *AbstractManglingParser<Derived, Alloc>::parseType() {
4062 Node *Result = nullptr;
4063
4064 switch (look()) {
4065 // ::= <qualified-type>
4066 case 'r':
4067 case 'V':
4068 case 'K': {
4069 unsigned AfterQuals = 0;
4070 if (look(Lookahead: AfterQuals) == 'r') ++AfterQuals;
4071 if (look(Lookahead: AfterQuals) == 'V') ++AfterQuals;
4072 if (look(Lookahead: AfterQuals) == 'K') ++AfterQuals;
4073
4074 if (look(Lookahead: AfterQuals) == 'F' ||
4075 (look(Lookahead: AfterQuals) == 'D' &&
4076 (look(Lookahead: AfterQuals + 1) == 'o' || look(Lookahead: AfterQuals + 1) == 'O' ||
4077 look(Lookahead: AfterQuals + 1) == 'w' || look(Lookahead: AfterQuals + 1) == 'x'))) {
4078 Result = getDerived().parseFunctionType();
4079 break;
4080 }
4081 DEMANGLE_FALLTHROUGH;
4082 }
4083 case 'U': {
4084 Result = getDerived().parseQualifiedType();
4085 break;
4086 }
4087 // <builtin-type> ::= v # void
4088 case 'v':
4089 ++First;
4090 return make<NameType>("void");
4091 // ::= w # wchar_t
4092 case 'w':
4093 ++First;
4094 return make<NameType>("wchar_t");
4095 // ::= b # bool
4096 case 'b':
4097 ++First;
4098 return make<NameType>("bool");
4099 // ::= c # char
4100 case 'c':
4101 ++First;
4102 return make<NameType>("char");
4103 // ::= a # signed char
4104 case 'a':
4105 ++First;
4106 return make<NameType>("signed char");
4107 // ::= h # unsigned char
4108 case 'h':
4109 ++First;
4110 return make<NameType>("unsigned char");
4111 // ::= s # short
4112 case 's':
4113 ++First;
4114 return make<NameType>("short");
4115 // ::= t # unsigned short
4116 case 't':
4117 ++First;
4118 return make<NameType>("unsigned short");
4119 // ::= i # int
4120 case 'i':
4121 ++First;
4122 return make<NameType>("int");
4123 // ::= j # unsigned int
4124 case 'j':
4125 ++First;
4126 return make<NameType>("unsigned int");
4127 // ::= l # long
4128 case 'l':
4129 ++First;
4130 return make<NameType>("long");
4131 // ::= m # unsigned long
4132 case 'm':
4133 ++First;
4134 return make<NameType>("unsigned long");
4135 // ::= x # long long, __int64
4136 case 'x':
4137 ++First;
4138 return make<NameType>("long long");
4139 // ::= y # unsigned long long, __int64
4140 case 'y':
4141 ++First;
4142 return make<NameType>("unsigned long long");
4143 // ::= n # __int128
4144 case 'n':
4145 ++First;
4146 return make<NameType>("__int128");
4147 // ::= o # unsigned __int128
4148 case 'o':
4149 ++First;
4150 return make<NameType>("unsigned __int128");
4151 // ::= f # float
4152 case 'f':
4153 ++First;
4154 return make<NameType>("float");
4155 // ::= d # double
4156 case 'd':
4157 ++First;
4158 return make<NameType>("double");
4159 // ::= e # long double, __float80
4160 case 'e':
4161 ++First;
4162 return make<NameType>("long double");
4163 // ::= g # __float128
4164 case 'g':
4165 ++First;
4166 return make<NameType>("__float128");
4167 // ::= z # ellipsis
4168 case 'z':
4169 ++First;
4170 return make<NameType>("...");
4171
4172 // <builtin-type> ::= u <source-name> # vendor extended type
4173 case 'u': {
4174 ++First;
4175 std::string_view Res = parseBareSourceName();
4176 if (Res.empty())
4177 return nullptr;
4178 // Typically, <builtin-type>s are not considered substitution candidates,
4179 // but the exception to that exception is vendor extended types (Itanium C++
4180 // ABI 5.9.1).
4181 if (consumeIf('I')) {
4182 Node *BaseType = parseType();
4183 if (BaseType == nullptr)
4184 return nullptr;
4185 if (!consumeIf('E'))
4186 return nullptr;
4187 Result = make<TransformedType>(Res, BaseType);
4188 } else
4189 Result = make<NameType>(Res);
4190 break;
4191 }
4192 case 'D':
4193 switch (look(Lookahead: 1)) {
4194 // ::= Dd # IEEE 754r decimal floating point (64 bits)
4195 case 'd':
4196 First += 2;
4197 return make<NameType>("decimal64");
4198 // ::= De # IEEE 754r decimal floating point (128 bits)
4199 case 'e':
4200 First += 2;
4201 return make<NameType>("decimal128");
4202 // ::= Df # IEEE 754r decimal floating point (32 bits)
4203 case 'f':
4204 First += 2;
4205 return make<NameType>("decimal32");
4206 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
4207 case 'h':
4208 First += 2;
4209 return make<NameType>("half");
4210 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
4211 case 'F': {
4212 First += 2;
4213 Node *DimensionNumber = make<NameType>(parseNumber());
4214 if (!DimensionNumber)
4215 return nullptr;
4216 if (!consumeIf('_'))
4217 return nullptr;
4218 return make<BinaryFPType>(DimensionNumber);
4219 }
4220 // ::= DB <number> _ # C23 signed _BitInt(N)
4221 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
4222 // ::= DU <number> _ # C23 unsigned _BitInt(N)
4223 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
4224 case 'B':
4225 case 'U': {
4226 bool Signed = look(Lookahead: 1) == 'B';
4227 First += 2;
4228 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())
4229 : getDerived().parseExpr();
4230 if (!Size)
4231 return nullptr;
4232 if (!consumeIf('_'))
4233 return nullptr;
4234 return make<BitIntType>(Size, Signed);
4235 }
4236 // ::= Di # char32_t
4237 case 'i':
4238 First += 2;
4239 return make<NameType>("char32_t");
4240 // ::= Ds # char16_t
4241 case 's':
4242 First += 2;
4243 return make<NameType>("char16_t");
4244 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
4245 case 'u':
4246 First += 2;
4247 return make<NameType>("char8_t");
4248 // ::= Da # auto (in dependent new-expressions)
4249 case 'a':
4250 First += 2;
4251 return make<NameType>("auto");
4252 // ::= Dc # decltype(auto)
4253 case 'c':
4254 First += 2;
4255 return make<NameType>("decltype(auto)");
4256 // ::= Dk <type-constraint> # constrained auto
4257 // ::= DK <type-constraint> # constrained decltype(auto)
4258 case 'k':
4259 case 'K': {
4260 std::string_view Kind = look(Lookahead: 1) == 'k' ? " auto" : " decltype(auto)";
4261 First += 2;
4262 Node *Constraint = getDerived().parseName();
4263 if (!Constraint)
4264 return nullptr;
4265 return make<PostfixQualifiedType>(Constraint, Kind);
4266 }
4267 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
4268 case 'n':
4269 First += 2;
4270 return make<NameType>("std::nullptr_t");
4271
4272 // ::= <decltype>
4273 case 't':
4274 case 'T': {
4275 Result = getDerived().parseDecltype();
4276 break;
4277 }
4278 // extension ::= <vector-type> # <vector-type> starts with Dv
4279 case 'v': {
4280 Result = getDerived().parseVectorType();
4281 break;
4282 }
4283 // ::= Dp <type> # pack expansion (C++0x)
4284 case 'p': {
4285 First += 2;
4286 Node *Child = getDerived().parseType();
4287 if (!Child)
4288 return nullptr;
4289 Result = make<ParameterPackExpansion>(Child);
4290 break;
4291 }
4292 // Exception specifier on a function type.
4293 case 'o':
4294 case 'O':
4295 case 'w':
4296 // Transaction safe function type.
4297 case 'x':
4298 Result = getDerived().parseFunctionType();
4299 break;
4300 }
4301 break;
4302 // ::= <function-type>
4303 case 'F': {
4304 Result = getDerived().parseFunctionType();
4305 break;
4306 }
4307 // ::= <array-type>
4308 case 'A': {
4309 Result = getDerived().parseArrayType();
4310 break;
4311 }
4312 // ::= <pointer-to-member-type>
4313 case 'M': {
4314 Result = getDerived().parsePointerToMemberType();
4315 break;
4316 }
4317 // ::= <template-param>
4318 case 'T': {
4319 // This could be an elaborate type specifier on a <class-enum-type>.
4320 if (look(Lookahead: 1) == 's' || look(Lookahead: 1) == 'u' || look(Lookahead: 1) == 'e') {
4321 Result = getDerived().parseClassEnumType();
4322 break;
4323 }
4324
4325 Result = getDerived().parseTemplateParam();
4326 if (Result == nullptr)
4327 return nullptr;
4328
4329 // Result could be either of:
4330 // <type> ::= <template-param>
4331 // <type> ::= <template-template-param> <template-args>
4332 //
4333 // <template-template-param> ::= <template-param>
4334 // ::= <substitution>
4335 //
4336 // If this is followed by some <template-args>, and we're permitted to
4337 // parse them, take the second production.
4338
4339 if (TryToParseTemplateArgs && look() == 'I') {
4340 Node *TA = getDerived().parseTemplateArgs();
4341 if (TA == nullptr)
4342 return nullptr;
4343 Result = make<NameWithTemplateArgs>(Result, TA);
4344 }
4345 break;
4346 }
4347 // ::= P <type> # pointer
4348 case 'P': {
4349 ++First;
4350 Node *Ptr = getDerived().parseType();
4351 if (Ptr == nullptr)
4352 return nullptr;
4353 Result = make<PointerType>(Ptr);
4354 break;
4355 }
4356 // ::= R <type> # l-value reference
4357 case 'R': {
4358 ++First;
4359 Node *Ref = getDerived().parseType();
4360 if (Ref == nullptr)
4361 return nullptr;
4362 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4363 break;
4364 }
4365 // ::= O <type> # r-value reference (C++11)
4366 case 'O': {
4367 ++First;
4368 Node *Ref = getDerived().parseType();
4369 if (Ref == nullptr)
4370 return nullptr;
4371 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4372 break;
4373 }
4374 // ::= C <type> # complex pair (C99)
4375 case 'C': {
4376 ++First;
4377 Node *P = getDerived().parseType();
4378 if (P == nullptr)
4379 return nullptr;
4380 Result = make<PostfixQualifiedType>(P, " complex");
4381 break;
4382 }
4383 // ::= G <type> # imaginary (C99)
4384 case 'G': {
4385 ++First;
4386 Node *P = getDerived().parseType();
4387 if (P == nullptr)
4388 return P;
4389 Result = make<PostfixQualifiedType>(P, " imaginary");
4390 break;
4391 }
4392 // ::= <substitution> # See Compression below
4393 case 'S': {
4394 if (look(Lookahead: 1) != 't') {
4395 bool IsSubst = false;
4396 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4397 if (!Result)
4398 return nullptr;
4399
4400 // Sub could be either of:
4401 // <type> ::= <substitution>
4402 // <type> ::= <template-template-param> <template-args>
4403 //
4404 // <template-template-param> ::= <template-param>
4405 // ::= <substitution>
4406 //
4407 // If this is followed by some <template-args>, and we're permitted to
4408 // parse them, take the second production.
4409
4410 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4411 if (!IsSubst)
4412 Subs.push_back(Elem: Result);
4413 Node *TA = getDerived().parseTemplateArgs();
4414 if (TA == nullptr)
4415 return nullptr;
4416 Result = make<NameWithTemplateArgs>(Result, TA);
4417 } else if (IsSubst) {
4418 // If all we parsed was a substitution, don't re-insert into the
4419 // substitution table.
4420 return Result;
4421 }
4422 break;
4423 }
4424 DEMANGLE_FALLTHROUGH;
4425 }
4426 // ::= <class-enum-type>
4427 default: {
4428 Result = getDerived().parseClassEnumType();
4429 break;
4430 }
4431 }
4432
4433 // If we parsed a type, insert it into the substitution table. Note that all
4434 // <builtin-type>s and <substitution>s have already bailed out, because they
4435 // don't get substitutions.
4436 if (Result != nullptr)
4437 Subs.push_back(Elem: Result);
4438 return Result;
4439}
4440
4441template <typename Derived, typename Alloc>
4442Node *
4443AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(std::string_view Kind,
4444 Node::Prec Prec) {
4445 Node *E = getDerived().parseExpr();
4446 if (E == nullptr)
4447 return nullptr;
4448 return make<PrefixExpr>(Kind, E, Prec);
4449}
4450
4451template <typename Derived, typename Alloc>
4452Node *
4453AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(std::string_view Kind,
4454 Node::Prec Prec) {
4455 Node *LHS = getDerived().parseExpr();
4456 if (LHS == nullptr)
4457 return nullptr;
4458 Node *RHS = getDerived().parseExpr();
4459 if (RHS == nullptr)
4460 return nullptr;
4461 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
4462}
4463
4464template <typename Derived, typename Alloc>
4465Node *AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(
4466 std::string_view Lit) {
4467 std::string_view Tmp = parseNumber(AllowNegative: true);
4468 if (!Tmp.empty() && consumeIf('E'))
4469 return make<IntegerLiteral>(Lit, Tmp);
4470 return nullptr;
4471}
4472
4473// <CV-Qualifiers> ::= [r] [V] [K]
4474template <typename Alloc, typename Derived>
4475Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
4476 Qualifiers CVR = QualNone;
4477 if (consumeIf('r'))
4478 CVR |= QualRestrict;
4479 if (consumeIf('V'))
4480 CVR |= QualVolatile;
4481 if (consumeIf('K'))
4482 CVR |= QualConst;
4483 return CVR;
4484}
4485
4486// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4487// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4488// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4489// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
4490// ::= fpT # 'this' expression (not part of standard?)
4491template <typename Derived, typename Alloc>
4492Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
4493 if (consumeIf("fpT"))
4494 return make<NameType>("this");
4495 if (consumeIf("fp")) {
4496 parseCVQualifiers();
4497 std::string_view Num = parseNumber();
4498 if (!consumeIf('_'))
4499 return nullptr;
4500 return make<FunctionParam>(Num);
4501 }
4502 if (consumeIf("fL")) {
4503 if (parseNumber().empty())
4504 return nullptr;
4505 if (!consumeIf('p'))
4506 return nullptr;
4507 parseCVQualifiers();
4508 std::string_view Num = parseNumber();
4509 if (!consumeIf('_'))
4510 return nullptr;
4511 return make<FunctionParam>(Num);
4512 }
4513 return nullptr;
4514}
4515
4516// cv <type> <expression> # conversion with one argument
4517// cv <type> _ <expression>* E # conversion with a different number of arguments
4518template <typename Derived, typename Alloc>
4519Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
4520 if (!consumeIf("cv"))
4521 return nullptr;
4522 Node *Ty;
4523 {
4524 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
4525 Ty = getDerived().parseType();
4526 }
4527
4528 if (Ty == nullptr)
4529 return nullptr;
4530
4531 if (consumeIf('_')) {
4532 size_t ExprsBegin = Names.size();
4533 while (!consumeIf('E')) {
4534 Node *E = getDerived().parseExpr();
4535 if (E == nullptr)
4536 return E;
4537 Names.push_back(Elem: E);
4538 }
4539 NodeArray Exprs = popTrailingNodeArray(FromPosition: ExprsBegin);
4540 return make<ConversionExpr>(Ty, Exprs);
4541 }
4542
4543 Node *E[1] = {getDerived().parseExpr()};
4544 if (E[0] == nullptr)
4545 return nullptr;
4546 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4547}
4548
4549// <expr-primary> ::= L <type> <value number> E # integer literal
4550// ::= L <type> <value float> E # floating literal
4551// ::= L <string type> E # string literal
4552// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
4553// ::= L <lambda type> E # lambda expression
4554// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4555// ::= L <mangled-name> E # external name
4556template <typename Derived, typename Alloc>
4557Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
4558 if (!consumeIf('L'))
4559 return nullptr;
4560 switch (look()) {
4561 case 'w':
4562 ++First;
4563 return getDerived().parseIntegerLiteral("wchar_t");
4564 case 'b':
4565 if (consumeIf("b0E"))
4566 return make<BoolExpr>(0);
4567 if (consumeIf("b1E"))
4568 return make<BoolExpr>(1);
4569 return nullptr;
4570 case 'c':
4571 ++First;
4572 return getDerived().parseIntegerLiteral("char");
4573 case 'a':
4574 ++First;
4575 return getDerived().parseIntegerLiteral("signed char");
4576 case 'h':
4577 ++First;
4578 return getDerived().parseIntegerLiteral("unsigned char");
4579 case 's':
4580 ++First;
4581 return getDerived().parseIntegerLiteral("short");
4582 case 't':
4583 ++First;
4584 return getDerived().parseIntegerLiteral("unsigned short");
4585 case 'i':
4586 ++First;
4587 return getDerived().parseIntegerLiteral("");
4588 case 'j':
4589 ++First;
4590 return getDerived().parseIntegerLiteral("u");
4591 case 'l':
4592 ++First;
4593 return getDerived().parseIntegerLiteral("l");
4594 case 'm':
4595 ++First;
4596 return getDerived().parseIntegerLiteral("ul");
4597 case 'x':
4598 ++First;
4599 return getDerived().parseIntegerLiteral("ll");
4600 case 'y':
4601 ++First;
4602 return getDerived().parseIntegerLiteral("ull");
4603 case 'n':
4604 ++First;
4605 return getDerived().parseIntegerLiteral("__int128");
4606 case 'o':
4607 ++First;
4608 return getDerived().parseIntegerLiteral("unsigned __int128");
4609 case 'f':
4610 ++First;
4611 return getDerived().template parseFloatingLiteral<float>();
4612 case 'd':
4613 ++First;
4614 return getDerived().template parseFloatingLiteral<double>();
4615 case 'e':
4616 ++First;
4617#if defined(__powerpc__) || defined(__s390__)
4618 // Handle cases where long doubles encoded with e have the same size
4619 // and representation as doubles.
4620 return getDerived().template parseFloatingLiteral<double>();
4621#else
4622 return getDerived().template parseFloatingLiteral<long double>();
4623#endif
4624 case '_':
4625 if (consumeIf("_Z")) {
4626 Node *R = getDerived().parseEncoding();
4627 if (R != nullptr && consumeIf('E'))
4628 return R;
4629 }
4630 return nullptr;
4631 case 'A': {
4632 Node *T = getDerived().parseType();
4633 if (T == nullptr)
4634 return nullptr;
4635 // FIXME: We need to include the string contents in the mangling.
4636 if (consumeIf('E'))
4637 return make<StringLiteral>(T);
4638 return nullptr;
4639 }
4640 case 'D':
4641 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
4642 return make<NameType>("nullptr");
4643 return nullptr;
4644 case 'T':
4645 // Invalid mangled name per
4646 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4647 return nullptr;
4648 case 'U': {
4649 // FIXME: Should we support LUb... for block literals?
4650 if (look(Lookahead: 1) != 'l')
4651 return nullptr;
4652 Node *T = parseUnnamedTypeName(State: nullptr);
4653 if (!T || !consumeIf('E'))
4654 return nullptr;
4655 return make<LambdaExpr>(T);
4656 }
4657 default: {
4658 // might be named type
4659 Node *T = getDerived().parseType();
4660 if (T == nullptr)
4661 return nullptr;
4662 std::string_view N = parseNumber(/*AllowNegative=*/AllowNegative: true);
4663 if (N.empty())
4664 return nullptr;
4665 if (!consumeIf('E'))
4666 return nullptr;
4667 return make<EnumLiteral>(T, N);
4668 }
4669 }
4670}
4671
4672// <braced-expression> ::= <expression>
4673// ::= di <field source-name> <braced-expression> # .name = expr
4674// ::= dx <index expression> <braced-expression> # [expr] = expr
4675// ::= dX <range begin expression> <range end expression> <braced-expression>
4676template <typename Derived, typename Alloc>
4677Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
4678 if (look() == 'd') {
4679 switch (look(Lookahead: 1)) {
4680 case 'i': {
4681 First += 2;
4682 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
4683 if (Field == nullptr)
4684 return nullptr;
4685 Node *Init = getDerived().parseBracedExpr();
4686 if (Init == nullptr)
4687 return nullptr;
4688 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4689 }
4690 case 'x': {
4691 First += 2;
4692 Node *Index = getDerived().parseExpr();
4693 if (Index == nullptr)
4694 return nullptr;
4695 Node *Init = getDerived().parseBracedExpr();
4696 if (Init == nullptr)
4697 return nullptr;
4698 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4699 }
4700 case 'X': {
4701 First += 2;
4702 Node *RangeBegin = getDerived().parseExpr();
4703 if (RangeBegin == nullptr)
4704 return nullptr;
4705 Node *RangeEnd = getDerived().parseExpr();
4706 if (RangeEnd == nullptr)
4707 return nullptr;
4708 Node *Init = getDerived().parseBracedExpr();
4709 if (Init == nullptr)
4710 return nullptr;
4711 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4712 }
4713 }
4714 }
4715 return getDerived().parseExpr();
4716}
4717
4718// (not yet in the spec)
4719// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4720// ::= fR <binary-operator-name> <expression> <expression>
4721// ::= fl <binary-operator-name> <expression>
4722// ::= fr <binary-operator-name> <expression>
4723template <typename Derived, typename Alloc>
4724Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
4725 if (!consumeIf('f'))
4726 return nullptr;
4727
4728 bool IsLeftFold = false, HasInitializer = false;
4729 switch (look()) {
4730 default:
4731 return nullptr;
4732 case 'L':
4733 IsLeftFold = true;
4734 HasInitializer = true;
4735 break;
4736 case 'R':
4737 HasInitializer = true;
4738 break;
4739 case 'l':
4740 IsLeftFold = true;
4741 break;
4742 case 'r':
4743 break;
4744 }
4745 ++First;
4746
4747 const auto *Op = parseOperatorEncoding();
4748 if (!Op)
4749 return nullptr;
4750 if (!(Op->getKind() == OperatorInfo::Binary
4751 || (Op->getKind() == OperatorInfo::Member
4752 && Op->getName().back() == '*')))
4753 return nullptr;
4754
4755 Node *Pack = getDerived().parseExpr();
4756 if (Pack == nullptr)
4757 return nullptr;
4758
4759 Node *Init = nullptr;
4760 if (HasInitializer) {
4761 Init = getDerived().parseExpr();
4762 if (Init == nullptr)
4763 return nullptr;
4764 }
4765
4766 if (IsLeftFold && Init)
4767 std::swap(a&: Pack, b&: Init);
4768
4769 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
4770}
4771
4772// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4773//
4774// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4775template <typename Derived, typename Alloc>
4776Node *
4777AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4778 Node::Prec Prec) {
4779 Node *Ty = getDerived().parseType();
4780 if (!Ty)
4781 return nullptr;
4782 Node *Expr = getDerived().parseExpr();
4783 if (!Expr)
4784 return nullptr;
4785 std::string_view Offset = getDerived().parseNumber(true);
4786 if (!consumeIf('E'))
4787 return nullptr;
4788 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
4789}
4790
4791// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4792// <union-selector> ::= _ [<number>]
4793//
4794// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4795template <typename Derived, typename Alloc>
4796Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4797 Node *Ty = getDerived().parseType();
4798 if (!Ty)
4799 return nullptr;
4800 Node *Expr = getDerived().parseExpr();
4801 if (!Expr)
4802 return nullptr;
4803 std::string_view Offset = getDerived().parseNumber(true);
4804 size_t SelectorsBegin = Names.size();
4805 while (consumeIf('_')) {
4806 Node *Selector = make<NameType>(parseNumber());
4807 if (!Selector)
4808 return nullptr;
4809 Names.push_back(Elem: Selector);
4810 }
4811 bool OnePastTheEnd = consumeIf('p');
4812 if (!consumeIf('E'))
4813 return nullptr;
4814 return make<SubobjectExpr>(
4815 Ty, Expr, Offset, popTrailingNodeArray(FromPosition: SelectorsBegin), OnePastTheEnd);
4816}
4817
4818template <typename Derived, typename Alloc>
4819Node *AbstractManglingParser<Derived, Alloc>::parseConstraintExpr() {
4820 // Within this expression, all enclosing template parameter lists are in
4821 // scope.
4822 ScopedOverride<bool> SaveInConstraintExpr(InConstraintExpr, true);
4823 return getDerived().parseExpr();
4824}
4825
4826template <typename Derived, typename Alloc>
4827Node *AbstractManglingParser<Derived, Alloc>::parseRequiresExpr() {
4828 NodeArray Params;
4829 if (consumeIf("rQ")) {
4830 // <expression> ::= rQ <bare-function-type> _ <requirement>+ E
4831 size_t ParamsBegin = Names.size();
4832 while (!consumeIf('_')) {
4833 Node *Type = getDerived().parseType();
4834 if (Type == nullptr)
4835 return nullptr;
4836 Names.push_back(Elem: Type);
4837 }
4838 Params = popTrailingNodeArray(FromPosition: ParamsBegin);
4839 } else if (!consumeIf("rq")) {
4840 // <expression> ::= rq <requirement>+ E
4841 return nullptr;
4842 }
4843
4844 size_t ReqsBegin = Names.size();
4845 do {
4846 Node *Constraint = nullptr;
4847 if (consumeIf('X')) {
4848 // <requirement> ::= X <expression> [N] [R <type-constraint>]
4849 Node *Expr = getDerived().parseExpr();
4850 if (Expr == nullptr)
4851 return nullptr;
4852 bool Noexcept = consumeIf('N');
4853 Node *TypeReq = nullptr;
4854 if (consumeIf('R')) {
4855 TypeReq = getDerived().parseName();
4856 if (TypeReq == nullptr)
4857 return nullptr;
4858 }
4859 Constraint = make<ExprRequirement>(Expr, Noexcept, TypeReq);
4860 } else if (consumeIf('T')) {
4861 // <requirement> ::= T <type>
4862 Node *Type = getDerived().parseType();
4863 if (Type == nullptr)
4864 return nullptr;
4865 Constraint = make<TypeRequirement>(Type);
4866 } else if (consumeIf('Q')) {
4867 // <requirement> ::= Q <constraint-expression>
4868 //
4869 // FIXME: We use <expression> instead of <constraint-expression>. Either
4870 // the requires expression is already inside a constraint expression, in
4871 // which case it makes no difference, or we're in a requires-expression
4872 // that might be partially-substituted, where the language behavior is
4873 // not yet settled and clang mangles after substitution.
4874 Node *NestedReq = getDerived().parseExpr();
4875 if (NestedReq == nullptr)
4876 return nullptr;
4877 Constraint = make<NestedRequirement>(NestedReq);
4878 }
4879 if (Constraint == nullptr)
4880 return nullptr;
4881 Names.push_back(Elem: Constraint);
4882 } while (!consumeIf('E'));
4883
4884 return make<RequiresExpr>(Params, popTrailingNodeArray(FromPosition: ReqsBegin));
4885}
4886
4887// <expression> ::= <unary operator-name> <expression>
4888// ::= <binary operator-name> <expression> <expression>
4889// ::= <ternary operator-name> <expression> <expression> <expression>
4890// ::= cl <expression>+ E # call
4891// ::= cv <type> <expression> # conversion with one argument
4892// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4893// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4894// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4895// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4896// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4897// ::= [gs] dl <expression> # delete expression
4898// ::= [gs] da <expression> # delete[] expression
4899// ::= pp_ <expression> # prefix ++
4900// ::= mm_ <expression> # prefix --
4901// ::= ti <type> # typeid (type)
4902// ::= te <expression> # typeid (expression)
4903// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4904// ::= sc <type> <expression> # static_cast<type> (expression)
4905// ::= cc <type> <expression> # const_cast<type> (expression)
4906// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4907// ::= st <type> # sizeof (a type)
4908// ::= sz <expression> # sizeof (an expression)
4909// ::= at <type> # alignof (a type)
4910// ::= az <expression> # alignof (an expression)
4911// ::= nx <expression> # noexcept (expression)
4912// ::= <template-param>
4913// ::= <function-param>
4914// ::= dt <expression> <unresolved-name> # expr.name
4915// ::= pt <expression> <unresolved-name> # expr->name
4916// ::= ds <expression> <expression> # expr.*expr
4917// ::= sZ <template-param> # size of a parameter pack
4918// ::= sZ <function-param> # size of a function parameter pack
4919// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4920// ::= sp <expression> # pack expansion
4921// ::= tw <expression> # throw expression
4922// ::= tr # throw with no operand (rethrow)
4923// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4924// # freestanding dependent name (e.g., T::x),
4925// # objectless nonstatic member reference
4926// ::= fL <binary-operator-name> <expression> <expression>
4927// ::= fR <binary-operator-name> <expression> <expression>
4928// ::= fl <binary-operator-name> <expression>
4929// ::= fr <binary-operator-name> <expression>
4930// ::= <expr-primary>
4931template <typename Derived, typename Alloc>
4932Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
4933 bool Global = consumeIf("gs");
4934
4935 const auto *Op = parseOperatorEncoding();
4936 if (Op) {
4937 auto Sym = Op->getSymbol();
4938 switch (Op->getKind()) {
4939 case OperatorInfo::Binary:
4940 // Binary operator: lhs @ rhs
4941 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
4942 case OperatorInfo::Prefix:
4943 // Prefix unary operator: @ expr
4944 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
4945 case OperatorInfo::Postfix: {
4946 // Postfix unary operator: expr @
4947 if (consumeIf('_'))
4948 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
4949 Node *Ex = getDerived().parseExpr();
4950 if (Ex == nullptr)
4951 return nullptr;
4952 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
4953 }
4954 case OperatorInfo::Array: {
4955 // Array Index: lhs [ rhs ]
4956 Node *Base = getDerived().parseExpr();
4957 if (Base == nullptr)
4958 return nullptr;
4959 Node *Index = getDerived().parseExpr();
4960 if (Index == nullptr)
4961 return nullptr;
4962 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
4963 }
4964 case OperatorInfo::Member: {
4965 // Member access lhs @ rhs
4966 Node *LHS = getDerived().parseExpr();
4967 if (LHS == nullptr)
4968 return nullptr;
4969 Node *RHS = getDerived().parseExpr();
4970 if (RHS == nullptr)
4971 return nullptr;
4972 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
4973 }
4974 case OperatorInfo::New: {
4975 // New
4976 // # new (expr-list) type [(init)]
4977 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4978 // # new[] (expr-list) type [(init)]
4979 // [gs] na <expression>* _ <type> [pi <expression>*] E
4980 size_t Exprs = Names.size();
4981 while (!consumeIf('_')) {
4982 Node *Ex = getDerived().parseExpr();
4983 if (Ex == nullptr)
4984 return nullptr;
4985 Names.push_back(Elem: Ex);
4986 }
4987 NodeArray ExprList = popTrailingNodeArray(FromPosition: Exprs);
4988 Node *Ty = getDerived().parseType();
4989 if (Ty == nullptr)
4990 return nullptr;
4991 bool HaveInits = consumeIf("pi");
4992 size_t InitsBegin = Names.size();
4993 while (!consumeIf('E')) {
4994 if (!HaveInits)
4995 return nullptr;
4996 Node *Init = getDerived().parseExpr();
4997 if (Init == nullptr)
4998 return Init;
4999 Names.push_back(Elem: Init);
5000 }
5001 NodeArray Inits = popTrailingNodeArray(FromPosition: InitsBegin);
5002 return make<NewExpr>(ExprList, Ty, Inits, Global,
5003 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
5004 }
5005 case OperatorInfo::Del: {
5006 // Delete
5007 Node *Ex = getDerived().parseExpr();
5008 if (Ex == nullptr)
5009 return nullptr;
5010 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
5011 Op->getPrecedence());
5012 }
5013 case OperatorInfo::Call: {
5014 // Function Call
5015 Node *Callee = getDerived().parseExpr();
5016 if (Callee == nullptr)
5017 return nullptr;
5018 size_t ExprsBegin = Names.size();
5019 while (!consumeIf('E')) {
5020 Node *E = getDerived().parseExpr();
5021 if (E == nullptr)
5022 return nullptr;
5023 Names.push_back(Elem: E);
5024 }
5025 return make<CallExpr>(Callee, popTrailingNodeArray(FromPosition: ExprsBegin),
5026 Op->getPrecedence());
5027 }
5028 case OperatorInfo::CCast: {
5029 // C Cast: (type)expr
5030 Node *Ty;
5031 {
5032 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
5033 Ty = getDerived().parseType();
5034 }
5035 if (Ty == nullptr)
5036 return nullptr;
5037
5038 size_t ExprsBegin = Names.size();
5039 bool IsMany = consumeIf('_');
5040 while (!consumeIf('E')) {
5041 Node *E = getDerived().parseExpr();
5042 if (E == nullptr)
5043 return E;
5044 Names.push_back(Elem: E);
5045 if (!IsMany)
5046 break;
5047 }
5048 NodeArray Exprs = popTrailingNodeArray(FromPosition: ExprsBegin);
5049 if (!IsMany && Exprs.size() != 1)
5050 return nullptr;
5051 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
5052 }
5053 case OperatorInfo::Conditional: {
5054 // Conditional operator: expr ? expr : expr
5055 Node *Cond = getDerived().parseExpr();
5056 if (Cond == nullptr)
5057 return nullptr;
5058 Node *LHS = getDerived().parseExpr();
5059 if (LHS == nullptr)
5060 return nullptr;
5061 Node *RHS = getDerived().parseExpr();
5062 if (RHS == nullptr)
5063 return nullptr;
5064 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
5065 }
5066 case OperatorInfo::NamedCast: {
5067 // Named cast operation, @<type>(expr)
5068 Node *Ty = getDerived().parseType();
5069 if (Ty == nullptr)
5070 return nullptr;
5071 Node *Ex = getDerived().parseExpr();
5072 if (Ex == nullptr)
5073 return nullptr;
5074 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
5075 }
5076 case OperatorInfo::OfIdOp: {
5077 // [sizeof/alignof/typeid] ( <type>|<expr> )
5078 Node *Arg =
5079 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
5080 if (!Arg)
5081 return nullptr;
5082 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
5083 }
5084 case OperatorInfo::NameOnly: {
5085 // Not valid as an expression operand.
5086 return nullptr;
5087 }
5088 }
5089 DEMANGLE_UNREACHABLE;
5090 }
5091
5092 if (numLeft() < 2)
5093 return nullptr;
5094
5095 if (look() == 'L')
5096 return getDerived().parseExprPrimary();
5097 if (look() == 'T')
5098 return getDerived().parseTemplateParam();
5099 if (look() == 'f') {
5100 // Disambiguate a fold expression from a <function-param>.
5101 if (look(Lookahead: 1) == 'p' || (look(Lookahead: 1) == 'L' && std::isdigit(look(Lookahead: 2))))
5102 return getDerived().parseFunctionParam();
5103 return getDerived().parseFoldExpr();
5104 }
5105 if (consumeIf("il")) {
5106 size_t InitsBegin = Names.size();
5107 while (!consumeIf('E')) {
5108 Node *E = getDerived().parseBracedExpr();
5109 if (E == nullptr)
5110 return nullptr;
5111 Names.push_back(Elem: E);
5112 }
5113 return make<InitListExpr>(nullptr, popTrailingNodeArray(FromPosition: InitsBegin));
5114 }
5115 if (consumeIf("mc"))
5116 return parsePointerToMemberConversionExpr(Prec: Node::Prec::Unary);
5117 if (consumeIf("nx")) {
5118 Node *Ex = getDerived().parseExpr();
5119 if (Ex == nullptr)
5120 return Ex;
5121 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
5122 }
5123 if (look() == 'r' && (look(Lookahead: 1) == 'q' || look(Lookahead: 1) == 'Q'))
5124 return parseRequiresExpr();
5125 if (consumeIf("so"))
5126 return parseSubobjectExpr();
5127 if (consumeIf("sp")) {
5128 Node *Child = getDerived().parseExpr();
5129 if (Child == nullptr)
5130 return nullptr;
5131 return make<ParameterPackExpansion>(Child);
5132 }
5133 if (consumeIf("sZ")) {
5134 if (look() == 'T') {
5135 Node *R = getDerived().parseTemplateParam();
5136 if (R == nullptr)
5137 return nullptr;
5138 return make<SizeofParamPackExpr>(R);
5139 }
5140 Node *FP = getDerived().parseFunctionParam();
5141 if (FP == nullptr)
5142 return nullptr;
5143 return make<EnclosingExpr>("sizeof... ", FP);
5144 }
5145 if (consumeIf("sP")) {
5146 size_t ArgsBegin = Names.size();
5147 while (!consumeIf('E')) {
5148 Node *Arg = getDerived().parseTemplateArg();
5149 if (Arg == nullptr)
5150 return nullptr;
5151 Names.push_back(Elem: Arg);
5152 }
5153 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(FromPosition: ArgsBegin));
5154 if (!Pack)
5155 return nullptr;
5156 return make<EnclosingExpr>("sizeof... ", Pack);
5157 }
5158 if (consumeIf("tl")) {
5159 Node *Ty = getDerived().parseType();
5160 if (Ty == nullptr)
5161 return nullptr;
5162 size_t InitsBegin = Names.size();
5163 while (!consumeIf('E')) {
5164 Node *E = getDerived().parseBracedExpr();
5165 if (E == nullptr)
5166 return nullptr;
5167 Names.push_back(Elem: E);
5168 }
5169 return make<InitListExpr>(Ty, popTrailingNodeArray(FromPosition: InitsBegin));
5170 }
5171 if (consumeIf("tr"))
5172 return make<NameType>("throw");
5173 if (consumeIf("tw")) {
5174 Node *Ex = getDerived().parseExpr();
5175 if (Ex == nullptr)
5176 return nullptr;
5177 return make<ThrowExpr>(Ex);
5178 }
5179 if (consumeIf('u')) {
5180 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
5181 if (!Name)
5182 return nullptr;
5183 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
5184 // standard encoding expects a <template-arg>, and would be otherwise be
5185 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
5186 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
5187 // actual conflict here.
5188 bool IsUUID = false;
5189 Node *UUID = nullptr;
5190 if (Name->getBaseName() == "__uuidof") {
5191 if (consumeIf('t')) {
5192 UUID = getDerived().parseType();
5193 IsUUID = true;
5194 } else if (consumeIf('z')) {
5195 UUID = getDerived().parseExpr();
5196 IsUUID = true;
5197 }
5198 }
5199 size_t ExprsBegin = Names.size();
5200 if (IsUUID) {
5201 if (UUID == nullptr)
5202 return nullptr;
5203 Names.push_back(Elem: UUID);
5204 } else {
5205 while (!consumeIf('E')) {
5206 Node *E = getDerived().parseTemplateArg();
5207 if (E == nullptr)
5208 return E;
5209 Names.push_back(Elem: E);
5210 }
5211 }
5212 return make<CallExpr>(Name, popTrailingNodeArray(FromPosition: ExprsBegin),
5213 Node::Prec::Postfix);
5214 }
5215
5216 // Only unresolved names remain.
5217 return getDerived().parseUnresolvedName(Global);
5218}
5219
5220// <call-offset> ::= h <nv-offset> _
5221// ::= v <v-offset> _
5222//
5223// <nv-offset> ::= <offset number>
5224// # non-virtual base override
5225//
5226// <v-offset> ::= <offset number> _ <virtual offset number>
5227// # virtual base override, with vcall offset
5228template <typename Alloc, typename Derived>
5229bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
5230 // Just scan through the call offset, we never add this information into the
5231 // output.
5232 if (consumeIf('h'))
5233 return parseNumber(AllowNegative: true).empty() || !consumeIf('_');
5234 if (consumeIf('v'))
5235 return parseNumber(AllowNegative: true).empty() || !consumeIf('_') ||
5236 parseNumber(AllowNegative: true).empty() || !consumeIf('_');
5237 return true;
5238}
5239
5240// <special-name> ::= TV <type> # virtual table
5241// ::= TT <type> # VTT structure (construction vtable index)
5242// ::= TI <type> # typeinfo structure
5243// ::= TS <type> # typeinfo name (null-terminated byte string)
5244// ::= Tc <call-offset> <call-offset> <base encoding>
5245// # base is the nominal target function of thunk
5246// # first call-offset is 'this' adjustment
5247// # second call-offset is result adjustment
5248// ::= T <call-offset> <base encoding>
5249// # base is the nominal target function of thunk
5250// # Guard variable for one-time initialization
5251// ::= GV <object name>
5252// # No <type>
5253// ::= TW <object name> # Thread-local wrapper
5254// ::= TH <object name> # Thread-local initialization
5255// ::= GR <object name> _ # First temporary
5256// ::= GR <object name> <seq-id> _ # Subsequent temporaries
5257// # construction vtable for second-in-first
5258// extension ::= TC <first type> <number> _ <second type>
5259// extension ::= GR <object name> # reference temporary for object
5260// extension ::= GI <module name> # module global initializer
5261template <typename Derived, typename Alloc>
5262Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
5263 switch (look()) {
5264 case 'T':
5265 switch (look(Lookahead: 1)) {
5266 // TA <template-arg> # template parameter object
5267 //
5268 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
5269 case 'A': {
5270 First += 2;
5271 Node *Arg = getDerived().parseTemplateArg();
5272 if (Arg == nullptr)
5273 return nullptr;
5274 return make<SpecialName>("template parameter object for ", Arg);
5275 }
5276 // TV <type> # virtual table
5277 case 'V': {
5278 First += 2;
5279 Node *Ty = getDerived().parseType();
5280 if (Ty == nullptr)
5281 return nullptr;
5282 return make<SpecialName>("vtable for ", Ty);
5283 }
5284 // TT <type> # VTT structure (construction vtable index)
5285 case 'T': {
5286 First += 2;
5287 Node *Ty = getDerived().parseType();
5288 if (Ty == nullptr)
5289 return nullptr;
5290 return make<SpecialName>("VTT for ", Ty);
5291 }
5292 // TI <type> # typeinfo structure
5293 case 'I': {
5294 First += 2;
5295 Node *Ty = getDerived().parseType();
5296 if (Ty == nullptr)
5297 return nullptr;
5298 return make<SpecialName>("typeinfo for ", Ty);
5299 }
5300 // TS <type> # typeinfo name (null-terminated byte string)
5301 case 'S': {
5302 First += 2;
5303 Node *Ty = getDerived().parseType();
5304 if (Ty == nullptr)
5305 return nullptr;
5306 return make<SpecialName>("typeinfo name for ", Ty);
5307 }
5308 // Tc <call-offset> <call-offset> <base encoding>
5309 case 'c': {
5310 First += 2;
5311 if (parseCallOffset() || parseCallOffset())
5312 return nullptr;
5313 Node *Encoding = getDerived().parseEncoding();
5314 if (Encoding == nullptr)
5315 return nullptr;
5316 return make<SpecialName>("covariant return thunk to ", Encoding);
5317 }
5318 // extension ::= TC <first type> <number> _ <second type>
5319 // # construction vtable for second-in-first
5320 case 'C': {
5321 First += 2;
5322 Node *FirstType = getDerived().parseType();
5323 if (FirstType == nullptr)
5324 return nullptr;
5325 if (parseNumber(AllowNegative: true).empty() || !consumeIf('_'))
5326 return nullptr;
5327 Node *SecondType = getDerived().parseType();
5328 if (SecondType == nullptr)
5329 return nullptr;
5330 return make<CtorVtableSpecialName>(SecondType, FirstType);
5331 }
5332 // TW <object name> # Thread-local wrapper
5333 case 'W': {
5334 First += 2;
5335 Node *Name = getDerived().parseName();
5336 if (Name == nullptr)
5337 return nullptr;
5338 return make<SpecialName>("thread-local wrapper routine for ", Name);
5339 }
5340 // TH <object name> # Thread-local initialization
5341 case 'H': {
5342 First += 2;
5343 Node *Name = getDerived().parseName();
5344 if (Name == nullptr)
5345 return nullptr;
5346 return make<SpecialName>("thread-local initialization routine for ", Name);
5347 }
5348 // T <call-offset> <base encoding>
5349 default: {
5350 ++First;
5351 bool IsVirt = look() == 'v';
5352 if (parseCallOffset())
5353 return nullptr;
5354 Node *BaseEncoding = getDerived().parseEncoding();
5355 if (BaseEncoding == nullptr)
5356 return nullptr;
5357 if (IsVirt)
5358 return make<SpecialName>("virtual thunk to ", BaseEncoding);
5359 else
5360 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
5361 }
5362 }
5363 case 'G':
5364 switch (look(Lookahead: 1)) {
5365 // GV <object name> # Guard variable for one-time initialization
5366 case 'V': {
5367 First += 2;
5368 Node *Name = getDerived().parseName();
5369 if (Name == nullptr)
5370 return nullptr;
5371 return make<SpecialName>("guard variable for ", Name);
5372 }
5373 // GR <object name> # reference temporary for object
5374 // GR <object name> _ # First temporary
5375 // GR <object name> <seq-id> _ # Subsequent temporaries
5376 case 'R': {
5377 First += 2;
5378 Node *Name = getDerived().parseName();
5379 if (Name == nullptr)
5380 return nullptr;
5381 size_t Count;
5382 bool ParsedSeqId = !parseSeqId(Out: &Count);
5383 if (!consumeIf('_') && ParsedSeqId)
5384 return nullptr;
5385 return make<SpecialName>("reference temporary for ", Name);
5386 }
5387 // GI <module-name> v
5388 case 'I': {
5389 First += 2;
5390 ModuleName *Module = nullptr;
5391 if (getDerived().parseModuleNameOpt(Module))
5392 return nullptr;
5393 if (Module == nullptr)
5394 return nullptr;
5395 return make<SpecialName>("initializer for module ", Module);
5396 }
5397 }
5398 }
5399 return nullptr;
5400}
5401
5402// <encoding> ::= <function name> <bare-function-type>
5403// [`Q` <requires-clause expr>]
5404// ::= <data name>
5405// ::= <special-name>
5406template <typename Derived, typename Alloc>
5407Node *AbstractManglingParser<Derived, Alloc>::parseEncoding(bool ParseParams) {
5408 // The template parameters of an encoding are unrelated to those of the
5409 // enclosing context.
5410 SaveTemplateParams SaveTemplateParamsScope(this);
5411
5412 if (look() == 'G' || look() == 'T')
5413 return getDerived().parseSpecialName();
5414
5415 auto IsEndOfEncoding = [&] {
5416 // The set of chars that can potentially follow an <encoding> (none of which
5417 // can start a <type>). Enumerating these allows us to avoid speculative
5418 // parsing.
5419 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5420 };
5421
5422 NameState NameInfo(this);
5423 Node *Name = getDerived().parseName(&NameInfo);
5424 if (Name == nullptr)
5425 return nullptr;
5426
5427 if (resolveForwardTemplateRefs(State&: NameInfo))
5428 return nullptr;
5429
5430 if (IsEndOfEncoding())
5431 return Name;
5432
5433 // ParseParams may be false at the top level only, when called from parse().
5434 // For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be
5435 // false when demangling 3fooILZ3BarEET_f but is always true when demangling
5436 // 3Bar.
5437 if (!ParseParams) {
5438 while (consume())
5439 ;
5440 return Name;
5441 }
5442
5443 Node *Attrs = nullptr;
5444 if (consumeIf("Ua9enable_ifI")) {
5445 size_t BeforeArgs = Names.size();
5446 while (!consumeIf('E')) {
5447 Node *Arg = getDerived().parseTemplateArg();
5448 if (Arg == nullptr)
5449 return nullptr;
5450 Names.push_back(Elem: Arg);
5451 }
5452 Attrs = make<EnableIfAttr>(popTrailingNodeArray(FromPosition: BeforeArgs));
5453 if (!Attrs)
5454 return nullptr;
5455 }
5456
5457 Node *ReturnType = nullptr;
5458 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
5459 ReturnType = getDerived().parseType();
5460 if (ReturnType == nullptr)
5461 return nullptr;
5462 }
5463
5464 NodeArray Params;
5465 if (!consumeIf('v')) {
5466 size_t ParamsBegin = Names.size();
5467 do {
5468 Node *Ty = getDerived().parseType();
5469 if (Ty == nullptr)
5470 return nullptr;
5471
5472 const bool IsFirstParam = ParamsBegin == Names.size();
5473 if (NameInfo.HasExplicitObjectParameter && IsFirstParam)
5474 Ty = make<ExplicitObjectParameter>(Ty);
5475
5476 if (Ty == nullptr)
5477 return nullptr;
5478
5479 Names.push_back(Elem: Ty);
5480 } while (!IsEndOfEncoding() && look() != 'Q');
5481 Params = popTrailingNodeArray(FromPosition: ParamsBegin);
5482 }
5483
5484 Node *Requires = nullptr;
5485 if (consumeIf('Q')) {
5486 Requires = getDerived().parseConstraintExpr();
5487 if (!Requires)
5488 return nullptr;
5489 }
5490
5491 return make<FunctionEncoding>(ReturnType, Name, Params, Attrs, Requires,
5492 NameInfo.CVQualifiers,
5493 NameInfo.ReferenceQualifier);
5494}
5495
5496template <class Float>
5497struct FloatData;
5498
5499template <>
5500struct FloatData<float>
5501{
5502 static const size_t mangled_size = 8;
5503 static const size_t max_demangled_size = 24;
5504 static constexpr const char* spec = "%af";
5505};
5506
5507template <>
5508struct FloatData<double>
5509{
5510 static const size_t mangled_size = 16;
5511 static const size_t max_demangled_size = 32;
5512 static constexpr const char* spec = "%a";
5513};
5514
5515template <>
5516struct FloatData<long double>
5517{
5518#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5519 defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \
5520 defined(__ve__)
5521 static const size_t mangled_size = 32;
5522#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5523 static const size_t mangled_size = 16;
5524#else
5525 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5526#endif
5527 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5528 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5529 // Negatives are one character longer than positives.
5530 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5531 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5532 static const size_t max_demangled_size = 42;
5533 static constexpr const char *spec = "%LaL";
5534};
5535
5536template <typename Alloc, typename Derived>
5537template <class Float>
5538Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
5539 const size_t N = FloatData<Float>::mangled_size;
5540 if (numLeft() <= N)
5541 return nullptr;
5542 std::string_view Data(First, N);
5543 for (char C : Data)
5544 if (!std::isxdigit(C))
5545 return nullptr;
5546 First += N;
5547 if (!consumeIf('E'))
5548 return nullptr;
5549 return make<FloatLiteralImpl<Float>>(Data);
5550}
5551
5552// <seq-id> ::= <0-9A-Z>+
5553template <typename Alloc, typename Derived>
5554bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
5555 if (!(look() >= '0' && look() <= '9') &&
5556 !(look() >= 'A' && look() <= 'Z'))
5557 return true;
5558
5559 size_t Id = 0;
5560 while (true) {
5561 if (look() >= '0' && look() <= '9') {
5562 Id *= 36;
5563 Id += static_cast<size_t>(look() - '0');
5564 } else if (look() >= 'A' && look() <= 'Z') {
5565 Id *= 36;
5566 Id += static_cast<size_t>(look() - 'A') + 10;
5567 } else {
5568 *Out = Id;
5569 return false;
5570 }
5571 ++First;
5572 }
5573}
5574
5575// <substitution> ::= S <seq-id> _
5576// ::= S_
5577// <substitution> ::= Sa # ::std::allocator
5578// <substitution> ::= Sb # ::std::basic_string
5579// <substitution> ::= Ss # ::std::basic_string < char,
5580// ::std::char_traits<char>,
5581// ::std::allocator<char> >
5582// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5583// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5584// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
5585// The St case is handled specially in parseNestedName.
5586template <typename Derived, typename Alloc>
5587Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
5588 if (!consumeIf('S'))
5589 return nullptr;
5590
5591 if (look() >= 'a' && look() <= 'z') {
5592 SpecialSubKind Kind;
5593 switch (look()) {
5594 case 'a':
5595 Kind = SpecialSubKind::allocator;
5596 break;
5597 case 'b':
5598 Kind = SpecialSubKind::basic_string;
5599 break;
5600 case 'd':
5601 Kind = SpecialSubKind::iostream;
5602 break;
5603 case 'i':
5604 Kind = SpecialSubKind::istream;
5605 break;
5606 case 'o':
5607 Kind = SpecialSubKind::ostream;
5608 break;
5609 case 's':
5610 Kind = SpecialSubKind::string;
5611 break;
5612 default:
5613 return nullptr;
5614 }
5615 ++First;
5616 auto *SpecialSub = make<SpecialSubstitution>(Kind);
5617 if (!SpecialSub)
5618 return nullptr;
5619
5620 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5621 // has ABI tags, the tags are appended to the substitution; the result is a
5622 // substitutable component.
5623 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
5624 if (WithTags != SpecialSub) {
5625 Subs.push_back(Elem: WithTags);
5626 SpecialSub = WithTags;
5627 }
5628 return SpecialSub;
5629 }
5630
5631 // ::= S_
5632 if (consumeIf('_')) {
5633 if (Subs.empty())
5634 return nullptr;
5635 return Subs[0];
5636 }
5637
5638 // ::= S <seq-id> _
5639 size_t Index = 0;
5640 if (parseSeqId(Out: &Index))
5641 return nullptr;
5642 ++Index;
5643 if (!consumeIf('_') || Index >= Subs.size())
5644 return nullptr;
5645 return Subs[Index];
5646}
5647
5648// <template-param> ::= T_ # first template parameter
5649// ::= T <parameter-2 non-negative number> _
5650// ::= TL <level-1> __
5651// ::= TL <level-1> _ <parameter-2 non-negative number> _
5652template <typename Derived, typename Alloc>
5653Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
5654 const char *Begin = First;
5655 if (!consumeIf('T'))
5656 return nullptr;
5657
5658 size_t Level = 0;
5659 if (consumeIf('L')) {
5660 if (parsePositiveInteger(Out: &Level))
5661 return nullptr;
5662 ++Level;
5663 if (!consumeIf('_'))
5664 return nullptr;
5665 }
5666
5667 size_t Index = 0;
5668 if (!consumeIf('_')) {
5669 if (parsePositiveInteger(Out: &Index))
5670 return nullptr;
5671 ++Index;
5672 if (!consumeIf('_'))
5673 return nullptr;
5674 }
5675
5676 // We don't track enclosing template parameter levels well enough to reliably
5677 // substitute them all within a <constraint-expression>, so print the
5678 // parameter numbering instead for now.
5679 // TODO: Track all enclosing template parameters and substitute them here.
5680 if (InConstraintExpr) {
5681 return make<NameType>(std::string_view(Begin, First - 1 - Begin));
5682 }
5683
5684 // If we're in a context where this <template-param> refers to a
5685 // <template-arg> further ahead in the mangled name (currently just conversion
5686 // operator types), then we should only look it up in the right context.
5687 // This can only happen at the outermost level.
5688 if (PermitForwardTemplateReferences && Level == 0) {
5689 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5690 if (!ForwardRef)
5691 return nullptr;
5692 DEMANGLE_ASSERT(ForwardRef->getKind() == Node::KForwardTemplateReference,
5693 "");
5694 ForwardTemplateRefs.push_back(
5695 Elem: static_cast<ForwardTemplateReference *>(ForwardRef));
5696 return ForwardRef;
5697 }
5698
5699 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5700 Index >= TemplateParams[Level]->size()) {
5701 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5702 // list are mangled as the corresponding artificial template type parameter.
5703 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5704 // This will be popped by the ScopedTemplateParamList in
5705 // parseUnnamedTypeName.
5706 if (Level == TemplateParams.size())
5707 TemplateParams.push_back(Elem: nullptr);
5708 return make<NameType>("auto");
5709 }
5710
5711 return nullptr;
5712 }
5713
5714 return (*TemplateParams[Level])[Index];
5715}
5716
5717// <template-param-decl> ::= Ty # type parameter
5718// ::= Tn <type> # non-type parameter
5719// ::= Tt <template-param-decl>* E # template parameter
5720// ::= Tp <template-param-decl> # parameter pack
5721template <typename Derived, typename Alloc>
5722Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl(
5723 TemplateParamList *Params) {
5724 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5725 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5726 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5727 if (N && Params)
5728 Params->push_back(Elem: N);
5729 return N;
5730 };
5731
5732 if (consumeIf("Ty")) {
5733 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5734 if (!Name)
5735 return nullptr;
5736 return make<TypeTemplateParamDecl>(Name);
5737 }
5738
5739 if (consumeIf("Tk")) {
5740 Node *Constraint = getDerived().parseName();
5741 if (!Constraint)
5742 return nullptr;
5743 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5744 if (!Name)
5745 return nullptr;
5746 return make<ConstrainedTypeTemplateParamDecl>(Constraint, Name);
5747 }
5748
5749 if (consumeIf("Tn")) {
5750 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5751 if (!Name)
5752 return nullptr;
5753 Node *Type = parseType();
5754 if (!Type)
5755 return nullptr;
5756 return make<NonTypeTemplateParamDecl>(Name, Type);
5757 }
5758
5759 if (consumeIf("Tt")) {
5760 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5761 if (!Name)
5762 return nullptr;
5763 size_t ParamsBegin = Names.size();
5764 ScopedTemplateParamList TemplateTemplateParamParams(this);
5765 Node *Requires = nullptr;
5766 while (!consumeIf('E')) {
5767 Node *P = parseTemplateParamDecl(Params: TemplateTemplateParamParams.params());
5768 if (!P)
5769 return nullptr;
5770 Names.push_back(Elem: P);
5771 if (consumeIf('Q')) {
5772 Requires = getDerived().parseConstraintExpr();
5773 if (Requires == nullptr || !consumeIf('E'))
5774 return nullptr;
5775 break;
5776 }
5777 }
5778 NodeArray InnerParams = popTrailingNodeArray(FromPosition: ParamsBegin);
5779 return make<TemplateTemplateParamDecl>(Name, InnerParams, Requires);
5780 }
5781
5782 if (consumeIf("Tp")) {
5783 Node *P = parseTemplateParamDecl(Params);
5784 if (!P)
5785 return nullptr;
5786 return make<TemplateParamPackDecl>(P);
5787 }
5788
5789 return nullptr;
5790}
5791
5792// <template-arg> ::= <type> # type or template
5793// ::= X <expression> E # expression
5794// ::= <expr-primary> # simple expressions
5795// ::= J <template-arg>* E # argument pack
5796// ::= LZ <encoding> E # extension
5797// ::= <template-param-decl> <template-arg>
5798template <typename Derived, typename Alloc>
5799Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
5800 switch (look()) {
5801 case 'X': {
5802 ++First;
5803 Node *Arg = getDerived().parseExpr();
5804 if (Arg == nullptr || !consumeIf('E'))
5805 return nullptr;
5806 return Arg;
5807 }
5808 case 'J': {
5809 ++First;
5810 size_t ArgsBegin = Names.size();
5811 while (!consumeIf('E')) {
5812 Node *Arg = getDerived().parseTemplateArg();
5813 if (Arg == nullptr)
5814 return nullptr;
5815 Names.push_back(Elem: Arg);
5816 }
5817 NodeArray Args = popTrailingNodeArray(FromPosition: ArgsBegin);
5818 return make<TemplateArgumentPack>(Args);
5819 }
5820 case 'L': {
5821 // ::= LZ <encoding> E # extension
5822 if (look(Lookahead: 1) == 'Z') {
5823 First += 2;
5824 Node *Arg = getDerived().parseEncoding();
5825 if (Arg == nullptr || !consumeIf('E'))
5826 return nullptr;
5827 return Arg;
5828 }
5829 // ::= <expr-primary> # simple expressions
5830 return getDerived().parseExprPrimary();
5831 }
5832 case 'T': {
5833 // Either <template-param> or a <template-param-decl> <template-arg>.
5834 if (!getDerived().isTemplateParamDecl())
5835 return getDerived().parseType();
5836 Node *Param = getDerived().parseTemplateParamDecl(nullptr);
5837 if (!Param)
5838 return nullptr;
5839 Node *Arg = getDerived().parseTemplateArg();
5840 if (!Arg)
5841 return nullptr;
5842 return make<TemplateParamQualifiedArg>(Param, Arg);
5843 }
5844 default:
5845 return getDerived().parseType();
5846 }
5847}
5848
5849// <template-args> ::= I <template-arg>* E
5850// extension, the abi says <template-arg>+
5851template <typename Derived, typename Alloc>
5852Node *
5853AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
5854 if (!consumeIf('I'))
5855 return nullptr;
5856
5857 // <template-params> refer to the innermost <template-args>. Clear out any
5858 // outer args that we may have inserted into TemplateParams.
5859 if (TagTemplates) {
5860 TemplateParams.clear();
5861 TemplateParams.push_back(Elem: &OuterTemplateParams);
5862 OuterTemplateParams.clear();
5863 }
5864
5865 size_t ArgsBegin = Names.size();
5866 Node *Requires = nullptr;
5867 while (!consumeIf('E')) {
5868 if (TagTemplates) {
5869 Node *Arg = getDerived().parseTemplateArg();
5870 if (Arg == nullptr)
5871 return nullptr;
5872 Names.push_back(Elem: Arg);
5873 Node *TableEntry = Arg;
5874 if (Arg->getKind() == Node::KTemplateParamQualifiedArg) {
5875 TableEntry =
5876 static_cast<TemplateParamQualifiedArg *>(TableEntry)->getArg();
5877 }
5878 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5879 TableEntry = make<ParameterPack>(
5880 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
5881 if (!TableEntry)
5882 return nullptr;
5883 }
5884 OuterTemplateParams.push_back(Elem: TableEntry);
5885 } else {
5886 Node *Arg = getDerived().parseTemplateArg();
5887 if (Arg == nullptr)
5888 return nullptr;
5889 Names.push_back(Elem: Arg);
5890 }
5891 if (consumeIf('Q')) {
5892 Requires = getDerived().parseConstraintExpr();
5893 if (!Requires || !consumeIf('E'))
5894 return nullptr;
5895 break;
5896 }
5897 }
5898 return make<TemplateArgs>(popTrailingNodeArray(FromPosition: ArgsBegin), Requires);
5899}
5900
5901// <mangled-name> ::= _Z <encoding>
5902// ::= <type>
5903// extension ::= ___Z <encoding> _block_invoke
5904// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5905// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
5906template <typename Derived, typename Alloc>
5907Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {
5908 if (consumeIf("_Z") || consumeIf("__Z")) {
5909 Node *Encoding = getDerived().parseEncoding(ParseParams);
5910 if (Encoding == nullptr)
5911 return nullptr;
5912 if (look() == '.') {
5913 Encoding =
5914 make<DotSuffix>(Encoding, std::string_view(First, Last - First));
5915 First = Last;
5916 }
5917 if (numLeft() != 0)
5918 return nullptr;
5919 return Encoding;
5920 }
5921
5922 if (consumeIf("___Z") || consumeIf("____Z")) {
5923 Node *Encoding = getDerived().parseEncoding(ParseParams);
5924 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5925 return nullptr;
5926 bool RequireNumber = consumeIf('_');
5927 if (parseNumber().empty() && RequireNumber)
5928 return nullptr;
5929 if (look() == '.')
5930 First = Last;
5931 if (numLeft() != 0)
5932 return nullptr;
5933 return make<SpecialName>("invocation function for block in ", Encoding);
5934 }
5935
5936 Node *Ty = getDerived().parseType();
5937 if (numLeft() != 0)
5938 return nullptr;
5939 return Ty;
5940}
5941
5942template <typename Alloc>
5943struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5944 using AbstractManglingParser<ManglingParser<Alloc>,
5945 Alloc>::AbstractManglingParser;
5946};
5947
5948DEMANGLE_NAMESPACE_END
5949
5950#ifdef _LIBCXXABI_COMPILER_CLANG
5951#pragma clang diagnostic pop
5952#endif
5953
5954#endif // DEMANGLE_ITANIUMDEMANGLE_H
5955

source code of libcxxabi/src/demangle/ItaniumDemangle.h