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