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