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