LLVM 19.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#ifdef _LIBCXXABI_COMPILER_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
202 // FIXME: Make these protected.
203public:
204 /// Tracks if this node has a component on its right side, in which case we
205 /// need to call printRight.
207
208 /// Track if this node is a (possibly qualified) array type. This can affect
209 /// how we format the output string.
211
212 /// Track if this node is a (possibly qualified) function type. This can
213 /// affect how we format the output string.
215
216public:
217 Node(Kind K_, Prec Precedence_ = Prec::Primary,
218 Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,
219 Cache FunctionCache_ = Cache::No)
220 : K(K_), Precedence(Precedence_), RHSComponentCache(RHSComponentCache_),
221 ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {}
222 Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_ = Cache::No,
223 Cache FunctionCache_ = Cache::No)
224 : Node(K_, Prec::Primary, RHSComponentCache_, ArrayCache_,
225 FunctionCache_) {}
226
227 /// Visit the most-derived object corresponding to this object.
228 template<typename Fn> void visit(Fn F) const;
229
230 // The following function is provided by all derived classes:
231 //
232 // Call F with arguments that, when passed to the constructor of this node,
233 // would construct an equivalent node.
234 //template<typename Fn> void match(Fn F) const;
235
239 return hasRHSComponentSlow(OB);
240 }
241
242 bool hasArray(OutputBuffer &OB) const {
244 return ArrayCache == Cache::Yes;
245 return hasArraySlow(OB);
246 }
247
248 bool hasFunction(OutputBuffer &OB) const {
250 return FunctionCache == Cache::Yes;
251 return hasFunctionSlow(OB);
252 }
253
254 Kind getKind() const { return K; }
255
256 Prec getPrecedence() const { return Precedence; }
257
258 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
259 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
260 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
261
262 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
263 // get at a node that actually represents some concrete syntax.
264 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }
265
266 // Print this node as an expression operand, surrounding it in parentheses if
267 // its precedence is [Strictly] weaker than P.
269 bool StrictlyWorse = false) const {
270 bool Paren =
271 unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse);
272 if (Paren)
273 OB.printOpen();
274 print(OB);
275 if (Paren)
276 OB.printClose();
277 }
278
279 void print(OutputBuffer &OB) const {
280 printLeft(OB);
282 printRight(OB);
283 }
284
285 // Print the "left" side of this Node into OutputBuffer.
286 virtual void printLeft(OutputBuffer &) const = 0;
287
288 // Print the "right". This distinction is necessary to represent C++ types
289 // that appear on the RHS of their subtype, such as arrays or functions.
290 // Since most types don't have such a component, provide a default
291 // implementation.
292 virtual void printRight(OutputBuffer &) const {}
293
294 virtual std::string_view getBaseName() const { return {}; }
295
296 // Silence compiler warnings, this dtor will never be called.
297 virtual ~Node() = default;
298
299#ifndef NDEBUG
301#endif
302};
303
305 Node **Elements;
306 size_t NumElements;
307
308public:
309 NodeArray() : Elements(nullptr), NumElements(0) {}
310 NodeArray(Node **Elements_, size_t NumElements_)
311 : Elements(Elements_), NumElements(NumElements_) {}
312
313 bool empty() const { return NumElements == 0; }
314 size_t size() const { return NumElements; }
315
316 Node **begin() const { return Elements; }
317 Node **end() const { return Elements + NumElements; }
318
319 Node *operator[](size_t Idx) const { return Elements[Idx]; }
320
321 void printWithComma(OutputBuffer &OB) const {
322 bool FirstElement = true;
323 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
324 size_t BeforeComma = OB.getCurrentPosition();
325 if (!FirstElement)
326 OB += ", ";
327 size_t AfterComma = OB.getCurrentPosition();
328 Elements[Idx]->printAsOperand(OB, Node::Prec::Comma);
329
330 // Elements[Idx] is an empty parameter pack expansion, we should erase the
331 // comma we just printed.
332 if (AfterComma == OB.getCurrentPosition()) {
333 OB.setCurrentPosition(BeforeComma);
334 continue;
335 }
336
337 FirstElement = false;
338 }
339 }
340};
341
344 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
345
346 template<typename Fn> void match(Fn F) const { F(Array); }
347
348 void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
349};
350
351class DotSuffix final : public Node {
352 const Node *Prefix;
353 const std::string_view Suffix;
354
355public:
356 DotSuffix(const Node *Prefix_, std::string_view Suffix_)
357 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
358
359 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
360
361 void printLeft(OutputBuffer &OB) const override {
362 Prefix->print(OB);
363 OB += " (";
364 OB += Suffix;
365 OB += ")";
366 }
367};
368
369class VendorExtQualType final : public Node {
370 const Node *Ty;
371 std::string_view Ext;
372 const Node *TA;
373
374public:
375 VendorExtQualType(const Node *Ty_, std::string_view Ext_, const Node *TA_)
376 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
377
378 const Node *getTy() const { return Ty; }
379 std::string_view getExt() const { return Ext; }
380 const Node *getTA() const { return TA; }
381
382 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
383
384 void printLeft(OutputBuffer &OB) const override {
385 Ty->print(OB);
386 OB += " ";
387 OB += Ext;
388 if (TA != nullptr)
389 TA->print(OB);
390 }
391};
392
393enum FunctionRefQual : unsigned char {
397};
398
404};
405
407 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
408}
409
410class QualType final : public Node {
411protected:
413 const Node *Child;
414
415 void printQuals(OutputBuffer &OB) const {
416 if (Quals & QualConst)
417 OB += " const";
418 if (Quals & QualVolatile)
419 OB += " volatile";
420 if (Quals & QualRestrict)
421 OB += " restrict";
422 }
423
424public:
425 QualType(const Node *Child_, Qualifiers Quals_)
426 : Node(KQualType, Child_->RHSComponentCache,
427 Child_->ArrayCache, Child_->FunctionCache),
428 Quals(Quals_), Child(Child_) {}
429
430 Qualifiers getQuals() const { return Quals; }
431 const Node *getChild() const { return Child; }
432
433 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
434
435 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
436 return Child->hasRHSComponent(OB);
437 }
438 bool hasArraySlow(OutputBuffer &OB) const override {
439 return Child->hasArray(OB);
440 }
441 bool hasFunctionSlow(OutputBuffer &OB) const override {
442 return Child->hasFunction(OB);
443 }
444
445 void printLeft(OutputBuffer &OB) const override {
446 Child->printLeft(OB);
447 printQuals(OB);
448 }
449
450 void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
451};
452
453class ConversionOperatorType final : public Node {
454 const Node *Ty;
455
456public:
458 : Node(KConversionOperatorType), Ty(Ty_) {}
459
460 template<typename Fn> void match(Fn F) const { F(Ty); }
461
462 void printLeft(OutputBuffer &OB) const override {
463 OB += "operator ";
464 Ty->print(OB);
465 }
466};
467
468class PostfixQualifiedType final : public Node {
469 const Node *Ty;
470 const std::string_view Postfix;
471
472public:
473 PostfixQualifiedType(const Node *Ty_, std::string_view Postfix_)
474 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
475
476 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
477
478 void printLeft(OutputBuffer &OB) const override {
479 Ty->printLeft(OB);
480 OB += Postfix;
481 }
482};
483
484class NameType final : public Node {
485 const std::string_view Name;
486
487public:
488 NameType(std::string_view Name_) : Node(KNameType), Name(Name_) {}
489
490 template<typename Fn> void match(Fn F) const { F(Name); }
491
492 std::string_view getName() const { return Name; }
493 std::string_view getBaseName() const override { return Name; }
494
495 void printLeft(OutputBuffer &OB) const override { OB += Name; }
496};
497
498class BitIntType final : public Node {
499 const Node *Size;
500 bool Signed;
501
502public:
503 BitIntType(const Node *Size_, bool Signed_)
504 : Node(KBitIntType), Size(Size_), Signed(Signed_) {}
505
506 template <typename Fn> void match(Fn F) const { F(Size, Signed); }
507
508 void printLeft(OutputBuffer &OB) const override {
509 if (!Signed)
510 OB += "unsigned ";
511 OB += "_BitInt";
512 OB.printOpen();
513 Size->printAsOperand(OB);
514 OB.printClose();
515 }
516};
517
519 std::string_view Kind;
520 Node *Child;
521public:
522 ElaboratedTypeSpefType(std::string_view Kind_, Node *Child_)
523 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
524
525 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
526
527 void printLeft(OutputBuffer &OB) const override {
528 OB += Kind;
529 OB += ' ';
530 Child->print(OB);
531 }
532};
533
534class TransformedType : public Node {
535 std::string_view Transform;
536 Node *BaseType;
537public:
538 TransformedType(std::string_view Transform_, Node *BaseType_)
539 : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}
540
541 template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }
542
543 void printLeft(OutputBuffer &OB) const override {
544 OB += Transform;
545 OB += '(';
546 BaseType->print(OB);
547 OB += ')';
548 }
549};
550
551struct AbiTagAttr : Node {
553 std::string_view Tag;
554
555 AbiTagAttr(Node *Base_, std::string_view Tag_)
556 : Node(KAbiTagAttr, Base_->RHSComponentCache, Base_->ArrayCache,
557 Base_->FunctionCache),
558 Base(Base_), Tag(Tag_) {}
559
560 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
561
562 std::string_view getBaseName() const override { return Base->getBaseName(); }
563
564 void printLeft(OutputBuffer &OB) const override {
565 Base->printLeft(OB);
566 OB += "[abi:";
567 OB += Tag;
568 OB += "]";
569 }
570};
571
572class EnableIfAttr : public Node {
573 NodeArray Conditions;
574public:
576 : Node(KEnableIfAttr), Conditions(Conditions_) {}
577
578 template<typename Fn> void match(Fn F) const { F(Conditions); }
579
580 void printLeft(OutputBuffer &OB) const override {
581 OB += " [enable_if:";
582 Conditions.printWithComma(OB);
583 OB += ']';
584 }
585};
586
587class ObjCProtoName : public Node {
588 const Node *Ty;
589 std::string_view Protocol;
590
591 friend class PointerType;
592
593public:
594 ObjCProtoName(const Node *Ty_, std::string_view Protocol_)
595 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
596
597 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
598
599 bool isObjCObject() const {
600 return Ty->getKind() == KNameType &&
601 static_cast<const NameType *>(Ty)->getName() == "objc_object";
602 }
603
604 void printLeft(OutputBuffer &OB) const override {
605 Ty->print(OB);
606 OB += "<";
607 OB += Protocol;
608 OB += ">";
609 }
610};
611
612class PointerType final : public Node {
613 const Node *Pointee;
614
615public:
616 PointerType(const Node *Pointee_)
617 : Node(KPointerType, Pointee_->RHSComponentCache),
618 Pointee(Pointee_) {}
619
620 const Node *getPointee() const { return Pointee; }
621
622 template<typename Fn> void match(Fn F) const { F(Pointee); }
623
624 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
625 return Pointee->hasRHSComponent(OB);
626 }
627
628 void printLeft(OutputBuffer &OB) const override {
629 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
630 if (Pointee->getKind() != KObjCProtoName ||
631 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
632 Pointee->printLeft(OB);
633 if (Pointee->hasArray(OB))
634 OB += " ";
635 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
636 OB += "(";
637 OB += "*";
638 } else {
639 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
640 OB += "id<";
641 OB += objcProto->Protocol;
642 OB += ">";
643 }
644 }
645
646 void printRight(OutputBuffer &OB) const override {
647 if (Pointee->getKind() != KObjCProtoName ||
648 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
649 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
650 OB += ")";
651 Pointee->printRight(OB);
652 }
653 }
654};
655
656enum class ReferenceKind {
657 LValue,
658 RValue,
659};
660
661// Represents either a LValue or an RValue reference type.
662class ReferenceType : public Node {
663 const Node *Pointee;
664 ReferenceKind RK;
665
666 mutable bool Printing = false;
667
668 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
669 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
670 // other combination collapses to a lvalue ref.
671 //
672 // A combination of a TemplateForwardReference and a back-ref Substitution
673 // from an ill-formed string may have created a cycle; use cycle detection to
674 // avoid looping forever.
675 std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {
676 auto SoFar = std::make_pair(RK, Pointee);
677 // Track the chain of nodes for the Floyd's 'tortoise and hare'
678 // cycle-detection algorithm, since getSyntaxNode(S) is impure
680 for (;;) {
681 const Node *SN = SoFar.second->getSyntaxNode(OB);
682 if (SN->getKind() != KReferenceType)
683 break;
684 auto *RT = static_cast<const ReferenceType *>(SN);
685 SoFar.second = RT->Pointee;
686 SoFar.first = std::min(SoFar.first, RT->RK);
687
688 // The middle of Prev is the 'slow' pointer moving at half speed
689 Prev.push_back(SoFar.second);
690 if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {
691 // Cycle detected
692 SoFar.second = nullptr;
693 break;
694 }
695 }
696 return SoFar;
697 }
698
699public:
700 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
701 : Node(KReferenceType, Pointee_->RHSComponentCache),
702 Pointee(Pointee_), RK(RK_) {}
703
704 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
705
706 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
707 return Pointee->hasRHSComponent(OB);
708 }
709
710 void printLeft(OutputBuffer &OB) const override {
711 if (Printing)
712 return;
713 ScopedOverride<bool> SavePrinting(Printing, true);
714 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
715 if (!Collapsed.second)
716 return;
717 Collapsed.second->printLeft(OB);
718 if (Collapsed.second->hasArray(OB))
719 OB += " ";
720 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
721 OB += "(";
722
723 OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
724 }
725 void printRight(OutputBuffer &OB) const override {
726 if (Printing)
727 return;
728 ScopedOverride<bool> SavePrinting(Printing, true);
729 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
730 if (!Collapsed.second)
731 return;
732 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
733 OB += ")";
734 Collapsed.second->printRight(OB);
735 }
736};
737
738class PointerToMemberType final : public Node {
739 const Node *ClassType;
740 const Node *MemberType;
741
742public:
743 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
744 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
745 ClassType(ClassType_), MemberType(MemberType_) {}
746
747 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
748
749 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
750 return MemberType->hasRHSComponent(OB);
751 }
752
753 void printLeft(OutputBuffer &OB) const override {
754 MemberType->printLeft(OB);
755 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
756 OB += "(";
757 else
758 OB += " ";
759 ClassType->print(OB);
760 OB += "::*";
761 }
762
763 void printRight(OutputBuffer &OB) const override {
764 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
765 OB += ")";
766 MemberType->printRight(OB);
767 }
768};
769
770class ArrayType final : public Node {
771 const Node *Base;
772 Node *Dimension;
773
774public:
775 ArrayType(const Node *Base_, Node *Dimension_)
776 : Node(KArrayType,
777 /*RHSComponentCache=*/Cache::Yes,
778 /*ArrayCache=*/Cache::Yes),
779 Base(Base_), Dimension(Dimension_) {}
780
781 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
782
783 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
784 bool hasArraySlow(OutputBuffer &) const override { return true; }
785
786 void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
787
788 void printRight(OutputBuffer &OB) const override {
789 if (OB.back() != ']')
790 OB += " ";
791 OB += "[";
792 if (Dimension)
793 Dimension->print(OB);
794 OB += "]";
795 Base->printRight(OB);
796 }
797};
798
799class FunctionType final : public Node {
800 const Node *Ret;
801 NodeArray Params;
802 Qualifiers CVQuals;
803 FunctionRefQual RefQual;
804 const Node *ExceptionSpec;
805
806public:
807 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
808 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
809 : Node(KFunctionType,
810 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
811 /*FunctionCache=*/Cache::Yes),
812 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
813 ExceptionSpec(ExceptionSpec_) {}
814
815 template<typename Fn> void match(Fn F) const {
816 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
817 }
818
819 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
820 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
821
822 // Handle C++'s ... quirky decl grammar by using the left & right
823 // distinction. Consider:
824 // int (*f(float))(char) {}
825 // f is a function that takes a float and returns a pointer to a function
826 // that takes a char and returns an int. If we're trying to print f, start
827 // by printing out the return types's left, then print our parameters, then
828 // finally print right of the return type.
829 void printLeft(OutputBuffer &OB) const override {
830 Ret->printLeft(OB);
831 OB += " ";
832 }
833
834 void printRight(OutputBuffer &OB) const override {
835 OB.printOpen();
836 Params.printWithComma(OB);
837 OB.printClose();
838 Ret->printRight(OB);
839
840 if (CVQuals & QualConst)
841 OB += " const";
842 if (CVQuals & QualVolatile)
843 OB += " volatile";
844 if (CVQuals & QualRestrict)
845 OB += " restrict";
846
847 if (RefQual == FrefQualLValue)
848 OB += " &";
849 else if (RefQual == FrefQualRValue)
850 OB += " &&";
851
852 if (ExceptionSpec != nullptr) {
853 OB += ' ';
854 ExceptionSpec->print(OB);
855 }
856 }
857};
858
859class NoexceptSpec : public Node {
860 const Node *E;
861public:
862 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
863
864 template<typename Fn> void match(Fn F) const { F(E); }
865
866 void printLeft(OutputBuffer &OB) const override {
867 OB += "noexcept";
868 OB.printOpen();
869 E->printAsOperand(OB);
870 OB.printClose();
871 }
872};
873
875 NodeArray Types;
876public:
878 : Node(KDynamicExceptionSpec), Types(Types_) {}
879
880 template<typename Fn> void match(Fn F) const { F(Types); }
881
882 void printLeft(OutputBuffer &OB) const override {
883 OB += "throw";
884 OB.printOpen();
885 Types.printWithComma(OB);
886 OB.printClose();
887 }
888};
889
890/// Represents the explicitly named object parameter.
891/// E.g.,
892/// \code{.cpp}
893/// struct Foo {
894/// void bar(this Foo && self);
895/// };
896/// \endcode
897class ExplicitObjectParameter final : public Node {
898 Node *Base;
899
900public:
902 : Node(KExplicitObjectParameter), Base(Base_) {
904 Base != nullptr,
905 "Creating an ExplicitObjectParameter without a valid Base Node.");
906 }
907
908 template <typename Fn> void match(Fn F) const { F(Base); }
909
910 void printLeft(OutputBuffer &OB) const override {
911 OB += "this ";
912 Base->print(OB);
913 }
914};
915
916class FunctionEncoding final : public Node {
917 const Node *Ret;
918 const Node *Name;
919 NodeArray Params;
920 const Node *Attrs;
921 const Node *Requires;
922 Qualifiers CVQuals;
923 FunctionRefQual RefQual;
924
925public:
926 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
927 const Node *Attrs_, const Node *Requires_,
928 Qualifiers CVQuals_, FunctionRefQual RefQual_)
929 : Node(KFunctionEncoding,
930 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
931 /*FunctionCache=*/Cache::Yes),
932 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
933 Requires(Requires_), CVQuals(CVQuals_), RefQual(RefQual_) {}
934
935 template<typename Fn> void match(Fn F) const {
936 F(Ret, Name, Params, Attrs, Requires, CVQuals, RefQual);
937 }
938
939 Qualifiers getCVQuals() const { return CVQuals; }
940 FunctionRefQual getRefQual() const { return RefQual; }
941 NodeArray getParams() const { return Params; }
942 const Node *getReturnType() const { return Ret; }
943
944 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
945 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
946
947 const Node *getName() const { return Name; }
948
949 void printLeft(OutputBuffer &OB) const override {
950 if (Ret) {
951 Ret->printLeft(OB);
952 if (!Ret->hasRHSComponent(OB))
953 OB += " ";
954 }
955 Name->print(OB);
956 }
957
958 void printRight(OutputBuffer &OB) const override {
959 OB.printOpen();
960 Params.printWithComma(OB);
961 OB.printClose();
962 if (Ret)
963 Ret->printRight(OB);
964
965 if (CVQuals & QualConst)
966 OB += " const";
967 if (CVQuals & QualVolatile)
968 OB += " volatile";
969 if (CVQuals & QualRestrict)
970 OB += " restrict";
971
972 if (RefQual == FrefQualLValue)
973 OB += " &";
974 else if (RefQual == FrefQualRValue)
975 OB += " &&";
976
977 if (Attrs != nullptr)
978 Attrs->print(OB);
979
980 if (Requires != nullptr) {
981 OB += " requires ";
982 Requires->print(OB);
983 }
984 }
985};
986
987class LiteralOperator : public Node {
988 const Node *OpName;
989
990public:
991 LiteralOperator(const Node *OpName_)
992 : Node(KLiteralOperator), OpName(OpName_) {}
993
994 template<typename Fn> void match(Fn F) const { F(OpName); }
995
996 void printLeft(OutputBuffer &OB) const override {
997 OB += "operator\"\" ";
998 OpName->print(OB);
999 }
1000};
1001
1002class SpecialName final : public Node {
1003 const std::string_view Special;
1004 const Node *Child;
1005
1006public:
1007 SpecialName(std::string_view Special_, const Node *Child_)
1008 : Node(KSpecialName), Special(Special_), Child(Child_) {}
1009
1010 template<typename Fn> void match(Fn F) const { F(Special, Child); }
1011
1012 void printLeft(OutputBuffer &OB) const override {
1013 OB += Special;
1014 Child->print(OB);
1015 }
1016};
1017
1018class CtorVtableSpecialName final : public Node {
1019 const Node *FirstType;
1020 const Node *SecondType;
1021
1022public:
1023 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
1024 : Node(KCtorVtableSpecialName),
1025 FirstType(FirstType_), SecondType(SecondType_) {}
1026
1027 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
1028
1029 void printLeft(OutputBuffer &OB) const override {
1030 OB += "construction vtable for ";
1031 FirstType->print(OB);
1032 OB += "-in-";
1033 SecondType->print(OB);
1034 }
1035};
1036
1040
1041 NestedName(Node *Qual_, Node *Name_)
1042 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
1043
1044 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
1045
1046 std::string_view getBaseName() const override { return Name->getBaseName(); }
1047
1048 void printLeft(OutputBuffer &OB) const override {
1049 Qual->print(OB);
1050 OB += "::";
1051 Name->print(OB);
1052 }
1053};
1054
1058
1060 : Node(KMemberLikeFriendName), Qual(Qual_), Name(Name_) {}
1061
1062 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
1063
1064 std::string_view getBaseName() const override { return Name->getBaseName(); }
1065
1066 void printLeft(OutputBuffer &OB) const override {
1067 Qual->print(OB);
1068 OB += "::friend ";
1069 Name->print(OB);
1070 }
1071};
1072
1077
1078 ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false)
1079 : Node(KModuleName), Parent(Parent_), Name(Name_),
1080 IsPartition(IsPartition_) {}
1081
1082 template <typename Fn> void match(Fn F) const {
1084 }
1085
1086 void printLeft(OutputBuffer &OB) const override {
1087 if (Parent)
1088 Parent->print(OB);
1089 if (Parent || IsPartition)
1090 OB += IsPartition ? ':' : '.';
1091 Name->print(OB);
1092 }
1093};
1094
1098
1099 ModuleEntity(ModuleName *Module_, Node *Name_)
1100 : Node(KModuleEntity), Module(Module_), Name(Name_) {}
1101
1102 template <typename Fn> void match(Fn F) const { F(Module, Name); }
1103
1104 std::string_view getBaseName() const override { return Name->getBaseName(); }
1105
1106 void printLeft(OutputBuffer &OB) const override {
1107 Name->print(OB);
1108 OB += '@';
1109 Module->print(OB);
1110 }
1111};
1112
1113struct LocalName : Node {
1116
1117 LocalName(Node *Encoding_, Node *Entity_)
1118 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
1119
1120 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
1121
1122 void printLeft(OutputBuffer &OB) const override {
1123 Encoding->print(OB);
1124 OB += "::";
1125 Entity->print(OB);
1126 }
1127};
1128
1129class QualifiedName final : public Node {
1130 // qualifier::name
1131 const Node *Qualifier;
1132 const Node *Name;
1133
1134public:
1135 QualifiedName(const Node *Qualifier_, const Node *Name_)
1136 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
1137
1138 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
1139
1140 std::string_view getBaseName() const override { return Name->getBaseName(); }
1141
1142 void printLeft(OutputBuffer &OB) const override {
1143 Qualifier->print(OB);
1144 OB += "::";
1145 Name->print(OB);
1146 }
1147};
1148
1149class VectorType final : public Node {
1150 const Node *BaseType;
1151 const Node *Dimension;
1152
1153public:
1154 VectorType(const Node *BaseType_, const Node *Dimension_)
1155 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}
1156
1157 const Node *getBaseType() const { return BaseType; }
1158 const Node *getDimension() const { return Dimension; }
1159
1160 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
1161
1162 void printLeft(OutputBuffer &OB) const override {
1163 BaseType->print(OB);
1164 OB += " vector[";
1165 if (Dimension)
1166 Dimension->print(OB);
1167 OB += "]";
1168 }
1169};
1170
1171class PixelVectorType final : public Node {
1172 const Node *Dimension;
1173
1174public:
1175 PixelVectorType(const Node *Dimension_)
1176 : Node(KPixelVectorType), Dimension(Dimension_) {}
1177
1178 template<typename Fn> void match(Fn F) const { F(Dimension); }
1179
1180 void printLeft(OutputBuffer &OB) const override {
1181 // FIXME: This should demangle as "vector pixel".
1182 OB += "pixel vector[";
1183 Dimension->print(OB);
1184 OB += "]";
1185 }
1186};
1187
1188class BinaryFPType final : public Node {
1189 const Node *Dimension;
1190
1191public:
1192 BinaryFPType(const Node *Dimension_)
1193 : Node(KBinaryFPType), Dimension(Dimension_) {}
1194
1195 template<typename Fn> void match(Fn F) const { F(Dimension); }
1196
1197 void printLeft(OutputBuffer &OB) const override {
1198 OB += "_Float";
1199 Dimension->print(OB);
1200 }
1201};
1202
1204
1205/// An invented name for a template parameter for which we don't have a
1206/// corresponding template argument.
1207///
1208/// This node is created when parsing the <lambda-sig> for a lambda with
1209/// explicit template arguments, which might be referenced in the parameter
1210/// types appearing later in the <lambda-sig>.
1211class SyntheticTemplateParamName final : public Node {
1213 unsigned Index;
1214
1215public:
1217 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
1218
1219 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
1220
1221 void printLeft(OutputBuffer &OB) const override {
1222 switch (Kind) {
1223 case TemplateParamKind::Type:
1224 OB += "$T";
1225 break;
1226 case TemplateParamKind::NonType:
1227 OB += "$N";
1228 break;
1229 case TemplateParamKind::Template:
1230 OB += "$TT";
1231 break;
1232 }
1233 if (Index > 0)
1234 OB << Index - 1;
1235 }
1236};
1237
1238class TemplateParamQualifiedArg final : public Node {
1239 Node *Param;
1240 Node *Arg;
1241
1242public:
1244 : Node(KTemplateParamQualifiedArg), Param(Param_), Arg(Arg_) {}
1245
1246 template <typename Fn> void match(Fn F) const { F(Param, Arg); }
1247
1248 Node *getArg() { return Arg; }
1249
1250 void printLeft(OutputBuffer &OB) const override {
1251 // Don't print Param to keep the output consistent.
1252 Arg->print(OB);
1253 }
1254};
1255
1256/// A template type parameter declaration, 'typename T'.
1257class TypeTemplateParamDecl final : public Node {
1258 Node *Name;
1259
1260public:
1262 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
1263
1264 template<typename Fn> void match(Fn F) const { F(Name); }
1265
1266 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
1267
1268 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
1269};
1270
1271/// A constrained template type parameter declaration, 'C<U> T'.
1273 Node *Constraint;
1274 Node *Name;
1275
1276public:
1278 : Node(KConstrainedTypeTemplateParamDecl, Cache::Yes),
1279 Constraint(Constraint_), Name(Name_) {}
1280
1281 template<typename Fn> void match(Fn F) const { F(Constraint, Name); }
1282
1283 void printLeft(OutputBuffer &OB) const override {
1284 Constraint->print(OB);
1285 OB += " ";
1286 }
1287
1288 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
1289};
1290
1291/// A non-type template parameter declaration, 'int N'.
1292class NonTypeTemplateParamDecl final : public Node {
1293 Node *Name;
1294 Node *Type;
1295
1296public:
1298 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
1299
1300 template<typename Fn> void match(Fn F) const { F(Name, Type); }
1301
1302 void printLeft(OutputBuffer &OB) const override {
1303 Type->printLeft(OB);
1304 if (!Type->hasRHSComponent(OB))
1305 OB += " ";
1306 }
1307
1308 void printRight(OutputBuffer &OB) const override {
1309 Name->print(OB);
1310 Type->printRight(OB);
1311 }
1312};
1313
1314/// A template template parameter declaration,
1315/// 'template<typename T> typename N'.
1316class TemplateTemplateParamDecl final : public Node {
1317 Node *Name;
1318 NodeArray Params;
1319 Node *Requires;
1320
1321public:
1322 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_, Node *Requires_)
1323 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1324 Params(Params_), Requires(Requires_) {}
1325
1326 template <typename Fn> void match(Fn F) const { F(Name, Params, Requires); }
1327
1328 void printLeft(OutputBuffer &OB) const override {
1329 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
1330 OB += "template<";
1331 Params.printWithComma(OB);
1332 OB += "> typename ";
1333 }
1334
1335 void printRight(OutputBuffer &OB) const override {
1336 Name->print(OB);
1337 if (Requires != nullptr) {
1338 OB += " requires ";
1339 Requires->print(OB);
1340 }
1341 }
1342};
1343
1344/// A template parameter pack declaration, 'typename ...T'.
1345class TemplateParamPackDecl final : public Node {
1346 Node *Param;
1347
1348public:
1350 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1351
1352 template<typename Fn> void match(Fn F) const { F(Param); }
1353
1354 void printLeft(OutputBuffer &OB) const override {
1355 Param->printLeft(OB);
1356 OB += "...";
1357 }
1358
1359 void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
1360};
1361
1362/// An unexpanded parameter pack (either in the expression or type context). If
1363/// this AST is correct, this node will have a ParameterPackExpansion node above
1364/// it.
1365///
1366/// This node is created when some <template-args> are found that apply to an
1367/// <encoding>, and is stored in the TemplateParams table. In order for this to
1368/// appear in the final AST, it has to referenced via a <template-param> (ie,
1369/// T_).
1370class ParameterPack final : public Node {
1371 NodeArray Data;
1372
1373 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1374 // one.
1375 void initializePackExpansion(OutputBuffer &OB) const {
1376 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1377 OB.CurrentPackMax = static_cast<unsigned>(Data.size());
1378 OB.CurrentPackIndex = 0;
1379 }
1380 }
1381
1382public:
1383 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1385 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1386 return P->ArrayCache == Cache::No;
1387 }))
1389 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1390 return P->FunctionCache == Cache::No;
1391 }))
1393 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1394 return P->RHSComponentCache == 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 independant 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// ::= Tn <type> # non-type parameter
5718// ::= Tt <template-param-decl>* E # template parameter
5719// ::= Tp <template-param-decl> # parameter pack
5720template <typename Derived, typename Alloc>
5722 TemplateParamList *Params) {
5723 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5724 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5725 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5726 if (N && Params)
5727 Params->push_back(N);
5728 return N;
5729 };
5730
5731 if (consumeIf("Ty")) {
5732 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5733 if (!Name)
5734 return nullptr;
5735 return make<TypeTemplateParamDecl>(Name);
5736 }
5737
5738 if (consumeIf("Tk")) {
5739 Node *Constraint = getDerived().parseName();
5740 if (!Constraint)
5741 return nullptr;
5742 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5743 if (!Name)
5744 return nullptr;
5745 return make<ConstrainedTypeTemplateParamDecl>(Constraint, Name);
5746 }
5747
5748 if (consumeIf("Tn")) {
5749 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5750 if (!Name)
5751 return nullptr;
5752 Node *Type = parseType();
5753 if (!Type)
5754 return nullptr;
5755 return make<NonTypeTemplateParamDecl>(Name, Type);
5756 }
5757
5758 if (consumeIf("Tt")) {
5759 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5760 if (!Name)
5761 return nullptr;
5762 size_t ParamsBegin = Names.size();
5763 ScopedTemplateParamList TemplateTemplateParamParams(this);
5764 Node *Requires = nullptr;
5765 while (!consumeIf('E')) {
5766 Node *P = parseTemplateParamDecl(TemplateTemplateParamParams.params());
5767 if (!P)
5768 return nullptr;
5769 Names.push_back(P);
5770 if (consumeIf('Q')) {
5771 Requires = getDerived().parseConstraintExpr();
5772 if (Requires == nullptr || !consumeIf('E'))
5773 return nullptr;
5774 break;
5775 }
5776 }
5777 NodeArray InnerParams = popTrailingNodeArray(ParamsBegin);
5778 return make<TemplateTemplateParamDecl>(Name, InnerParams, Requires);
5779 }
5780
5781 if (consumeIf("Tp")) {
5782 Node *P = parseTemplateParamDecl(Params);
5783 if (!P)
5784 return nullptr;
5785 return make<TemplateParamPackDecl>(P);
5786 }
5787
5788 return nullptr;
5789}
5790
5791// <template-arg> ::= <type> # type or template
5792// ::= X <expression> E # expression
5793// ::= <expr-primary> # simple expressions
5794// ::= J <template-arg>* E # argument pack
5795// ::= LZ <encoding> E # extension
5796// ::= <template-param-decl> <template-arg>
5797template <typename Derived, typename Alloc>
5799 switch (look()) {
5800 case 'X': {
5801 ++First;
5802 Node *Arg = getDerived().parseExpr();
5803 if (Arg == nullptr || !consumeIf('E'))
5804 return nullptr;
5805 return Arg;
5806 }
5807 case 'J': {
5808 ++First;
5809 size_t ArgsBegin = Names.size();
5810 while (!consumeIf('E')) {
5811 Node *Arg = getDerived().parseTemplateArg();
5812 if (Arg == nullptr)
5813 return nullptr;
5814 Names.push_back(Arg);
5815 }
5816 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5817 return make<TemplateArgumentPack>(Args);
5818 }
5819 case 'L': {
5820 // ::= LZ <encoding> E # extension
5821 if (look(1) == 'Z') {
5822 First += 2;
5823 Node *Arg = getDerived().parseEncoding();
5824 if (Arg == nullptr || !consumeIf('E'))
5825 return nullptr;
5826 return Arg;
5827 }
5828 // ::= <expr-primary> # simple expressions
5829 return getDerived().parseExprPrimary();
5830 }
5831 case 'T': {
5832 // Either <template-param> or a <template-param-decl> <template-arg>.
5833 if (!getDerived().isTemplateParamDecl())
5834 return getDerived().parseType();
5835 Node *Param = getDerived().parseTemplateParamDecl(nullptr);
5836 if (!Param)
5837 return nullptr;
5838 Node *Arg = getDerived().parseTemplateArg();
5839 if (!Arg)
5840 return nullptr;
5841 return make<TemplateParamQualifiedArg>(Param, Arg);
5842 }
5843 default:
5844 return getDerived().parseType();
5845 }
5846}
5847
5848// <template-args> ::= I <template-arg>* E
5849// extension, the abi says <template-arg>+
5850template <typename Derived, typename Alloc>
5851Node *
5853 if (!consumeIf('I'))
5854 return nullptr;
5855
5856 // <template-params> refer to the innermost <template-args>. Clear out any
5857 // outer args that we may have inserted into TemplateParams.
5858 if (TagTemplates) {
5859 TemplateParams.clear();
5860 TemplateParams.push_back(&OuterTemplateParams);
5861 OuterTemplateParams.clear();
5862 }
5863
5864 size_t ArgsBegin = Names.size();
5865 Node *Requires = nullptr;
5866 while (!consumeIf('E')) {
5867 if (TagTemplates) {
5868 Node *Arg = getDerived().parseTemplateArg();
5869 if (Arg == nullptr)
5870 return nullptr;
5871 Names.push_back(Arg);
5872 Node *TableEntry = Arg;
5873 if (Arg->getKind() == Node::KTemplateParamQualifiedArg) {
5874 TableEntry =
5875 static_cast<TemplateParamQualifiedArg *>(TableEntry)->getArg();
5876 }
5877 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5878 TableEntry = make<ParameterPack>(
5879 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
5880 if (!TableEntry)
5881 return nullptr;
5882 }
5883 OuterTemplateParams.push_back(TableEntry);
5884 } else {
5885 Node *Arg = getDerived().parseTemplateArg();
5886 if (Arg == nullptr)
5887 return nullptr;
5888 Names.push_back(Arg);
5889 }
5890 if (consumeIf('Q')) {
5891 Requires = getDerived().parseConstraintExpr();
5892 if (!Requires || !consumeIf('E'))
5893 return nullptr;
5894 break;
5895 }
5896 }
5897 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin), Requires);
5898}
5899
5900// <mangled-name> ::= _Z <encoding>
5901// ::= <type>
5902// extension ::= ___Z <encoding> _block_invoke
5903// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5904// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
5905template <typename Derived, typename Alloc>
5907 if (consumeIf("_Z") || consumeIf("__Z")) {
5908 Node *Encoding = getDerived().parseEncoding(ParseParams);
5909 if (Encoding == nullptr)
5910 return nullptr;
5911 if (look() == '.') {
5912 Encoding =
5913 make<DotSuffix>(Encoding, std::string_view(First, Last - First));
5914 First = Last;
5915 }
5916 if (numLeft() != 0)
5917 return nullptr;
5918 return Encoding;
5919 }
5920
5921 if (consumeIf("___Z") || consumeIf("____Z")) {
5922 Node *Encoding = getDerived().parseEncoding(ParseParams);
5923 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5924 return nullptr;
5925 bool RequireNumber = consumeIf('_');
5926 if (parseNumber().empty() && RequireNumber)
5927 return nullptr;
5928 if (look() == '.')
5929 First = Last;
5930 if (numLeft() != 0)
5931 return nullptr;
5932 return make<SpecialName>("invocation function for block in ", Encoding);
5933 }
5934
5935 Node *Ty = getDerived().parseType();
5936 if (numLeft() != 0)
5937 return nullptr;
5938 return Ty;
5939}
5940
5941template <typename Alloc>
5942struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5945};
5946
5948
5949#ifdef _LIBCXXABI_COMPILER_CLANG
5950#pragma clang diagnostic pop
5951#endif
5952
5953#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:1290
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)
bool hasArray(OutputBuffer &OB) 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
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.