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 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
4334 case 'F': {
4335 First += 2;
4336 Node *DimensionNumber = make<NameType>(parseNumber());
4337 if (!DimensionNumber)
4338 return nullptr;
4339 if (!consumeIf('_'))
4340 return nullptr;
4341 return make<BinaryFPType>(DimensionNumber);
4342 }
4343 // ::= [DS] DA # N1169 fixed-point [_Sat] T _Accum
4344 // ::= [DS] DR # N1169 fixed-point [_Sat] T _Frac
4345 // <fixed-point-size>
4346 // ::= s # short
4347 // ::= t # unsigned short
4348 // ::= i # plain
4349 // ::= j # unsigned
4350 // ::= l # long
4351 // ::= m # unsigned long
4352 case 'A': {
4353 char c = look(2);
4354 First += 3;
4355 switch (c) {
4356 case 's':
4357 return make<NameType>("short _Accum");
4358 case 't':
4359 return make<NameType>("unsigned short _Accum");
4360 case 'i':
4361 return make<NameType>("_Accum");
4362 case 'j':
4363 return make<NameType>("unsigned _Accum");
4364 case 'l':
4365 return make<NameType>("long _Accum");
4366 case 'm':
4367 return make<NameType>("unsigned long _Accum");
4368 default:
4369 return nullptr;
4370 }
4371 }
4372 case 'R': {
4373 char c = look(2);
4374 First += 3;
4375 switch (c) {
4376 case 's':
4377 return make<NameType>("short _Fract");
4378 case 't':
4379 return make<NameType>("unsigned short _Fract");
4380 case 'i':
4381 return make<NameType>("_Fract");
4382 case 'j':
4383 return make<NameType>("unsigned _Fract");
4384 case 'l':
4385 return make<NameType>("long _Fract");
4386 case 'm':
4387 return make<NameType>("unsigned long _Fract");
4388 default:
4389 return nullptr;
4390 }
4391 }
4392 case 'S': {
4393 First += 2;
4394 if (look() != 'D')
4395 return nullptr;
4396 if (look(1) == 'A') {
4397 char c = look(2);
4398 First += 3;
4399 switch (c) {
4400 case 's':
4401 return make<NameType>("_Sat short _Accum");
4402 case 't':
4403 return make<NameType>("_Sat unsigned short _Accum");
4404 case 'i':
4405 return make<NameType>("_Sat _Accum");
4406 case 'j':
4407 return make<NameType>("_Sat unsigned _Accum");
4408 case 'l':
4409 return make<NameType>("_Sat long _Accum");
4410 case 'm':
4411 return make<NameType>("_Sat unsigned long _Accum");
4412 default:
4413 return nullptr;
4414 }
4415 }
4416 if (look(1) == 'R') {
4417 char c = look(2);
4418 First += 3;
4419 switch (c) {
4420 case 's':
4421 return make<NameType>("_Sat short _Fract");
4422 case 't':
4423 return make<NameType>("_Sat unsigned short _Fract");
4424 case 'i':
4425 return make<NameType>("_Sat _Fract");
4426 case 'j':
4427 return make<NameType>("_Sat unsigned _Fract");
4428 case 'l':
4429 return make<NameType>("_Sat long _Fract");
4430 case 'm':
4431 return make<NameType>("_Sat unsigned long _Fract");
4432 default:
4433 return nullptr;
4434 }
4435 }
4436 return nullptr;
4437 }
4438 // ::= DB <number> _ # C23 signed _BitInt(N)
4439 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
4440 // ::= DU <number> _ # C23 unsigned _BitInt(N)
4441 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
4442 case 'B':
4443 case 'U': {
4444 bool Signed = look(1) == 'B';
4445 First += 2;
4446 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())
4447 : getDerived().parseExpr();
4448 if (!Size)
4449 return nullptr;
4450 if (!consumeIf('_'))
4451 return nullptr;
4452 return make<BitIntType>(Size, Signed);
4453 }
4454 // ::= Di # char32_t
4455 case 'i':
4456 First += 2;
4457 return make<NameType>("char32_t");
4458 // ::= Ds # char16_t
4459 case 's':
4460 First += 2;
4461 return make<NameType>("char16_t");
4462 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
4463 case 'u':
4464 First += 2;
4465 return make<NameType>("char8_t");
4466 // ::= Da # auto (in dependent new-expressions)
4467 case 'a':
4468 First += 2;
4469 return make<NameType>("auto");
4470 // ::= Dc # decltype(auto)
4471 case 'c':
4472 First += 2;
4473 return make<NameType>("decltype(auto)");
4474 // ::= Dk <type-constraint> # constrained auto
4475 // ::= DK <type-constraint> # constrained decltype(auto)
4476 case 'k':
4477 case 'K': {
4478 std::string_view Kind = look(1) == 'k' ? " auto" : " decltype(auto)";
4479 First += 2;
4480 Node *Constraint = getDerived().parseName();
4481 if (!Constraint)
4482 return nullptr;
4483 return make<PostfixQualifiedType>(Constraint, Kind);
4484 }
4485 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
4486 case 'n':
4487 First += 2;
4488 return make<NameType>("std::nullptr_t");
4489
4490 // ::= <decltype>
4491 case 't':
4492 case 'T': {
4493 Result = getDerived().parseDecltype();
4494 break;
4495 }
4496 // extension ::= <vector-type> # <vector-type> starts with Dv
4497 case 'v': {
4498 Result = getDerived().parseVectorType();
4499 break;
4500 }
4501 // ::= Dp <type> # pack expansion (C++0x)
4502 case 'p': {
4503 First += 2;
4504 Node *Child = getDerived().parseType();
4505 if (!Child)
4506 return nullptr;
4507 Result = make<ParameterPackExpansion>(Child);
4508 break;
4509 }
4510 // Exception specifier on a function type.
4511 case 'o':
4512 case 'O':
4513 case 'w':
4514 // Transaction safe function type.
4515 case 'x':
4516 Result = getDerived().parseFunctionType();
4517 break;
4518 }
4519 break;
4520 // ::= <function-type>
4521 case 'F': {
4522 Result = getDerived().parseFunctionType();
4523 break;
4524 }
4525 // ::= <array-type>
4526 case 'A': {
4527 Result = getDerived().parseArrayType();
4528 break;
4529 }
4530 // ::= <pointer-to-member-type>
4531 case 'M': {
4532 Result = getDerived().parsePointerToMemberType();
4533 break;
4534 }
4535 // ::= <template-param>
4536 case 'T': {
4537 // This could be an elaborate type specifier on a <class-enum-type>.
4538 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
4539 Result = getDerived().parseClassEnumType();
4540 break;
4541 }
4542
4543 Result = getDerived().parseTemplateParam();
4544 if (Result == nullptr)
4545 return nullptr;
4546
4547 // Result could be either of:
4548 // <type> ::= <template-param>
4549 // <type> ::= <template-template-param> <template-args>
4550 //
4551 // <template-template-param> ::= <template-param>
4552 // ::= <substitution>
4553 //
4554 // If this is followed by some <template-args>, and we're permitted to
4555 // parse them, take the second production.
4556
4557 if (TryToParseTemplateArgs && look() == 'I') {
4558 Subs.push_back(Result);
4559 Node *TA = getDerived().parseTemplateArgs();
4560 if (TA == nullptr)
4561 return nullptr;
4562 Result = make<NameWithTemplateArgs>(Result, TA);
4563 }
4564 break;
4565 }
4566 // ::= P <type> # pointer
4567 case 'P': {
4568 ++First;
4569 Node *Ptr = getDerived().parseType();
4570 if (Ptr == nullptr)
4571 return nullptr;
4572 Result = make<PointerType>(Ptr);
4573 break;
4574 }
4575 // ::= R <type> # l-value reference
4576 case 'R': {
4577 ++First;
4578 Node *Ref = getDerived().parseType();
4579 if (Ref == nullptr)
4580 return nullptr;
4581 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4582 break;
4583 }
4584 // ::= O <type> # r-value reference (C++11)
4585 case 'O': {
4586 ++First;
4587 Node *Ref = getDerived().parseType();
4588 if (Ref == nullptr)
4589 return nullptr;
4590 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4591 break;
4592 }
4593 // ::= C <type> # complex pair (C99)
4594 case 'C': {
4595 ++First;
4596 Node *P = getDerived().parseType();
4597 if (P == nullptr)
4598 return nullptr;
4599 Result = make<PostfixQualifiedType>(P, " complex");
4600 break;
4601 }
4602 // ::= G <type> # imaginary (C99)
4603 case 'G': {
4604 ++First;
4605 Node *P = getDerived().parseType();
4606 if (P == nullptr)
4607 return P;
4608 Result = make<PostfixQualifiedType>(P, " imaginary");
4609 break;
4610 }
4611 // ::= <substitution> # See Compression below
4612 case 'S': {
4613 if (look(1) != 't') {
4614 bool IsSubst = false;
4615 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4616 if (!Result)
4617 return nullptr;
4618
4619 // Sub could be either of:
4620 // <type> ::= <substitution>
4621 // <type> ::= <template-template-param> <template-args>
4622 //
4623 // <template-template-param> ::= <template-param>
4624 // ::= <substitution>
4625 //
4626 // If this is followed by some <template-args>, and we're permitted to
4627 // parse them, take the second production.
4628
4629 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4630 if (!IsSubst)
4631 Subs.push_back(Result);
4632 Node *TA = getDerived().parseTemplateArgs();
4633 if (TA == nullptr)
4634 return nullptr;
4635 Result = make<NameWithTemplateArgs>(Result, TA);
4636 } else if (IsSubst) {
4637 // If all we parsed was a substitution, don't re-insert into the
4638 // substitution table.
4639 return Result;
4640 }
4641 break;
4642 }
4644 }
4645 // ::= <class-enum-type>
4646 default: {
4647 Result = getDerived().parseClassEnumType();
4648 break;
4649 }
4650 }
4651
4652 // If we parsed a type, insert it into the substitution table. Note that all
4653 // <builtin-type>s and <substitution>s have already bailed out, because they
4654 // don't get substitutions.
4655 if (Result != nullptr)
4656 Subs.push_back(Result);
4657 return Result;
4658}
4659
4660template <typename Derived, typename Alloc>
4661Node *
4663 Node::Prec Prec) {
4664 Node *E = getDerived().parseExpr();
4665 if (E == nullptr)
4666 return nullptr;
4667 return make<PrefixExpr>(Kind, E, Prec);
4668}
4669
4670template <typename Derived, typename Alloc>
4671Node *
4673 Node::Prec Prec) {
4674 Node *LHS = getDerived().parseExpr();
4675 if (LHS == nullptr)
4676 return nullptr;
4677 Node *RHS = getDerived().parseExpr();
4678 if (RHS == nullptr)
4679 return nullptr;
4680 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
4681}
4682
4683template <typename Derived, typename Alloc>
4685 std::string_view Lit) {
4686 std::string_view Tmp = parseNumber(true);
4687 if (!Tmp.empty() && consumeIf('E'))
4688 return make<IntegerLiteral>(Lit, Tmp);
4689 return nullptr;
4690}
4691
4692// <CV-Qualifiers> ::= [r] [V] [K]
4693template <typename Alloc, typename Derived>
4695 Qualifiers CVR = QualNone;
4696 if (consumeIf('r'))
4697 CVR |= QualRestrict;
4698 if (consumeIf('V'))
4699 CVR |= QualVolatile;
4700 if (consumeIf('K'))
4701 CVR |= QualConst;
4702 return CVR;
4703}
4704
4705// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4706// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4707// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4708// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
4709// ::= fpT # 'this' expression (not part of standard?)
4710template <typename Derived, typename Alloc>
4712 if (consumeIf("fpT"))
4713 return make<NameType>("this");
4714 if (consumeIf("fp")) {
4715 parseCVQualifiers();
4716 std::string_view Num = parseNumber();
4717 if (!consumeIf('_'))
4718 return nullptr;
4719 return make<FunctionParam>(Num);
4720 }
4721 if (consumeIf("fL")) {
4722 if (parseNumber().empty())
4723 return nullptr;
4724 if (!consumeIf('p'))
4725 return nullptr;
4726 parseCVQualifiers();
4727 std::string_view Num = parseNumber();
4728 if (!consumeIf('_'))
4729 return nullptr;
4730 return make<FunctionParam>(Num);
4731 }
4732 return nullptr;
4733}
4734
4735// cv <type> <expression> # conversion with one argument
4736// cv <type> _ <expression>* E # conversion with a different number of arguments
4737template <typename Derived, typename Alloc>
4739 if (!consumeIf("cv"))
4740 return nullptr;
4741 Node *Ty;
4742 {
4743 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
4744 Ty = getDerived().parseType();
4745 }
4746
4747 if (Ty == nullptr)
4748 return nullptr;
4749
4750 if (consumeIf('_')) {
4751 size_t ExprsBegin = Names.size();
4752 while (!consumeIf('E')) {
4753 Node *E = getDerived().parseExpr();
4754 if (E == nullptr)
4755 return E;
4756 Names.push_back(E);
4757 }
4758 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4759 return make<ConversionExpr>(Ty, Exprs);
4760 }
4761
4762 Node *E[1] = {getDerived().parseExpr()};
4763 if (E[0] == nullptr)
4764 return nullptr;
4765 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4766}
4767
4768// <expr-primary> ::= L <type> <value number> E # integer literal
4769// ::= L <type> <value float> E # floating literal
4770// ::= L <string type> E # string literal
4771// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
4772// ::= L <lambda type> E # lambda expression
4773// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4774// ::= L <mangled-name> E # external name
4775template <typename Derived, typename Alloc>
4777 if (!consumeIf('L'))
4778 return nullptr;
4779 switch (look()) {
4780 case 'w':
4781 ++First;
4782 return getDerived().parseIntegerLiteral("wchar_t");
4783 case 'b':
4784 if (consumeIf("b0E"))
4785 return make<BoolExpr>(0);
4786 if (consumeIf("b1E"))
4787 return make<BoolExpr>(1);
4788 return nullptr;
4789 case 'c':
4790 ++First;
4791 return getDerived().parseIntegerLiteral("char");
4792 case 'a':
4793 ++First;
4794 return getDerived().parseIntegerLiteral("signed char");
4795 case 'h':
4796 ++First;
4797 return getDerived().parseIntegerLiteral("unsigned char");
4798 case 's':
4799 ++First;
4800 return getDerived().parseIntegerLiteral("short");
4801 case 't':
4802 ++First;
4803 return getDerived().parseIntegerLiteral("unsigned short");
4804 case 'i':
4805 ++First;
4806 return getDerived().parseIntegerLiteral("");
4807 case 'j':
4808 ++First;
4809 return getDerived().parseIntegerLiteral("u");
4810 case 'l':
4811 ++First;
4812 return getDerived().parseIntegerLiteral("l");
4813 case 'm':
4814 ++First;
4815 return getDerived().parseIntegerLiteral("ul");
4816 case 'x':
4817 ++First;
4818 return getDerived().parseIntegerLiteral("ll");
4819 case 'y':
4820 ++First;
4821 return getDerived().parseIntegerLiteral("ull");
4822 case 'n':
4823 ++First;
4824 return getDerived().parseIntegerLiteral("__int128");
4825 case 'o':
4826 ++First;
4827 return getDerived().parseIntegerLiteral("unsigned __int128");
4828 case 'f':
4829 ++First;
4830 return getDerived().template parseFloatingLiteral<float>();
4831 case 'd':
4832 ++First;
4833 return getDerived().template parseFloatingLiteral<double>();
4834 case 'e':
4835 ++First;
4836#if defined(__powerpc__) || defined(__s390__)
4837 // Handle cases where long doubles encoded with e have the same size
4838 // and representation as doubles.
4839 return getDerived().template parseFloatingLiteral<double>();
4840#else
4841 return getDerived().template parseFloatingLiteral<long double>();
4842#endif
4843 case '_':
4844 if (consumeIf("_Z")) {
4845 Node *R = getDerived().parseEncoding();
4846 if (R != nullptr && consumeIf('E'))
4847 return R;
4848 }
4849 return nullptr;
4850 case 'A': {
4851 Node *T = getDerived().parseType();
4852 if (T == nullptr)
4853 return nullptr;
4854 // FIXME: We need to include the string contents in the mangling.
4855 if (consumeIf('E'))
4856 return make<StringLiteral>(T);
4857 return nullptr;
4858 }
4859 case 'D':
4860 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
4861 return make<NameType>("nullptr");
4862 return nullptr;
4863 case 'T':
4864 // Invalid mangled name per
4865 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4866 return nullptr;
4867 case 'U': {
4868 // FIXME: Should we support LUb... for block literals?
4869 if (look(1) != 'l')
4870 return nullptr;
4871 Node *T = parseUnnamedTypeName(nullptr);
4872 if (!T || !consumeIf('E'))
4873 return nullptr;
4874 return make<LambdaExpr>(T);
4875 }
4876 default: {
4877 // might be named type
4878 Node *T = getDerived().parseType();
4879 if (T == nullptr)
4880 return nullptr;
4881 std::string_view N = parseNumber(/*AllowNegative=*/true);
4882 if (N.empty())
4883 return nullptr;
4884 if (!consumeIf('E'))
4885 return nullptr;
4886 return make<EnumLiteral>(T, N);
4887 }
4888 }
4889}
4890
4891// <braced-expression> ::= <expression>
4892// ::= di <field source-name> <braced-expression> # .name = expr
4893// ::= dx <index expression> <braced-expression> # [expr] = expr
4894// ::= dX <range begin expression> <range end expression> <braced-expression>
4895template <typename Derived, typename Alloc>
4897 if (look() == 'd') {
4898 switch (look(1)) {
4899 case 'i': {
4900 First += 2;
4901 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
4902 if (Field == nullptr)
4903 return nullptr;
4904 Node *Init = getDerived().parseBracedExpr();
4905 if (Init == nullptr)
4906 return nullptr;
4907 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4908 }
4909 case 'x': {
4910 First += 2;
4911 Node *Index = getDerived().parseExpr();
4912 if (Index == nullptr)
4913 return nullptr;
4914 Node *Init = getDerived().parseBracedExpr();
4915 if (Init == nullptr)
4916 return nullptr;
4917 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4918 }
4919 case 'X': {
4920 First += 2;
4921 Node *RangeBegin = getDerived().parseExpr();
4922 if (RangeBegin == nullptr)
4923 return nullptr;
4924 Node *RangeEnd = getDerived().parseExpr();
4925 if (RangeEnd == nullptr)
4926 return nullptr;
4927 Node *Init = getDerived().parseBracedExpr();
4928 if (Init == nullptr)
4929 return nullptr;
4930 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4931 }
4932 }
4933 }
4934 return getDerived().parseExpr();
4935}
4936
4937// (not yet in the spec)
4938// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4939// ::= fR <binary-operator-name> <expression> <expression>
4940// ::= fl <binary-operator-name> <expression>
4941// ::= fr <binary-operator-name> <expression>
4942template <typename Derived, typename Alloc>
4944 if (!consumeIf('f'))
4945 return nullptr;
4946
4947 bool IsLeftFold = false, HasInitializer = false;
4948 switch (look()) {
4949 default:
4950 return nullptr;
4951 case 'L':
4952 IsLeftFold = true;
4953 HasInitializer = true;
4954 break;
4955 case 'R':
4956 HasInitializer = true;
4957 break;
4958 case 'l':
4959 IsLeftFold = true;
4960 break;
4961 case 'r':
4962 break;
4963 }
4964 ++First;
4965
4966 const auto *Op = parseOperatorEncoding();
4967 if (!Op)
4968 return nullptr;
4969 if (!(Op->getKind() == OperatorInfo::Binary
4970 || (Op->getKind() == OperatorInfo::Member
4971 && Op->getName().back() == '*')))
4972 return nullptr;
4973
4974 Node *Pack = getDerived().parseExpr();
4975 if (Pack == nullptr)
4976 return nullptr;
4977
4978 Node *Init = nullptr;
4979 if (HasInitializer) {
4980 Init = getDerived().parseExpr();
4981 if (Init == nullptr)
4982 return nullptr;
4983 }
4984
4985 if (IsLeftFold && Init)
4986 std::swap(Pack, Init);
4987
4988 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
4989}
4990
4991// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4992//
4993// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4994template <typename Derived, typename Alloc>
4995Node *
4997 Node::Prec Prec) {
4998 Node *Ty = getDerived().parseType();
4999 if (!Ty)
5000 return nullptr;
5001 Node *Expr = getDerived().parseExpr();
5002 if (!Expr)
5003 return nullptr;
5004 std::string_view Offset = getDerived().parseNumber(true);
5005 if (!consumeIf('E'))
5006 return nullptr;
5007 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
5008}
5009
5010// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
5011// <union-selector> ::= _ [<number>]
5012//
5013// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
5014template <typename Derived, typename Alloc>
5016 Node *Ty = getDerived().parseType();
5017 if (!Ty)
5018 return nullptr;
5019 Node *Expr = getDerived().parseExpr();
5020 if (!Expr)
5021 return nullptr;
5022 std::string_view Offset = getDerived().parseNumber(true);
5023 size_t SelectorsBegin = Names.size();
5024 while (consumeIf('_')) {
5025 Node *Selector = make<NameType>(parseNumber());
5026 if (!Selector)
5027 return nullptr;
5028 Names.push_back(Selector);
5029 }
5030 bool OnePastTheEnd = consumeIf('p');
5031 if (!consumeIf('E'))
5032 return nullptr;
5033 return make<SubobjectExpr>(
5034 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
5035}
5036
5037template <typename Derived, typename Alloc>
5039 // Within this expression, all enclosing template parameter lists are in
5040 // scope.
5041 ScopedOverride<bool> SaveIncompleteTemplateParameterTracking(
5042 HasIncompleteTemplateParameterTracking, true);
5043 return getDerived().parseExpr();
5044}
5045
5046template <typename Derived, typename Alloc>
5048 NodeArray Params;
5049 if (consumeIf("rQ")) {
5050 // <expression> ::= rQ <bare-function-type> _ <requirement>+ E
5051 size_t ParamsBegin = Names.size();
5052 while (!consumeIf('_')) {
5053 Node *Type = getDerived().parseType();
5054 if (Type == nullptr)
5055 return nullptr;
5056 Names.push_back(Type);
5057 }
5058 Params = popTrailingNodeArray(ParamsBegin);
5059 } else if (!consumeIf("rq")) {
5060 // <expression> ::= rq <requirement>+ E
5061 return nullptr;
5062 }
5063
5064 size_t ReqsBegin = Names.size();
5065 do {
5066 Node *Constraint = nullptr;
5067 if (consumeIf('X')) {
5068 // <requirement> ::= X <expression> [N] [R <type-constraint>]
5069 Node *Expr = getDerived().parseExpr();
5070 if (Expr == nullptr)
5071 return nullptr;
5072 bool Noexcept = consumeIf('N');
5073 Node *TypeReq = nullptr;
5074 if (consumeIf('R')) {
5075 TypeReq = getDerived().parseName();
5076 if (TypeReq == nullptr)
5077 return nullptr;
5078 }
5079 Constraint = make<ExprRequirement>(Expr, Noexcept, TypeReq);
5080 } else if (consumeIf('T')) {
5081 // <requirement> ::= T <type>
5082 Node *Type = getDerived().parseType();
5083 if (Type == nullptr)
5084 return nullptr;
5085 Constraint = make<TypeRequirement>(Type);
5086 } else if (consumeIf('Q')) {
5087 // <requirement> ::= Q <constraint-expression>
5088 //
5089 // FIXME: We use <expression> instead of <constraint-expression>. Either
5090 // the requires expression is already inside a constraint expression, in
5091 // which case it makes no difference, or we're in a requires-expression
5092 // that might be partially-substituted, where the language behavior is
5093 // not yet settled and clang mangles after substitution.
5094 Node *NestedReq = getDerived().parseExpr();
5095 if (NestedReq == nullptr)
5096 return nullptr;
5097 Constraint = make<NestedRequirement>(NestedReq);
5098 }
5099 if (Constraint == nullptr)
5100 return nullptr;
5101 Names.push_back(Constraint);
5102 } while (!consumeIf('E'));
5103
5104 return make<RequiresExpr>(Params, popTrailingNodeArray(ReqsBegin));
5105}
5106
5107// <expression> ::= <unary operator-name> <expression>
5108// ::= <binary operator-name> <expression> <expression>
5109// ::= <ternary operator-name> <expression> <expression> <expression>
5110// ::= cl <expression>+ E # call
5111// ::= cp <base-unresolved-name> <expression>* E # (name) (expr-list), call that would use argument-dependent lookup but for the parentheses
5112// ::= cv <type> <expression> # conversion with one argument
5113// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
5114// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
5115// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
5116// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
5117// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
5118// ::= [gs] dl <expression> # delete expression
5119// ::= [gs] da <expression> # delete[] expression
5120// ::= pp_ <expression> # prefix ++
5121// ::= mm_ <expression> # prefix --
5122// ::= ti <type> # typeid (type)
5123// ::= te <expression> # typeid (expression)
5124// ::= dc <type> <expression> # dynamic_cast<type> (expression)
5125// ::= sc <type> <expression> # static_cast<type> (expression)
5126// ::= cc <type> <expression> # const_cast<type> (expression)
5127// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
5128// ::= st <type> # sizeof (a type)
5129// ::= sz <expression> # sizeof (an expression)
5130// ::= at <type> # alignof (a type)
5131// ::= az <expression> # alignof (an expression)
5132// ::= nx <expression> # noexcept (expression)
5133// ::= <template-param>
5134// ::= <function-param>
5135// ::= dt <expression> <unresolved-name> # expr.name
5136// ::= pt <expression> <unresolved-name> # expr->name
5137// ::= ds <expression> <expression> # expr.*expr
5138// ::= sZ <template-param> # size of a parameter pack
5139// ::= sZ <function-param> # size of a function parameter pack
5140// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
5141// ::= sp <expression> # pack expansion
5142// ::= tw <expression> # throw expression
5143// ::= tr # throw with no operand (rethrow)
5144// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
5145// # freestanding dependent name (e.g., T::x),
5146// # objectless nonstatic member reference
5147// ::= fL <binary-operator-name> <expression> <expression>
5148// ::= fR <binary-operator-name> <expression> <expression>
5149// ::= fl <binary-operator-name> <expression>
5150// ::= fr <binary-operator-name> <expression>
5151// ::= <expr-primary>
5152template <typename Derived, typename Alloc>
5154 bool Global = consumeIf("gs");
5155
5156 const auto *Op = parseOperatorEncoding();
5157 if (Op) {
5158 auto Sym = Op->getSymbol();
5159 switch (Op->getKind()) {
5160 case OperatorInfo::Binary:
5161 // Binary operator: lhs @ rhs
5162 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
5163 case OperatorInfo::Prefix:
5164 // Prefix unary operator: @ expr
5165 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
5166 case OperatorInfo::Postfix: {
5167 // Postfix unary operator: expr @
5168 if (consumeIf('_'))
5169 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
5170 Node *Ex = getDerived().parseExpr();
5171 if (Ex == nullptr)
5172 return nullptr;
5173 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
5174 }
5175 case OperatorInfo::Array: {
5176 // Array Index: lhs [ rhs ]
5177 Node *Base = getDerived().parseExpr();
5178 if (Base == nullptr)
5179 return nullptr;
5180 Node *Index = getDerived().parseExpr();
5181 if (Index == nullptr)
5182 return nullptr;
5183 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
5184 }
5185 case OperatorInfo::Member: {
5186 // Member access lhs @ rhs
5187 Node *LHS = getDerived().parseExpr();
5188 if (LHS == nullptr)
5189 return nullptr;
5190 Node *RHS = getDerived().parseExpr();
5191 if (RHS == nullptr)
5192 return nullptr;
5193 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
5194 }
5195 case OperatorInfo::New: {
5196 // New
5197 // # new (expr-list) type [(init)]
5198 // [gs] nw <expression>* _ <type> [pi <expression>*] E
5199 // # new[] (expr-list) type [(init)]
5200 // [gs] na <expression>* _ <type> [pi <expression>*] E
5201 size_t Exprs = Names.size();
5202 while (!consumeIf('_')) {
5203 Node *Ex = getDerived().parseExpr();
5204 if (Ex == nullptr)
5205 return nullptr;
5206 Names.push_back(Ex);
5207 }
5208 NodeArray ExprList = popTrailingNodeArray(Exprs);
5209 Node *Ty = getDerived().parseType();
5210 if (Ty == nullptr)
5211 return nullptr;
5212 bool HaveInits = consumeIf("pi");
5213 size_t InitsBegin = Names.size();
5214 while (!consumeIf('E')) {
5215 if (!HaveInits)
5216 return nullptr;
5217 Node *Init = getDerived().parseExpr();
5218 if (Init == nullptr)
5219 return Init;
5220 Names.push_back(Init);
5221 }
5222 NodeArray Inits = popTrailingNodeArray(InitsBegin);
5223 return make<NewExpr>(ExprList, Ty, Inits, Global,
5224 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
5225 }
5226 case OperatorInfo::Del: {
5227 // Delete
5228 Node *Ex = getDerived().parseExpr();
5229 if (Ex == nullptr)
5230 return nullptr;
5231 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
5232 Op->getPrecedence());
5233 }
5234 case OperatorInfo::Call: {
5235 // Function Call
5236 Node *Callee = getDerived().parseExpr();
5237 if (Callee == nullptr)
5238 return nullptr;
5239 size_t ExprsBegin = Names.size();
5240 while (!consumeIf('E')) {
5241 Node *E = getDerived().parseExpr();
5242 if (E == nullptr)
5243 return nullptr;
5244 Names.push_back(E);
5245 }
5246 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
5247 /*IsParen=*/Op->getFlag(), Op->getPrecedence());
5248 }
5249 case OperatorInfo::CCast: {
5250 // C Cast: (type)expr
5251 Node *Ty;
5252 {
5253 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
5254 Ty = getDerived().parseType();
5255 }
5256 if (Ty == nullptr)
5257 return nullptr;
5258
5259 size_t ExprsBegin = Names.size();
5260 bool IsMany = consumeIf('_');
5261 while (!consumeIf('E')) {
5262 Node *E = getDerived().parseExpr();
5263 if (E == nullptr)
5264 return E;
5265 Names.push_back(E);
5266 if (!IsMany)
5267 break;
5268 }
5269 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
5270 if (!IsMany && Exprs.size() != 1)
5271 return nullptr;
5272 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
5273 }
5274 case OperatorInfo::Conditional: {
5275 // Conditional operator: expr ? expr : expr
5276 Node *Cond = getDerived().parseExpr();
5277 if (Cond == nullptr)
5278 return nullptr;
5279 Node *LHS = getDerived().parseExpr();
5280 if (LHS == nullptr)
5281 return nullptr;
5282 Node *RHS = getDerived().parseExpr();
5283 if (RHS == nullptr)
5284 return nullptr;
5285 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
5286 }
5287 case OperatorInfo::NamedCast: {
5288 // Named cast operation, @<type>(expr)
5289 Node *Ty = getDerived().parseType();
5290 if (Ty == nullptr)
5291 return nullptr;
5292 Node *Ex = getDerived().parseExpr();
5293 if (Ex == nullptr)
5294 return nullptr;
5295 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
5296 }
5297 case OperatorInfo::OfIdOp: {
5298 // [sizeof/alignof/typeid] ( <type>|<expr> )
5299 Node *Arg =
5300 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
5301 if (!Arg)
5302 return nullptr;
5303 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
5304 }
5305 case OperatorInfo::NameOnly: {
5306 // Not valid as an expression operand.
5307 return nullptr;
5308 }
5309 }
5311 }
5312
5313 if (numLeft() < 2)
5314 return nullptr;
5315
5316 if (look() == 'L')
5317 return getDerived().parseExprPrimary();
5318 if (look() == 'T')
5319 return getDerived().parseTemplateParam();
5320 if (look() == 'f') {
5321 // Disambiguate a fold expression from a <function-param>.
5322 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
5323 return getDerived().parseFunctionParam();
5324 return getDerived().parseFoldExpr();
5325 }
5326 if (consumeIf("il")) {
5327 size_t InitsBegin = Names.size();
5328 while (!consumeIf('E')) {
5329 Node *E = getDerived().parseBracedExpr();
5330 if (E == nullptr)
5331 return nullptr;
5332 Names.push_back(E);
5333 }
5334 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
5335 }
5336 if (consumeIf("mc"))
5337 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
5338 if (consumeIf("nx")) {
5339 Node *Ex = getDerived().parseExpr();
5340 if (Ex == nullptr)
5341 return Ex;
5342 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
5343 }
5344 if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q'))
5345 return parseRequiresExpr();
5346 if (consumeIf("so"))
5347 return parseSubobjectExpr();
5348 if (consumeIf("sp")) {
5349 Node *Child = getDerived().parseExpr();
5350 if (Child == nullptr)
5351 return nullptr;
5352 return make<ParameterPackExpansion>(Child);
5353 }
5354 if (consumeIf("sZ")) {
5355 if (look() == 'T') {
5356 Node *R = getDerived().parseTemplateParam();
5357 if (R == nullptr)
5358 return nullptr;
5359 return make<SizeofParamPackExpr>(R);
5360 }
5361 Node *FP = getDerived().parseFunctionParam();
5362 if (FP == nullptr)
5363 return nullptr;
5364 return make<EnclosingExpr>("sizeof... ", FP);
5365 }
5366 if (consumeIf("sP")) {
5367 size_t ArgsBegin = Names.size();
5368 while (!consumeIf('E')) {
5369 Node *Arg = getDerived().parseTemplateArg();
5370 if (Arg == nullptr)
5371 return nullptr;
5372 Names.push_back(Arg);
5373 }
5374 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
5375 if (!Pack)
5376 return nullptr;
5377 return make<EnclosingExpr>("sizeof... ", Pack);
5378 }
5379 if (consumeIf("tl")) {
5380 Node *Ty = getDerived().parseType();
5381 if (Ty == nullptr)
5382 return nullptr;
5383 size_t InitsBegin = Names.size();
5384 while (!consumeIf('E')) {
5385 Node *E = getDerived().parseBracedExpr();
5386 if (E == nullptr)
5387 return nullptr;
5388 Names.push_back(E);
5389 }
5390 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
5391 }
5392 if (consumeIf("tr"))
5393 return make<NameType>("throw");
5394 if (consumeIf("tw")) {
5395 Node *Ex = getDerived().parseExpr();
5396 if (Ex == nullptr)
5397 return nullptr;
5398 return make<ThrowExpr>(Ex);
5399 }
5400 if (consumeIf('u')) {
5401 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
5402 if (!Name)
5403 return nullptr;
5404 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
5405 // standard encoding expects a <template-arg>, and would be otherwise be
5406 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
5407 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
5408 // actual conflict here.
5409 bool IsUUID = false;
5410 Node *UUID = nullptr;
5411 if (Name->getBaseName() == "__uuidof") {
5412 if (consumeIf('t')) {
5413 UUID = getDerived().parseType();
5414 IsUUID = true;
5415 } else if (consumeIf('z')) {
5416 UUID = getDerived().parseExpr();
5417 IsUUID = true;
5418 }
5419 }
5420 size_t ExprsBegin = Names.size();
5421 if (IsUUID) {
5422 if (UUID == nullptr)
5423 return nullptr;
5424 Names.push_back(UUID);
5425 } else {
5426 while (!consumeIf('E')) {
5427 Node *E = getDerived().parseTemplateArg();
5428 if (E == nullptr)
5429 return E;
5430 Names.push_back(E);
5431 }
5432 }
5433 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
5434 /*IsParen=*/false, Node::Prec::Postfix);
5435 }
5436
5437 // Only unresolved names remain.
5438 return getDerived().parseUnresolvedName(Global);
5439}
5440
5441// <call-offset> ::= h <nv-offset> _
5442// ::= v <v-offset> _
5443//
5444// <nv-offset> ::= <offset number>
5445// # non-virtual base override
5446//
5447// <v-offset> ::= <offset number> _ <virtual offset number>
5448// # virtual base override, with vcall offset
5449template <typename Alloc, typename Derived>
5451 // Just scan through the call offset, we never add this information into the
5452 // output.
5453 if (consumeIf('h'))
5454 return parseNumber(true).empty() || !consumeIf('_');
5455 if (consumeIf('v'))
5456 return parseNumber(true).empty() || !consumeIf('_') ||
5457 parseNumber(true).empty() || !consumeIf('_');
5458 return true;
5459}
5460
5461// <special-name> ::= TV <type> # virtual table
5462// ::= TT <type> # VTT structure (construction vtable index)
5463// ::= TI <type> # typeinfo structure
5464// ::= TS <type> # typeinfo name (null-terminated byte string)
5465// ::= Tc <call-offset> <call-offset> <base encoding>
5466// # base is the nominal target function of thunk
5467// # first call-offset is 'this' adjustment
5468// # second call-offset is result adjustment
5469// ::= T <call-offset> <base encoding>
5470// # base is the nominal target function of thunk
5471// # Guard variable for one-time initialization
5472// ::= GV <object name>
5473// # No <type>
5474// ::= TW <object name> # Thread-local wrapper
5475// ::= TH <object name> # Thread-local initialization
5476// ::= GR <object name> _ # First temporary
5477// ::= GR <object name> <seq-id> _ # Subsequent temporaries
5478// # construction vtable for second-in-first
5479// extension ::= TC <first type> <number> _ <second type>
5480// extension ::= GR <object name> # reference temporary for object
5481// extension ::= GI <module name> # module global initializer
5482template <typename Derived, typename Alloc>
5484 switch (look()) {
5485 case 'T':
5486 switch (look(1)) {
5487 // TA <template-arg> # template parameter object
5488 //
5489 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
5490 case 'A': {
5491 First += 2;
5492 Node *Arg = getDerived().parseTemplateArg();
5493 if (Arg == nullptr)
5494 return nullptr;
5495 return make<SpecialName>("template parameter object for ", Arg);
5496 }
5497 // TV <type> # virtual table
5498 case 'V': {
5499 First += 2;
5500 Node *Ty = getDerived().parseType();
5501 if (Ty == nullptr)
5502 return nullptr;
5503 return make<SpecialName>("vtable for ", Ty);
5504 }
5505 // TT <type> # VTT structure (construction vtable index)
5506 case 'T': {
5507 First += 2;
5508 Node *Ty = getDerived().parseType();
5509 if (Ty == nullptr)
5510 return nullptr;
5511 return make<SpecialName>("VTT for ", Ty);
5512 }
5513 // TI <type> # typeinfo structure
5514 case 'I': {
5515 First += 2;
5516 Node *Ty = getDerived().parseType();
5517 if (Ty == nullptr)
5518 return nullptr;
5519 return make<SpecialName>("typeinfo for ", Ty);
5520 }
5521 // TS <type> # typeinfo name (null-terminated byte string)
5522 case 'S': {
5523 First += 2;
5524 Node *Ty = getDerived().parseType();
5525 if (Ty == nullptr)
5526 return nullptr;
5527 return make<SpecialName>("typeinfo name for ", Ty);
5528 }
5529 // Tc <call-offset> <call-offset> <base encoding>
5530 case 'c': {
5531 First += 2;
5532 if (parseCallOffset() || parseCallOffset())
5533 return nullptr;
5534 Node *Encoding = getDerived().parseEncoding();
5535 if (Encoding == nullptr)
5536 return nullptr;
5537 return make<SpecialName>("covariant return thunk to ", Encoding);
5538 }
5539 // extension ::= TC <first type> <number> _ <second type>
5540 // # construction vtable for second-in-first
5541 case 'C': {
5542 First += 2;
5543 Node *FirstType = getDerived().parseType();
5544 if (FirstType == nullptr)
5545 return nullptr;
5546 if (parseNumber(true).empty() || !consumeIf('_'))
5547 return nullptr;
5548 Node *SecondType = getDerived().parseType();
5549 if (SecondType == nullptr)
5550 return nullptr;
5551 return make<CtorVtableSpecialName>(SecondType, FirstType);
5552 }
5553 // TW <object name> # Thread-local wrapper
5554 case 'W': {
5555 First += 2;
5556 Node *Name = getDerived().parseName();
5557 if (Name == nullptr)
5558 return nullptr;
5559 return make<SpecialName>("thread-local wrapper routine for ", Name);
5560 }
5561 // TH <object name> # Thread-local initialization
5562 case 'H': {
5563 First += 2;
5564 Node *Name = getDerived().parseName();
5565 if (Name == nullptr)
5566 return nullptr;
5567 return make<SpecialName>("thread-local initialization routine for ", Name);
5568 }
5569 // T <call-offset> <base encoding>
5570 default: {
5571 ++First;
5572 bool IsVirt = look() == 'v';
5573 if (parseCallOffset())
5574 return nullptr;
5575 Node *BaseEncoding = getDerived().parseEncoding();
5576 if (BaseEncoding == nullptr)
5577 return nullptr;
5578 if (IsVirt)
5579 return make<SpecialName>("virtual thunk to ", BaseEncoding);
5580 else
5581 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
5582 }
5583 }
5584 case 'G':
5585 switch (look(1)) {
5586 // GV <object name> # Guard variable for one-time initialization
5587 case 'V': {
5588 First += 2;
5589 Node *Name = getDerived().parseName();
5590 if (Name == nullptr)
5591 return nullptr;
5592 return make<SpecialName>("guard variable for ", Name);
5593 }
5594 // GR <object name> # reference temporary for object
5595 // GR <object name> _ # First temporary
5596 // GR <object name> <seq-id> _ # Subsequent temporaries
5597 case 'R': {
5598 First += 2;
5599 Node *Name = getDerived().parseName();
5600 if (Name == nullptr)
5601 return nullptr;
5602 size_t Count;
5603 bool ParsedSeqId = !parseSeqId(&Count);
5604 if (!consumeIf('_') && ParsedSeqId)
5605 return nullptr;
5606 return make<SpecialName>("reference temporary for ", Name);
5607 }
5608 // GI <module-name> v
5609 case 'I': {
5610 First += 2;
5611 ModuleName *Module = nullptr;
5612 if (getDerived().parseModuleNameOpt(Module))
5613 return nullptr;
5614 if (Module == nullptr)
5615 return nullptr;
5616 return make<SpecialName>("initializer for module ", Module);
5617 }
5618 }
5619 }
5620 return nullptr;
5621}
5622
5623// <encoding> ::= <function name> <bare-function-type>
5624// [`Q` <requires-clause expr>]
5625// ::= <data name>
5626// ::= <special-name>
5627template <typename Derived, typename Alloc>
5629 // The template parameters of an encoding are unrelated to those of the
5630 // enclosing context.
5631 SaveTemplateParams SaveTemplateParamsScope(this);
5632
5633 if (look() == 'G' || look() == 'T')
5634 return getDerived().parseSpecialName();
5635
5636 auto IsEndOfEncoding = [&] {
5637 // The set of chars that can potentially follow an <encoding> (none of which
5638 // can start a <type>). Enumerating these allows us to avoid speculative
5639 // parsing.
5640 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5641 };
5642
5643 NameState NameInfo(this);
5644 Node *Name = getDerived().parseName(&NameInfo);
5645 if (Name == nullptr)
5646 return nullptr;
5647
5648 if (resolveForwardTemplateRefs(NameInfo))
5649 return nullptr;
5650
5651 if (IsEndOfEncoding())
5652 return Name;
5653
5654 // ParseParams may be false at the top level only, when called from parse().
5655 // For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be
5656 // false when demangling 3fooILZ3BarEET_f but is always true when demangling
5657 // 3Bar.
5658 if (!ParseParams) {
5659 while (consume())
5660 ;
5661 return Name;
5662 }
5663
5664 Node *Attrs = nullptr;
5665 if (consumeIf("Ua9enable_ifI")) {
5666 size_t BeforeArgs = Names.size();
5667 while (!consumeIf('E')) {
5668 Node *Arg = getDerived().parseTemplateArg();
5669 if (Arg == nullptr)
5670 return nullptr;
5671 Names.push_back(Arg);
5672 }
5673 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
5674 if (!Attrs)
5675 return nullptr;
5676 }
5677
5678 Node *ReturnType = nullptr;
5679 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
5680 ReturnType = getDerived().parseType();
5681 if (ReturnType == nullptr)
5682 return nullptr;
5683 }
5684
5685 NodeArray Params;
5686 if (!consumeIf('v')) {
5687 size_t ParamsBegin = Names.size();
5688 do {
5689 Node *Ty = getDerived().parseType();
5690 if (Ty == nullptr)
5691 return nullptr;
5692
5693 const bool IsFirstParam = ParamsBegin == Names.size();
5694 if (NameInfo.HasExplicitObjectParameter && IsFirstParam)
5695 Ty = make<ExplicitObjectParameter>(Ty);
5696
5697 if (Ty == nullptr)
5698 return nullptr;
5699
5700 Names.push_back(Ty);
5701 } while (!IsEndOfEncoding() && look() != 'Q');
5702 Params = popTrailingNodeArray(ParamsBegin);
5703 }
5704
5705 Node *Requires = nullptr;
5706 if (consumeIf('Q')) {
5707 Requires = getDerived().parseConstraintExpr();
5708 if (!Requires)
5709 return nullptr;
5710 }
5711
5712 return make<FunctionEncoding>(ReturnType, Name, Params, Attrs, Requires,
5713 NameInfo.CVQualifiers,
5714 NameInfo.ReferenceQualifier);
5715}
5716
5717template <class Float>
5718struct FloatData;
5719
5720template <>
5721struct FloatData<float>
5722{
5723 static const size_t mangled_size = 8;
5724 static const size_t max_demangled_size = 24;
5725 static constexpr const char* spec = "%af";
5726};
5727
5728template <>
5729struct FloatData<double>
5730{
5731 static const size_t mangled_size = 16;
5732 static const size_t max_demangled_size = 32;
5733 static constexpr const char* spec = "%a";
5734};
5735
5736template <>
5737struct FloatData<long double>
5738{
5739#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5740 defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \
5741 defined(__ve__)
5742 static const size_t mangled_size = 32;
5743#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5744 static const size_t mangled_size = 16;
5745#else
5746 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5747#endif
5748 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5749 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5750 // Negatives are one character longer than positives.
5751 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5752 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5753 static const size_t max_demangled_size = 42;
5754 static constexpr const char *spec = "%LaL";
5755};
5756
5757template <typename Alloc, typename Derived>
5758template <class Float>
5760 const size_t N = FloatData<Float>::mangled_size;
5761 if (numLeft() <= N)
5762 return nullptr;
5763 std::string_view Data(First, N);
5764 for (char C : Data)
5765 if (!(C >= '0' && C <= '9') && !(C >= 'a' && C <= 'f'))
5766 return nullptr;
5767 First += N;
5768 if (!consumeIf('E'))
5769 return nullptr;
5770 return make<FloatLiteralImpl<Float>>(Data);
5771}
5772
5773// <seq-id> ::= <0-9A-Z>+
5774template <typename Alloc, typename Derived>
5776 if (!(look() >= '0' && look() <= '9') &&
5777 !(look() >= 'A' && look() <= 'Z'))
5778 return true;
5779
5780 size_t Id = 0;
5781 while (true) {
5782 if (look() >= '0' && look() <= '9') {
5783 Id *= 36;
5784 Id += static_cast<size_t>(look() - '0');
5785 } else if (look() >= 'A' && look() <= 'Z') {
5786 Id *= 36;
5787 Id += static_cast<size_t>(look() - 'A') + 10;
5788 } else {
5789 *Out = Id;
5790 return false;
5791 }
5792 ++First;
5793 }
5794}
5795
5796// <substitution> ::= S <seq-id> _
5797// ::= S_
5798// <substitution> ::= Sa # ::std::allocator
5799// <substitution> ::= Sb # ::std::basic_string
5800// <substitution> ::= Ss # ::std::basic_string < char,
5801// ::std::char_traits<char>,
5802// ::std::allocator<char> >
5803// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5804// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5805// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
5806// The St case is handled specially in parseNestedName.
5807template <typename Derived, typename Alloc>
5809 if (!consumeIf('S'))
5810 return nullptr;
5811
5812 if (look() >= 'a' && look() <= 'z') {
5813 SpecialSubKind Kind;
5814 switch (look()) {
5815 case 'a':
5817 break;
5818 case 'b':
5820 break;
5821 case 'd':
5823 break;
5824 case 'i':
5826 break;
5827 case 'o':
5829 break;
5830 case 's':
5832 break;
5833 default:
5834 return nullptr;
5835 }
5836 ++First;
5837 auto *SpecialSub = make<SpecialSubstitution>(Kind);
5838 if (!SpecialSub)
5839 return nullptr;
5840
5841 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5842 // has ABI tags, the tags are appended to the substitution; the result is a
5843 // substitutable component.
5844 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
5845 if (WithTags != SpecialSub) {
5846 Subs.push_back(WithTags);
5847 SpecialSub = WithTags;
5848 }
5849 return SpecialSub;
5850 }
5851
5852 // ::= S_
5853 if (consumeIf('_')) {
5854 if (Subs.empty())
5855 return nullptr;
5856 return Subs[0];
5857 }
5858
5859 // ::= S <seq-id> _
5860 size_t Index = 0;
5861 if (parseSeqId(&Index))
5862 return nullptr;
5863 ++Index;
5864 if (!consumeIf('_') || Index >= Subs.size())
5865 return nullptr;
5866 return Subs[Index];
5867}
5868
5869// <template-param> ::= T_ # first template parameter
5870// ::= T <parameter-2 non-negative number> _
5871// ::= TL <level-1> __
5872// ::= TL <level-1> _ <parameter-2 non-negative number> _
5873template <typename Derived, typename Alloc>
5875 const char *Begin = First;
5876 if (!consumeIf('T'))
5877 return nullptr;
5878
5879 size_t Level = 0;
5880 if (consumeIf('L')) {
5881 if (parsePositiveInteger(&Level))
5882 return nullptr;
5883 ++Level;
5884 if (!consumeIf('_'))
5885 return nullptr;
5886 }
5887
5888 size_t Index = 0;
5889 if (!consumeIf('_')) {
5890 if (parsePositiveInteger(&Index))
5891 return nullptr;
5892 ++Index;
5893 if (!consumeIf('_'))
5894 return nullptr;
5895 }
5896
5897 // We don't track enclosing template parameter levels well enough to reliably
5898 // substitute them all within a <constraint-expression>, so print the
5899 // parameter numbering instead for now.
5900 // TODO: Track all enclosing template parameters and substitute them here.
5901 if (HasIncompleteTemplateParameterTracking) {
5902 return make<NameType>(std::string_view(Begin, First - 1 - Begin));
5903 }
5904
5905 // If we're in a context where this <template-param> refers to a
5906 // <template-arg> further ahead in the mangled name (currently just conversion
5907 // operator types), then we should only look it up in the right context.
5908 // This can only happen at the outermost level.
5909 if (PermitForwardTemplateReferences && Level == 0) {
5910 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5911 if (!ForwardRef)
5912 return nullptr;
5913 DEMANGLE_ASSERT(ForwardRef->getKind() == Node::KForwardTemplateReference,
5914 "");
5915 ForwardTemplateRefs.push_back(
5916 static_cast<ForwardTemplateReference *>(ForwardRef));
5917 return ForwardRef;
5918 }
5919
5920 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5921 Index >= TemplateParams[Level]->size()) {
5922 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5923 // list are mangled as the corresponding artificial template type parameter.
5924 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5925 // This will be popped by the ScopedTemplateParamList in
5926 // parseUnnamedTypeName.
5927 if (Level == TemplateParams.size())
5928 TemplateParams.push_back(nullptr);
5929 return make<NameType>("auto");
5930 }
5931
5932 return nullptr;
5933 }
5934
5935 return (*TemplateParams[Level])[Index];
5936}
5937
5938// <template-param-decl> ::= Ty # type parameter
5939// ::= Tk <concept name> [<template-args>] # constrained type parameter
5940// ::= Tn <type> # non-type parameter
5941// ::= Tt <template-param-decl>* E # template parameter
5942// ::= Tp <template-param-decl> # parameter pack
5943template <typename Derived, typename Alloc>
5945 TemplateParamList *Params) {
5946 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5947 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5948 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5949 if (N && Params)
5950 Params->push_back(N);
5951 return N;
5952 };
5953
5954 if (consumeIf("Ty")) {
5955 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5956 if (!Name)
5957 return nullptr;
5958 return make<TypeTemplateParamDecl>(Name);
5959 }
5960
5961 if (consumeIf("Tk")) {
5962 // We don't track enclosing template parameter levels well enough to
5963 // reliably demangle template parameter substitutions, so print an arbitrary
5964 // string in place of a parameter for now.
5965 // TODO: Track all enclosing template parameters and demangle substitutions.
5966 ScopedOverride<bool> SaveIncompleteTemplateParameterTrackingExpr(
5967 HasIncompleteTemplateParameterTracking, true);
5968 Node *Constraint = getDerived().parseName();
5969 if (!Constraint)
5970 return nullptr;
5971 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5972 if (!Name)
5973 return nullptr;
5974 return make<ConstrainedTypeTemplateParamDecl>(Constraint, Name);
5975 }
5976
5977 if (consumeIf("Tn")) {
5978 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5979 if (!Name)
5980 return nullptr;
5981 Node *Type = parseType();
5982 if (!Type)
5983 return nullptr;
5984 return make<NonTypeTemplateParamDecl>(Name, Type);
5985 }
5986
5987 if (consumeIf("Tt")) {
5988 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5989 if (!Name)
5990 return nullptr;
5991 size_t ParamsBegin = Names.size();
5992 ScopedTemplateParamList TemplateTemplateParamParams(this);
5993 Node *Requires = nullptr;
5994 while (!consumeIf('E')) {
5995 Node *P = parseTemplateParamDecl(TemplateTemplateParamParams.params());
5996 if (!P)
5997 return nullptr;
5998 Names.push_back(P);
5999 if (consumeIf('Q')) {
6000 Requires = getDerived().parseConstraintExpr();
6001 if (Requires == nullptr || !consumeIf('E'))
6002 return nullptr;
6003 break;
6004 }
6005 }
6006 NodeArray InnerParams = popTrailingNodeArray(ParamsBegin);
6007 return make<TemplateTemplateParamDecl>(Name, InnerParams, Requires);
6008 }
6009
6010 if (consumeIf("Tp")) {
6011 Node *P = parseTemplateParamDecl(Params);
6012 if (!P)
6013 return nullptr;
6014 return make<TemplateParamPackDecl>(P);
6015 }
6016
6017 return nullptr;
6018}
6019
6020// <template-arg> ::= <type> # type or template
6021// ::= X <expression> E # expression
6022// ::= <expr-primary> # simple expressions
6023// ::= J <template-arg>* E # argument pack
6024// ::= LZ <encoding> E # extension
6025// ::= <template-param-decl> <template-arg>
6026template <typename Derived, typename Alloc>
6028 switch (look()) {
6029 case 'X': {
6030 ++First;
6031 Node *Arg = getDerived().parseExpr();
6032 if (Arg == nullptr || !consumeIf('E'))
6033 return nullptr;
6034 return Arg;
6035 }
6036 case 'J': {
6037 ++First;
6038 size_t ArgsBegin = Names.size();
6039 while (!consumeIf('E')) {
6040 Node *Arg = getDerived().parseTemplateArg();
6041 if (Arg == nullptr)
6042 return nullptr;
6043 Names.push_back(Arg);
6044 }
6045 NodeArray Args = popTrailingNodeArray(ArgsBegin);
6046 return make<TemplateArgumentPack>(Args);
6047 }
6048 case 'L': {
6049 // ::= LZ <encoding> E # extension
6050 if (look(1) == 'Z') {
6051 First += 2;
6052 Node *Arg = getDerived().parseEncoding();
6053 if (Arg == nullptr || !consumeIf('E'))
6054 return nullptr;
6055 return Arg;
6056 }
6057 // ::= <expr-primary> # simple expressions
6058 return getDerived().parseExprPrimary();
6059 }
6060 case 'T': {
6061 // Either <template-param> or a <template-param-decl> <template-arg>.
6062 if (!getDerived().isTemplateParamDecl())
6063 return getDerived().parseType();
6064 Node *Param = getDerived().parseTemplateParamDecl(nullptr);
6065 if (!Param)
6066 return nullptr;
6067 Node *Arg = getDerived().parseTemplateArg();
6068 if (!Arg)
6069 return nullptr;
6070 return make<TemplateParamQualifiedArg>(Param, Arg);
6071 }
6072 default:
6073 return getDerived().parseType();
6074 }
6075}
6076
6077// <template-args> ::= I <template-arg>* [Q <requires-clause expr>] E
6078// extension, the abi says <template-arg>+
6079template <typename Derived, typename Alloc>
6080Node *
6082 if (!consumeIf('I'))
6083 return nullptr;
6084
6085 // <template-params> refer to the innermost <template-args>. Clear out any
6086 // outer args that we may have inserted into TemplateParams.
6087 if (TagTemplates) {
6088 TemplateParams.clear();
6089 TemplateParams.push_back(&OuterTemplateParams);
6090 OuterTemplateParams.clear();
6091 }
6092
6093 size_t ArgsBegin = Names.size();
6094 Node *Requires = nullptr;
6095 while (!consumeIf('E')) {
6096 if (TagTemplates) {
6097 Node *Arg = getDerived().parseTemplateArg();
6098 if (Arg == nullptr)
6099 return nullptr;
6100 Names.push_back(Arg);
6101 Node *TableEntry = Arg;
6102 if (Arg->getKind() == Node::KTemplateParamQualifiedArg) {
6103 TableEntry =
6104 static_cast<TemplateParamQualifiedArg *>(TableEntry)->getArg();
6105 }
6106 if (Arg->getKind() == Node::KTemplateArgumentPack) {
6107 TableEntry = make<ParameterPack>(
6108 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
6109 if (!TableEntry)
6110 return nullptr;
6111 }
6112 OuterTemplateParams.push_back(TableEntry);
6113 } else {
6114 Node *Arg = getDerived().parseTemplateArg();
6115 if (Arg == nullptr)
6116 return nullptr;
6117 Names.push_back(Arg);
6118 }
6119 if (consumeIf('Q')) {
6120 Requires = getDerived().parseConstraintExpr();
6121 if (!Requires || !consumeIf('E'))
6122 return nullptr;
6123 break;
6124 }
6125 }
6126 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin), Requires);
6127}
6128
6129// <mangled-name> ::= _Z <encoding>
6130// ::= <type>
6131// extension ::= ___Z <encoding> _block_invoke
6132// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
6133// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
6134template <typename Derived, typename Alloc>
6136 if (consumeIf("_Z") || consumeIf("__Z")) {
6137 Node *Encoding = getDerived().parseEncoding(ParseParams);
6138 if (Encoding == nullptr)
6139 return nullptr;
6140 if (look() == '.') {
6141 Encoding =
6142 make<DotSuffix>(Encoding, std::string_view(First, Last - First));
6143 First = Last;
6144 }
6145 if (numLeft() != 0)
6146 return nullptr;
6147 return Encoding;
6148 }
6149
6150 if (consumeIf("___Z") || consumeIf("____Z")) {
6151 Node *Encoding = getDerived().parseEncoding(ParseParams);
6152 if (Encoding == nullptr || !consumeIf("_block_invoke"))
6153 return nullptr;
6154 bool RequireNumber = consumeIf('_');
6155 if (parseNumber().empty() && RequireNumber)
6156 return nullptr;
6157 if (look() == '.')
6158 First = Last;
6159 if (numLeft() != 0)
6160 return nullptr;
6161 return make<SpecialName>("invocation function for block in ", Encoding);
6162 }
6163
6164 Node *Ty = getDerived().parseType();
6165 if (numLeft() != 0)
6166 return nullptr;
6167 return Ty;
6168}
6169
6170template <typename Alloc>
6171struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
6174};
6175
6177
6178#if defined(__clang__)
6179#pragma clang diagnostic pop
6180#endif
6181
6182#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:1313
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.