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