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.
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
425
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
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
1243enum class TemplateParamKind { Type, NonType, Template };
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 {
1252 TemplateParamKind Kind;
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) {
1264 OB += "$T";
1265 break;
1267 OB += "$N";
1268 break;
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<bool> LT(OB.TemplateTracker.InsideTemplate, true);
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<bool> LT(OB.TemplateTracker.InsideTemplate, true);
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
1681
1684protected:
1686
1689public:
1691 : ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}
1693
1694 template<typename Fn> void match(Fn F) const { F(SSK); }
1695
1696protected:
1697 bool isInstantiation() const {
1699 }
1700
1701 std::string_view getBaseName() const override {
1702 switch (SSK) {
1704 return {"allocator"};
1706 return {"basic_string"};
1708 return {"basic_string"};
1710 return {"basic_istream"};
1712 return {"basic_ostream"};
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>";
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
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<bool> LT(OB.TemplateTracker.InsideTemplate, true);
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 // If we're printing a '<' inside of a template argument, and we haven't
1889 // yet parenthesized the expression, do so now.
1890 bool ParenAll = !OB.isInParensInTemplateArgs() &&
1891 (InfixOperator == ">" || InfixOperator == ">>");
1892 if (ParenAll)
1893 OB.printOpen();
1894 // Assignment is right associative, with special LHS precedence.
1895 bool IsAssign = getPrecedence() == Prec::Assign;
1896 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1897 // No space before comma operator
1898 if (!(InfixOperator == ","))
1899 OB += " ";
1900 OB += InfixOperator;
1901 OB += " ";
1902 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1903 if (ParenAll)
1904 OB.printClose();
1905 }
1906};
1907
1908class ArraySubscriptExpr : public Node {
1909 const Node *Op1;
1910 const Node *Op2;
1911
1912public:
1913 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1914 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
1915
1916 template <typename Fn> void match(Fn F) const {
1917 F(Op1, Op2, getPrecedence());
1918 }
1919
1920 void printLeft(OutputBuffer &OB) const override {
1921 Op1->printAsOperand(OB, getPrecedence());
1922 OB.printOpen('[');
1923 Op2->printAsOperand(OB);
1924 OB.printClose(']');
1925 }
1926};
1927
1928class PostfixExpr : public Node {
1929 const Node *Child;
1930 const std::string_view Operator;
1931
1932public:
1933 PostfixExpr(const Node *Child_, std::string_view Operator_, Prec Prec_)
1934 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
1935
1936 template <typename Fn> void match(Fn F) const {
1937 F(Child, Operator, getPrecedence());
1938 }
1939
1940 void printLeft(OutputBuffer &OB) const override {
1941 Child->printAsOperand(OB, getPrecedence(), true);
1942 OB += Operator;
1943 }
1944};
1945
1946class ConditionalExpr : public Node {
1947 const Node *Cond;
1948 const Node *Then;
1949 const Node *Else;
1950
1951public:
1952 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1953 Prec Prec_)
1954 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
1955
1956 template <typename Fn> void match(Fn F) const {
1957 F(Cond, Then, Else, getPrecedence());
1958 }
1959
1960 void printLeft(OutputBuffer &OB) const override {
1961 Cond->printAsOperand(OB, getPrecedence());
1962 OB += " ? ";
1963 Then->printAsOperand(OB);
1964 OB += " : ";
1965 Else->printAsOperand(OB, Prec::Assign, true);
1966 }
1967};
1968
1969class MemberExpr : public Node {
1970 const Node *LHS;
1971 const std::string_view Kind;
1972 const Node *RHS;
1973
1974public:
1975 MemberExpr(const Node *LHS_, std::string_view Kind_, const Node *RHS_,
1976 Prec Prec_)
1977 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
1978
1979 template <typename Fn> void match(Fn F) const {
1980 F(LHS, Kind, RHS, getPrecedence());
1981 }
1982
1983 void printLeft(OutputBuffer &OB) const override {
1984 LHS->printAsOperand(OB, getPrecedence(), true);
1985 OB += Kind;
1986 RHS->printAsOperand(OB, getPrecedence(), false);
1987 }
1988};
1989
1990class SubobjectExpr : public Node {
1991 const Node *Type;
1992 const Node *SubExpr;
1993 std::string_view Offset;
1994 NodeArray UnionSelectors;
1995 bool OnePastTheEnd;
1996
1997public:
1998 SubobjectExpr(const Node *Type_, const Node *SubExpr_,
1999 std::string_view Offset_, NodeArray UnionSelectors_,
2000 bool OnePastTheEnd_)
2001 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
2002 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
2003
2004 template<typename Fn> void match(Fn F) const {
2005 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
2006 }
2007
2008 void printLeft(OutputBuffer &OB) const override {
2009 SubExpr->print(OB);
2010 OB += ".<";
2011 Type->print(OB);
2012 OB += " at offset ";
2013 if (Offset.empty()) {
2014 OB += "0";
2015 } else if (Offset[0] == 'n') {
2016 OB += "-";
2017 OB += std::string_view(Offset.data() + 1, Offset.size() - 1);
2018 } else {
2019 OB += Offset;
2020 }
2021 OB += ">";
2022 }
2023};
2024
2025class EnclosingExpr : public Node {
2026 const std::string_view Prefix;
2027 const Node *Infix;
2028 const std::string_view Postfix;
2029
2030public:
2031 EnclosingExpr(std::string_view Prefix_, const Node *Infix_,
2032 Prec Prec_ = Prec::Primary)
2033 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
2034
2035 template <typename Fn> void match(Fn F) const {
2036 F(Prefix, Infix, getPrecedence());
2037 }
2038
2039 void printLeft(OutputBuffer &OB) const override {
2040 OB += Prefix;
2041 OB.printOpen();
2042 Infix->print(OB);
2043 OB.printClose();
2044 OB += Postfix;
2045 }
2046};
2047
2048class CastExpr : public Node {
2049 // cast_kind<to>(from)
2050 const std::string_view CastKind;
2051 const Node *To;
2052 const Node *From;
2053
2054public:
2055 CastExpr(std::string_view CastKind_, const Node *To_, const Node *From_,
2056 Prec Prec_)
2057 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
2058
2059 template <typename Fn> void match(Fn F) const {
2060 F(CastKind, To, From, getPrecedence());
2061 }
2062
2063 void printLeft(OutputBuffer &OB) const override {
2064 OB += CastKind;
2065 {
2066 ScopedOverride<bool> LT(OB.TemplateTracker.InsideTemplate, true);
2067 OB += "<";
2068 OB.printLeft(*To);
2069 OB += ">";
2070 }
2071 OB.printOpen();
2072 From->printAsOperand(OB);
2073 OB.printClose();
2074 }
2075};
2076
2078 const Node *Pack;
2079
2080public:
2082 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
2083
2084 template<typename Fn> void match(Fn F) const { F(Pack); }
2085
2086 void printLeft(OutputBuffer &OB) const override {
2087 OB += "sizeof...";
2088 OB.printOpen();
2089 ParameterPackExpansion PPE(Pack);
2090 PPE.printLeft(OB);
2091 OB.printClose();
2092 }
2093};
2094
2095class CallExpr : public Node {
2096 const Node *Callee;
2097 NodeArray Args;
2098 bool IsParen; // (func)(args ...) ?
2099
2100public:
2101 CallExpr(const Node *Callee_, NodeArray Args_, bool IsParen_, Prec Prec_)
2102 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_),
2103 IsParen(IsParen_) {}
2104
2105 template <typename Fn> void match(Fn F) const {
2106 F(Callee, Args, IsParen, getPrecedence());
2107 }
2108
2109 void printLeft(OutputBuffer &OB) const override {
2110 if (IsParen)
2111 OB.printOpen();
2112 Callee->print(OB);
2113 if (IsParen)
2114 OB.printClose();
2115 OB.printOpen();
2116 Args.printWithComma(OB);
2117 OB.printClose();
2118 }
2119};
2120
2121class NewExpr : public Node {
2122 // new (expr_list) type(init_list)
2123 NodeArray ExprList;
2124 Node *Type;
2125 NodeArray InitList;
2126 bool IsGlobal; // ::operator new ?
2127 bool IsArray; // new[] ?
2128public:
2129 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
2130 bool IsArray_, Prec Prec_)
2131 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
2132 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
2133
2134 template<typename Fn> void match(Fn F) const {
2135 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
2136 }
2137
2138 void printLeft(OutputBuffer &OB) const override {
2139 if (IsGlobal)
2140 OB += "::";
2141 OB += "new";
2142 if (IsArray)
2143 OB += "[]";
2144 if (!ExprList.empty()) {
2145 OB.printOpen();
2146 ExprList.printWithComma(OB);
2147 OB.printClose();
2148 }
2149 OB += " ";
2150 Type->print(OB);
2151 if (!InitList.empty()) {
2152 OB.printOpen();
2153 InitList.printWithComma(OB);
2154 OB.printClose();
2155 }
2156 }
2157};
2158
2159class DeleteExpr : public Node {
2160 Node *Op;
2161 bool IsGlobal;
2162 bool IsArray;
2163
2164public:
2165 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
2166 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
2167 IsArray(IsArray_) {}
2168
2169 template <typename Fn> void match(Fn F) const {
2170 F(Op, IsGlobal, IsArray, getPrecedence());
2171 }
2172
2173 void printLeft(OutputBuffer &OB) const override {
2174 if (IsGlobal)
2175 OB += "::";
2176 OB += "delete";
2177 if (IsArray)
2178 OB += "[]";
2179 OB += ' ';
2180 Op->print(OB);
2181 }
2182};
2183
2184class PrefixExpr : public Node {
2185 std::string_view Prefix;
2186 Node *Child;
2187
2188public:
2189 PrefixExpr(std::string_view Prefix_, Node *Child_, Prec Prec_)
2190 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
2191
2192 template <typename Fn> void match(Fn F) const {
2193 F(Prefix, Child, getPrecedence());
2194 }
2195
2196 void printLeft(OutputBuffer &OB) const override {
2197 OB += Prefix;
2198 Child->printAsOperand(OB, getPrecedence());
2199 }
2200};
2201
2202class FunctionParam : public Node {
2203 std::string_view Number;
2204
2205public:
2206 FunctionParam(std::string_view Number_)
2207 : Node(KFunctionParam), Number(Number_) {}
2208
2209 template<typename Fn> void match(Fn F) const { F(Number); }
2210
2211 void printLeft(OutputBuffer &OB) const override {
2212 OB += "fp";
2213 OB += Number;
2214 }
2215};
2216
2217class ConversionExpr : public Node {
2218 const Node *Type;
2219 NodeArray Expressions;
2220
2221public:
2222 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2223 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
2224
2225 template <typename Fn> void match(Fn F) const {
2226 F(Type, Expressions, getPrecedence());
2227 }
2228
2229 void printLeft(OutputBuffer &OB) const override {
2230 OB.printOpen();
2231 Type->print(OB);
2232 OB.printClose();
2233 OB.printOpen();
2234 Expressions.printWithComma(OB);
2235 OB.printClose();
2236 }
2237};
2238
2240 const Node *Type;
2241 const Node *SubExpr;
2242 std::string_view Offset;
2243
2244public:
2245 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
2246 std::string_view Offset_, Prec Prec_)
2247 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2248 SubExpr(SubExpr_), Offset(Offset_) {}
2249
2250 template <typename Fn> void match(Fn F) const {
2251 F(Type, SubExpr, Offset, getPrecedence());
2252 }
2253
2254 void printLeft(OutputBuffer &OB) const override {
2255 OB.printOpen();
2256 Type->print(OB);
2257 OB.printClose();
2258 OB.printOpen();
2259 SubExpr->print(OB);
2260 OB.printClose();
2261 }
2262};
2263
2264class InitListExpr : public Node {
2265 const Node *Ty;
2266 NodeArray Inits;
2267public:
2268 InitListExpr(const Node *Ty_, NodeArray Inits_)
2269 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2270
2271 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2272
2273 void printLeft(OutputBuffer &OB) const override {
2274 if (Ty) {
2275 if (Ty->printInitListAsType(OB, Inits))
2276 return;
2277 Ty->print(OB);
2278 }
2279 OB += '{';
2280 Inits.printWithComma(OB);
2281 OB += '}';
2282 }
2283};
2284
2285class BracedExpr : public Node {
2286 const Node *Elem;
2287 const Node *Init;
2288 bool IsArray;
2289public:
2290 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2291 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2292
2293 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
2294
2295 void printLeft(OutputBuffer &OB) const override {
2296 if (IsArray) {
2297 OB += '[';
2298 Elem->print(OB);
2299 OB += ']';
2300 } else {
2301 OB += '.';
2302 Elem->print(OB);
2303 }
2304 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
2305 OB += " = ";
2306 Init->print(OB);
2307 }
2308};
2309
2310class BracedRangeExpr : public Node {
2311 const Node *First;
2312 const Node *Last;
2313 const Node *Init;
2314public:
2315 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2316 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2317
2318 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2319
2320 void printLeft(OutputBuffer &OB) const override {
2321 OB += '[';
2322 First->print(OB);
2323 OB += " ... ";
2324 Last->print(OB);
2325 OB += ']';
2326 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
2327 OB += " = ";
2328 Init->print(OB);
2329 }
2330};
2331
2332class FoldExpr : public Node {
2333 const Node *Pack, *Init;
2334 std::string_view OperatorName;
2335 bool IsLeftFold;
2336
2337public:
2338 FoldExpr(bool IsLeftFold_, std::string_view OperatorName_, const Node *Pack_,
2339 const Node *Init_)
2340 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2341 IsLeftFold(IsLeftFold_) {}
2342
2343 template<typename Fn> void match(Fn F) const {
2344 F(IsLeftFold, OperatorName, Pack, Init);
2345 }
2346
2347 void printLeft(OutputBuffer &OB) const override {
2348 auto PrintPack = [&] {
2349 OB.printOpen();
2350 ParameterPackExpansion(Pack).print(OB);
2351 OB.printClose();
2352 };
2353
2354 OB.printOpen();
2355 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2356 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2357 // Fold expr operands are cast-expressions
2358 if (!IsLeftFold || Init != nullptr) {
2359 // '(init|pack) op '
2360 if (IsLeftFold)
2361 Init->printAsOperand(OB, Prec::Cast, true);
2362 else
2363 PrintPack();
2364 OB << " " << OperatorName << " ";
2365 }
2366 OB << "...";
2367 if (IsLeftFold || Init != nullptr) {
2368 // ' op (init|pack)'
2369 OB << " " << OperatorName << " ";
2370 if (IsLeftFold)
2371 PrintPack();
2372 else
2373 Init->printAsOperand(OB, Prec::Cast, true);
2374 }
2375 OB.printClose();
2376 }
2377};
2378
2379class ThrowExpr : public Node {
2380 const Node *Op;
2381
2382public:
2383 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2384
2385 template<typename Fn> void match(Fn F) const { F(Op); }
2386
2387 void printLeft(OutputBuffer &OB) const override {
2388 OB += "throw ";
2389 Op->print(OB);
2390 }
2391};
2392
2393class BoolExpr : public Node {
2394 bool Value;
2395
2396public:
2397 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2398
2399 template<typename Fn> void match(Fn F) const { F(Value); }
2400
2401 void printLeft(OutputBuffer &OB) const override {
2402 OB += Value ? std::string_view("true") : std::string_view("false");
2403 }
2404};
2405
2406class StringLiteral : public Node {
2407 const Node *Type;
2408
2409public:
2410 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2411
2412 template<typename Fn> void match(Fn F) const { F(Type); }
2413
2414 void printLeft(OutputBuffer &OB) const override {
2415 OB += "\"<";
2416 Type->print(OB);
2417 OB += ">\"";
2418 }
2419};
2420
2421class LambdaExpr : public Node {
2422 const Node *Type;
2423
2424public:
2425 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2426
2427 template<typename Fn> void match(Fn F) const { F(Type); }
2428
2429 void printLeft(OutputBuffer &OB) const override {
2430 OB += "[]";
2431 if (Type->getKind() == KClosureTypeName)
2432 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2433 OB += "{...}";
2434 }
2435};
2436
2437class EnumLiteral : public Node {
2438 // ty(integer)
2439 const Node *Ty;
2440 std::string_view Integer;
2441
2442public:
2443 EnumLiteral(const Node *Ty_, std::string_view Integer_)
2444 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
2445
2446 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2447
2448 void printLeft(OutputBuffer &OB) const override {
2449 OB.printOpen();
2450 Ty->print(OB);
2451 OB.printClose();
2452
2453 if (Integer[0] == 'n')
2454 OB << '-' << std::string_view(Integer.data() + 1, Integer.size() - 1);
2455 else
2456 OB << Integer;
2457 }
2458};
2459
2460class IntegerLiteral : public Node {
2461 std::string_view Type;
2462 std::string_view Value;
2463
2464public:
2465 IntegerLiteral(std::string_view Type_, std::string_view Value_)
2466 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2467
2468 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2469
2470 void printLeft(OutputBuffer &OB) const override {
2471 if (Type.size() > 3) {
2472 OB.printOpen();
2473 OB += Type;
2474 OB.printClose();
2475 }
2476
2477 if (Value[0] == 'n')
2478 OB << '-' << std::string_view(Value.data() + 1, Value.size() - 1);
2479 else
2480 OB += Value;
2481
2482 if (Type.size() <= 3)
2483 OB += Type;
2484 }
2485
2486 std::string_view value() const { return Value; }
2487};
2488
2489class RequiresExpr : public Node {
2490 NodeArray Parameters;
2491 NodeArray Requirements;
2492public:
2493 RequiresExpr(NodeArray Parameters_, NodeArray Requirements_)
2494 : Node(KRequiresExpr), Parameters(Parameters_),
2495 Requirements(Requirements_) {}
2496
2497 template<typename Fn> void match(Fn F) const { F(Parameters, Requirements); }
2498
2499 void printLeft(OutputBuffer &OB) const override {
2500 OB += "requires";
2501 if (!Parameters.empty()) {
2502 OB += ' ';
2503 OB.printOpen();
2504 Parameters.printWithComma(OB);
2505 OB.printClose();
2506 }
2507 OB += ' ';
2508 OB.printOpen('{');
2509 for (const Node *Req : Requirements) {
2510 Req->print(OB);
2511 }
2512 OB += ' ';
2513 OB.printClose('}');
2514 }
2515};
2516
2517class ExprRequirement : public Node {
2518 const Node *Expr;
2519 bool IsNoexcept;
2520 const Node *TypeConstraint;
2521public:
2522 ExprRequirement(const Node *Expr_, bool IsNoexcept_,
2523 const Node *TypeConstraint_)
2524 : Node(KExprRequirement), Expr(Expr_), IsNoexcept(IsNoexcept_),
2525 TypeConstraint(TypeConstraint_) {}
2526
2527 template <typename Fn> void match(Fn F) const {
2528 F(Expr, IsNoexcept, TypeConstraint);
2529 }
2530
2531 void printLeft(OutputBuffer &OB) const override {
2532 OB += " ";
2533 if (IsNoexcept || TypeConstraint)
2534 OB.printOpen('{');
2535 Expr->print(OB);
2536 if (IsNoexcept || TypeConstraint)
2537 OB.printClose('}');
2538 if (IsNoexcept)
2539 OB += " noexcept";
2540 if (TypeConstraint) {
2541 OB += " -> ";
2542 TypeConstraint->print(OB);
2543 }
2544 OB += ';';
2545 }
2546};
2547
2548class TypeRequirement : public Node {
2549 const Node *Type;
2550public:
2551 TypeRequirement(const Node *Type_)
2552 : Node(KTypeRequirement), Type(Type_) {}
2553
2554 template <typename Fn> void match(Fn F) const { F(Type); }
2555
2556 void printLeft(OutputBuffer &OB) const override {
2557 OB += " typename ";
2558 Type->print(OB);
2559 OB += ';';
2560 }
2561};
2562
2563class NestedRequirement : public Node {
2564 const Node *Constraint;
2565public:
2566 NestedRequirement(const Node *Constraint_)
2567 : Node(KNestedRequirement), Constraint(Constraint_) {}
2568
2569 template <typename Fn> void match(Fn F) const { F(Constraint); }
2570
2571 void printLeft(OutputBuffer &OB) const override {
2572 OB += " requires ";
2573 Constraint->print(OB);
2574 OB += ';';
2575 }
2576};
2577
2578template <class Float> struct FloatData;
2579
2582 return Node::KFloatLiteral;
2583}
2584constexpr Node::Kind getFloatLiteralKind(double *) {
2585 return Node::KDoubleLiteral;
2586}
2587constexpr Node::Kind getFloatLiteralKind(long double *) {
2588 return Node::KLongDoubleLiteral;
2589}
2590}
2591
2592template <class Float> class FloatLiteralImpl : public Node {
2593 const std::string_view Contents;
2594
2595 static constexpr Kind KindForClass =
2597
2598public:
2599 FloatLiteralImpl(std::string_view Contents_)
2600 : Node(KindForClass), Contents(Contents_) {}
2601
2602 template<typename Fn> void match(Fn F) const { F(Contents); }
2603
2604 void printLeft(OutputBuffer &OB) const override {
2605 const size_t N = FloatData<Float>::mangled_size;
2606 if (Contents.size() >= N) {
2607 union {
2608 Float value;
2609 char buf[sizeof(Float)];
2610 };
2611 const char *t = Contents.data();
2612 const char *last = t + N;
2613 char *e = buf;
2614 for (; t != last; ++t, ++e) {
2615 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2616 : static_cast<unsigned>(*t - 'a' + 10);
2617 ++t;
2618 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2619 : static_cast<unsigned>(*t - 'a' + 10);
2620 *e = static_cast<char>((d1 << 4) + d0);
2621 }
2622#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2623 std::reverse(buf, e);
2624#endif
2626 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
2627 OB += std::string_view(num, n);
2628 }
2629 }
2630};
2631
2635
2636/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2637/// appropriate derived class.
2638template<typename Fn>
2639void Node::visit(Fn F) const {
2640 switch (K) {
2641#define NODE(X) \
2642 case K##X: \
2643 return F(static_cast<const X *>(this));
2644#include "ItaniumNodes.def"
2645 }
2646 DEMANGLE_ASSERT(0, "unknown mangling node kind");
2647}
2648
2649/// Determine the kind of a node from its type.
2650template<typename NodeT> struct NodeKind;
2651#define NODE(X) \
2652 template <> struct NodeKind<X> { \
2653 static constexpr Node::Kind Kind = Node::K##X; \
2654 static constexpr const char *name() { return #X; } \
2655 };
2656#include "ItaniumNodes.def"
2657
2659 auto StartPos = OB.getCurrentPosition();
2660 auto Fail = [&OB, StartPos] {
2661 OB.setCurrentPosition(StartPos);
2662 return false;
2663 };
2664
2665 OB += '"';
2666 bool LastWasNumericEscape = false;
2667 for (const Node *Element : *this) {
2668 if (Element->getKind() != Node::KIntegerLiteral)
2669 return Fail();
2670 int integer_value = 0;
2671 for (char c : static_cast<const IntegerLiteral *>(Element)->value()) {
2672 if (c < '0' || c > '9' || integer_value > 25)
2673 return Fail();
2674 integer_value *= 10;
2675 integer_value += c - '0';
2676 }
2677 if (integer_value > 255)
2678 return Fail();
2679
2680 // Insert a `""` to avoid accidentally extending a numeric escape.
2681 if (LastWasNumericEscape) {
2682 if ((integer_value >= '0' && integer_value <= '9') ||
2683 (integer_value >= 'a' && integer_value <= 'f') ||
2684 (integer_value >= 'A' && integer_value <= 'F')) {
2685 OB += "\"\"";
2686 }
2687 }
2688
2689 LastWasNumericEscape = false;
2690
2691 // Determine how to print this character.
2692 switch (integer_value) {
2693 case '\a':
2694 OB += "\\a";
2695 break;
2696 case '\b':
2697 OB += "\\b";
2698 break;
2699 case '\f':
2700 OB += "\\f";
2701 break;
2702 case '\n':
2703 OB += "\\n";
2704 break;
2705 case '\r':
2706 OB += "\\r";
2707 break;
2708 case '\t':
2709 OB += "\\t";
2710 break;
2711 case '\v':
2712 OB += "\\v";
2713 break;
2714
2715 case '"':
2716 OB += "\\\"";
2717 break;
2718 case '\\':
2719 OB += "\\\\";
2720 break;
2721
2722 default:
2723 // We assume that the character is ASCII, and use a numeric escape for all
2724 // remaining non-printable ASCII characters.
2725 if (integer_value < 32 || integer_value == 127) {
2726 constexpr char Hex[] = "0123456789ABCDEF";
2727 OB += '\\';
2728 if (integer_value > 7)
2729 OB += 'x';
2730 if (integer_value >= 16)
2731 OB += Hex[integer_value >> 4];
2732 OB += Hex[integer_value & 0xF];
2733 LastWasNumericEscape = true;
2734 break;
2735 }
2736
2737 // Assume all remaining characters are directly printable.
2738 OB += (char)integer_value;
2739 break;
2740 }
2741 }
2742 OB += '"';
2743 return true;
2744}
2745
2746template <typename Derived, typename Alloc> struct AbstractManglingParser {
2747 const char *First;
2748 const char *Last;
2749
2750 // Name stack, this is used by the parser to hold temporary names that were
2751 // parsed. The parser collapses multiple names into new nodes to construct
2752 // the AST. Once the parser is finished, names.size() == 1.
2754
2755 // Substitution table. Itanium supports name substitutions as a means of
2756 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2757 // table.
2759
2760 // A list of template argument values corresponding to a template parameter
2761 // list.
2763
2765 AbstractManglingParser *Parser;
2766 size_t OldNumTemplateParamLists;
2767 TemplateParamList Params;
2768
2769 public:
2771 : Parser(TheParser),
2772 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
2773 Parser->TemplateParams.push_back(&Params);
2774 }
2776 DEMANGLE_ASSERT(Parser->TemplateParams.size() >= OldNumTemplateParamLists,
2777 "");
2778 Parser->TemplateParams.shrinkToSize(OldNumTemplateParamLists);
2779 }
2780 TemplateParamList *params() { return &Params; }
2781 };
2782
2783 // Template parameter table. Like the above, but referenced like "T42_".
2784 // This has a smaller size compared to Subs and Names because it can be
2785 // stored on the stack.
2787
2788 // Lists of template parameters indexed by template parameter depth,
2789 // referenced like "TL2_4_". If nonempty, element 0 is always
2790 // OuterTemplateParams; inner elements are always template parameter lists of
2791 // lambda expressions. For a generic lambda with no explicit template
2792 // parameter list, the corresponding parameter list pointer will be null.
2794
2796 AbstractManglingParser *Parser;
2797 decltype(TemplateParams) OldParams;
2798 decltype(OuterTemplateParams) OldOuterParams;
2799
2800 public:
2801 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
2802 OldParams = std::move(Parser->TemplateParams);
2803 OldOuterParams = std::move(Parser->OuterTemplateParams);
2804 Parser->TemplateParams.clear();
2805 Parser->OuterTemplateParams.clear();
2806 }
2808 Parser->TemplateParams = std::move(OldParams);
2809 Parser->OuterTemplateParams = std::move(OldOuterParams);
2810 }
2811 };
2812
2813 // Set of unresolved forward <template-param> references. These can occur in a
2814 // conversion operator's type, and are resolved in the enclosing <encoding>.
2816
2820 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2821
2823
2825
2826 AbstractManglingParser(const char *First_, const char *Last_)
2827 : First(First_), Last(Last_) {}
2828
2829 Derived &getDerived() { return static_cast<Derived &>(*this); }
2830
2831 void reset(const char *First_, const char *Last_) {
2832 First = First_;
2833 Last = Last_;
2834 Names.clear();
2835 Subs.clear();
2836 TemplateParams.clear();
2837 ParsingLambdaParamsAtLevel = (size_t)-1;
2840 for (int I = 0; I != 3; ++I)
2842 ASTAllocator.reset();
2843 }
2844
2845 template <class T, class... Args> Node *make(Args &&... args) {
2846 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2847 }
2848
2849 template <class It> NodeArray makeNodeArray(It begin, It end) {
2850 size_t sz = static_cast<size_t>(end - begin);
2851 void *mem = ASTAllocator.allocateNodeArray(sz);
2852 Node **data = new (mem) Node *[sz];
2853 std::copy(begin, end, data);
2854 return NodeArray(data, sz);
2855 }
2856
2857 NodeArray popTrailingNodeArray(size_t FromPosition) {
2858 DEMANGLE_ASSERT(FromPosition <= Names.size(), "");
2859 NodeArray res =
2860 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2861 Names.shrinkToSize(FromPosition);
2862 return res;
2863 }
2864
2865 bool consumeIf(std::string_view S) {
2866 if (starts_with(std::string_view(First, Last - First), S)) {
2867 First += S.size();
2868 return true;
2869 }
2870 return false;
2871 }
2872
2873 bool consumeIf(char C) {
2874 if (First != Last && *First == C) {
2875 ++First;
2876 return true;
2877 }
2878 return false;
2879 }
2880
2881 char consume() { return First != Last ? *First++ : '\0'; }
2882
2883 char look(unsigned Lookahead = 0) const {
2884 if (static_cast<size_t>(Last - First) <= Lookahead)
2885 return '\0';
2886 return First[Lookahead];
2887 }
2888
2889 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2890
2891 std::string_view parseNumber(bool AllowNegative = false);
2893 bool parsePositiveInteger(size_t *Out);
2894 std::string_view parseBareSourceName();
2895
2896 bool parseSeqId(size_t *Out);
2900 Node *parseTemplateArgs(bool TagTemplates = false);
2902
2904 return look() == 'T' &&
2905 std::string_view("yptnk").find(look(1)) != std::string_view::npos;
2906 }
2907
2908 /// Parse the <expression> production.
2910 Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);
2911 Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);
2912 Node *parseIntegerLiteral(std::string_view Lit);
2914 template <class Float> Node *parseFloatingLiteral();
2923
2924 /// Parse the <type> production.
2933
2934 Node *parseEncoding(bool ParseParams = true);
2937
2938 /// Holds some extra information about a <name> that is being parsed. This
2939 /// information is only pertinent if the <name> refers to an <encoding>.
2951
2953 size_t I = State.ForwardTemplateRefsBegin;
2954 size_t E = ForwardTemplateRefs.size();
2955 for (; I < E; ++I) {
2956 size_t Idx = ForwardTemplateRefs[I]->Index;
2957 if (TemplateParams.empty() || !TemplateParams[0] ||
2958 Idx >= TemplateParams[0]->size())
2959 return true;
2960 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
2961 }
2962 ForwardTemplateRefs.shrinkToSize(State.ForwardTemplateRefsBegin);
2963 return false;
2964 }
2965
2966 /// Parse the <name> production>
2967 Node *parseName(NameState *State = nullptr);
2968 Node *parseLocalName(NameState *State);
2969 Node *parseOperatorName(NameState *State);
2971 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
2972 Node *parseUnnamedTypeName(NameState *State);
2973 Node *parseSourceName(NameState *State);
2974 Node *parseUnscopedName(NameState *State, bool *isSubstName);
2975 Node *parseNestedName(NameState *State);
2976 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2977
2979
2981 enum OIKind : unsigned char {
2982 Prefix, // Prefix unary: @ expr
2983 Postfix, // Postfix unary: expr @
2984 Binary, // Binary: lhs @ rhs
2985 Array, // Array index: lhs [ rhs ]
2986 Member, // Member access: lhs @ rhs
2987 New, // New
2988 Del, // Delete
2989 Call, // Function call: expr (expr*)
2990 CCast, // C cast: (type)expr
2991 Conditional, // Conditional: expr ? expr : expr
2992 NameOnly, // Overload only, not allowed in expression.
2993 // Below do not have operator names
2994 NamedCast, // Named cast, @<type>(expr)
2995 OfIdOp, // alignof, sizeof, typeid
2996
2998 };
2999 char Enc[2]; // Encoding
3000 OIKind Kind; // Kind of operator
3001 bool Flag : 1; // Entry-specific flag
3002 Node::Prec Prec : 7; // Precedence
3003 const char *Name; // Spelling
3004
3005 public:
3006 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
3007 const char *N)
3008 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
3009
3010 public:
3011 bool operator<(const OperatorInfo &Other) const {
3012 return *this < Other.Enc;
3013 }
3014 bool operator<(const char *Peek) const {
3015 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
3016 }
3017 bool operator==(const char *Peek) const {
3018 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
3019 }
3020 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
3021
3022 public:
3023 std::string_view getSymbol() const {
3024 std::string_view Res = Name;
3025 if (Kind < Unnameable) {
3026 DEMANGLE_ASSERT(starts_with(Res, "operator"),
3027 "operator name does not start with 'operator'");
3028 Res.remove_prefix(sizeof("operator") - 1);
3029 if (starts_with(Res, ' '))
3030 Res.remove_prefix(1);
3031 }
3032 return Res;
3033 }
3034 std::string_view getName() const { return Name; }
3035 OIKind getKind() const { return Kind; }
3036 bool getFlag() const { return Flag; }
3037 Node::Prec getPrecedence() const { return Prec; }
3038 };
3039 static const OperatorInfo Ops[];
3040 static const size_t NumOps;
3041 const OperatorInfo *parseOperatorEncoding();
3042
3043 /// Parse the <unresolved-name> production.
3049
3050 /// Top-level entry point into the parser.
3051 Node *parse(bool ParseParams = true);
3052};
3053
3054DEMANGLE_ABI const char *parse_discriminator(const char *first,
3055 const char *last);
3056
3057// <name> ::= <nested-name> // N
3058// ::= <local-name> # See Scope Encoding below // Z
3059// ::= <unscoped-template-name> <template-args>
3060// ::= <unscoped-name>
3061//
3062// <unscoped-template-name> ::= <unscoped-name>
3063// ::= <substitution>
3064template <typename Derived, typename Alloc>
3066 if (look() == 'N')
3067 return getDerived().parseNestedName(State);
3068 if (look() == 'Z')
3069 return getDerived().parseLocalName(State);
3070
3071 Node *Result = nullptr;
3072 bool IsSubst = false;
3073
3074 Result = getDerived().parseUnscopedName(State, &IsSubst);
3075 if (!Result)
3076 return nullptr;
3077
3078 if (look() == 'I') {
3079 // ::= <unscoped-template-name> <template-args>
3080 if (!IsSubst)
3081 // An unscoped-template-name is substitutable.
3082 Subs.push_back(Result);
3083 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
3084 if (TA == nullptr)
3085 return nullptr;
3086 if (State)
3087 State->EndsWithTemplateArgs = true;
3088 Result = make<NameWithTemplateArgs>(Result, TA);
3089 } else if (IsSubst) {
3090 // The substitution case must be followed by <template-args>.
3091 return nullptr;
3092 }
3093
3094 return Result;
3095}
3096
3097// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
3098// := Z <function encoding> E s [<discriminator>]
3099// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
3100template <typename Derived, typename Alloc>
3102 if (!consumeIf('Z'))
3103 return nullptr;
3104 Node *Encoding = getDerived().parseEncoding();
3105 if (Encoding == nullptr || !consumeIf('E'))
3106 return nullptr;
3107
3108 if (consumeIf('s')) {
3110 auto *StringLitName = make<NameType>("string literal");
3111 if (!StringLitName)
3112 return nullptr;
3113 return make<LocalName>(Encoding, StringLitName);
3114 }
3115
3116 // The template parameters of the inner name are unrelated to those of the
3117 // enclosing context.
3118 SaveTemplateParams SaveTemplateParamsScope(this);
3119
3120 if (consumeIf('d')) {
3121 parseNumber(true);
3122 if (!consumeIf('_'))
3123 return nullptr;
3124 Node *N = getDerived().parseName(State);
3125 if (N == nullptr)
3126 return nullptr;
3127 return make<LocalName>(Encoding, N);
3128 }
3129
3130 Node *Entity = getDerived().parseName(State);
3131 if (Entity == nullptr)
3132 return nullptr;
3134 return make<LocalName>(Encoding, Entity);
3135}
3136
3137// <unscoped-name> ::= <unqualified-name>
3138// ::= St <unqualified-name> # ::std::
3139// [*] extension
3140template <typename Derived, typename Alloc>
3141Node *
3143 bool *IsSubst) {
3144
3145 Node *Std = nullptr;
3146 if (consumeIf("St")) {
3147 Std = make<NameType>("std");
3148 if (Std == nullptr)
3149 return nullptr;
3150 }
3151
3152 Node *Res = nullptr;
3153 ModuleName *Module = nullptr;
3154 if (look() == 'S') {
3155 Node *S = getDerived().parseSubstitution();
3156 if (!S)
3157 return nullptr;
3158 if (S->getKind() == Node::KModuleName)
3159 Module = static_cast<ModuleName *>(S);
3160 else if (IsSubst && Std == nullptr) {
3161 Res = S;
3162 *IsSubst = true;
3163 } else {
3164 return nullptr;
3165 }
3166 }
3167
3168 if (Res == nullptr || Std != nullptr) {
3169 Res = getDerived().parseUnqualifiedName(State, Std, Module);
3170 }
3171
3172 return Res;
3173}
3174
3175// <unqualified-name> ::= [<module-name>] F? L? <operator-name> [<abi-tags>]
3176// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
3177// ::= [<module-name>] F? L? <source-name> [<abi-tags>]
3178// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
3179// # structured binding declaration
3180// ::= [<module-name>] L? DC <source-name>+ E
3181template <typename Derived, typename Alloc>
3183 NameState *State, Node *Scope, ModuleName *Module) {
3185 return nullptr;
3186
3187 bool IsMemberLikeFriend = Scope && consumeIf('F');
3188
3189 consumeIf('L');
3190
3191 Node *Result;
3192 if (look() >= '1' && look() <= '9') {
3193 Result = getDerived().parseSourceName(State);
3194 } else if (look() == 'U') {
3195 Result = getDerived().parseUnnamedTypeName(State);
3196 } else if (consumeIf("DC")) {
3197 // Structured binding
3198 size_t BindingsBegin = Names.size();
3199 do {
3200 Node *Binding = getDerived().parseSourceName(State);
3201 if (Binding == nullptr)
3202 return nullptr;
3203 Names.push_back(Binding);
3204 } while (!consumeIf('E'));
3205 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
3206 } else if (look() == 'C' || look() == 'D') {
3207 // A <ctor-dtor-name>.
3208 if (Scope == nullptr || Module != nullptr)
3209 return nullptr;
3210 Result = getDerived().parseCtorDtorName(Scope, State);
3211 } else {
3212 Result = getDerived().parseOperatorName(State);
3213 }
3214
3215 if (Result != nullptr && Module != nullptr)
3216 Result = make<ModuleEntity>(Module, Result);
3217 if (Result != nullptr)
3218 Result = getDerived().parseAbiTags(Result);
3219 if (Result != nullptr && IsMemberLikeFriend)
3220 Result = make<MemberLikeFriendName>(Scope, Result);
3221 else if (Result != nullptr && Scope != nullptr)
3222 Result = make<NestedName>(Scope, Result);
3223
3224 return Result;
3225}
3226
3227// <module-name> ::= <module-subname>
3228// ::= <module-name> <module-subname>
3229// ::= <substitution> # passed in by caller
3230// <module-subname> ::= W <source-name>
3231// ::= W P <source-name>
3232template <typename Derived, typename Alloc>
3234 ModuleName *&Module) {
3235 while (consumeIf('W')) {
3236 bool IsPartition = consumeIf('P');
3237 Node *Sub = getDerived().parseSourceName(nullptr);
3238 if (!Sub)
3239 return true;
3240 Module =
3241 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
3242 Subs.push_back(Module);
3243 }
3244
3245 return false;
3246}
3247
3248// <unnamed-type-name> ::= Ut [<nonnegative number>] _
3249// ::= <closure-type-name>
3250//
3251// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
3252//
3253// <lambda-sig> ::= <template-param-decl>* [Q <requires-clause expression>]
3254// <parameter type>+ # or "v" if the lambda has no parameters
3255template <typename Derived, typename Alloc>
3256Node *
3258 // <template-params> refer to the innermost <template-args>. Clear out any
3259 // outer args that we may have inserted into TemplateParams.
3260 if (State != nullptr)
3261 TemplateParams.clear();
3262
3263 if (consumeIf("Ut")) {
3264 std::string_view Count = parseNumber();
3265 if (!consumeIf('_'))
3266 return nullptr;
3267 return make<UnnamedTypeName>(Count);
3268 }
3269 if (consumeIf("Ul")) {
3271 TemplateParams.size());
3272 ScopedTemplateParamList LambdaTemplateParams(this);
3273
3274 size_t ParamsBegin = Names.size();
3275 while (getDerived().isTemplateParamDecl()) {
3276 Node *T =
3277 getDerived().parseTemplateParamDecl(LambdaTemplateParams.params());
3278 if (T == nullptr)
3279 return nullptr;
3280 Names.push_back(T);
3281 }
3282 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
3283
3284 // FIXME: If TempParams is empty and none of the function parameters
3285 // includes 'auto', we should remove LambdaTemplateParams from the
3286 // TemplateParams list. Unfortunately, we don't find out whether there are
3287 // any 'auto' parameters until too late in an example such as:
3288 //
3289 // template<typename T> void f(
3290 // decltype([](decltype([]<typename T>(T v) {}),
3291 // auto) {})) {}
3292 // template<typename T> void f(
3293 // decltype([](decltype([]<typename T>(T w) {}),
3294 // int) {})) {}
3295 //
3296 // Here, the type of v is at level 2 but the type of w is at level 1. We
3297 // don't find this out until we encounter the type of the next parameter.
3298 //
3299 // However, compilers can't actually cope with the former example in
3300 // practice, and it's likely to be made ill-formed in future, so we don't
3301 // need to support it here.
3302 //
3303 // If we encounter an 'auto' in the function parameter types, we will
3304 // recreate a template parameter scope for it, but any intervening lambdas
3305 // will be parsed in the 'wrong' template parameter depth.
3306 if (TempParams.empty())
3307 TemplateParams.pop_back();
3308
3309 Node *Requires1 = nullptr;
3310 if (consumeIf('Q')) {
3311 Requires1 = getDerived().parseConstraintExpr();
3312 if (Requires1 == nullptr)
3313 return nullptr;
3314 }
3315
3316 if (!consumeIf("v")) {
3317 do {
3318 Node *P = getDerived().parseType();
3319 if (P == nullptr)
3320 return nullptr;
3321 Names.push_back(P);
3322 } while (look() != 'E' && look() != 'Q');
3323 }
3324 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3325
3326 Node *Requires2 = nullptr;
3327 if (consumeIf('Q')) {
3328 Requires2 = getDerived().parseConstraintExpr();
3329 if (Requires2 == nullptr)
3330 return nullptr;
3331 }
3332
3333 if (!consumeIf('E'))
3334 return nullptr;
3335
3336 std::string_view Count = parseNumber();
3337 if (!consumeIf('_'))
3338 return nullptr;
3339 return make<ClosureTypeName>(TempParams, Requires1, Params, Requires2,
3340 Count);
3341 }
3342 if (consumeIf("Ub")) {
3343 (void)parseNumber();
3344 if (!consumeIf('_'))
3345 return nullptr;
3346 return make<NameType>("'block-literal'");
3347 }
3348 return nullptr;
3349}
3350
3351// <source-name> ::= <positive length number> <identifier>
3352template <typename Derived, typename Alloc>
3354 size_t Length = 0;
3355 if (parsePositiveInteger(&Length))
3356 return nullptr;
3357 if (numLeft() < Length || Length == 0)
3358 return nullptr;
3359 std::string_view Name(First, Length);
3360 First += Length;
3361 if (starts_with(Name, "_GLOBAL__N"))
3362 return make<NameType>("(anonymous namespace)");
3363 return make<NameType>(Name);
3364}
3365
3366// Operator encodings
3367template <typename Derived, typename Alloc>
3368const typename AbstractManglingParser<
3369 Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,
3371 // Keep ordered by encoding
3372 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
3373 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
3374 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
3375 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
3376 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
3377 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},
3378 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
3379 "operator co_await"},
3380 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},
3381 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
3382 {"cl", OperatorInfo::Call, /*Paren*/ false, Node::Prec::Postfix,
3383 "operator()"},
3384 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
3385 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
3386 {"cp", OperatorInfo::Call, /*Paren*/ true, Node::Prec::Postfix,
3387 "operator()"},
3388 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast
3389 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
3390 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
3391 "operator delete[]"},
3392 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},
3393 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
3394 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
3395 "operator delete"},
3396 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3397 "operator.*"},
3398 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
3399 "operator."},
3400 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
3401 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
3402 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
3403 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
3404 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
3405 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
3406 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
3407 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
3408 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
3409 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
3410 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
3411 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
3412 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
3413 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
3414 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3415 "operator*"},
3416 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
3417 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
3418 "operator new[]"},
3419 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
3420 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
3421 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
3422 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},
3423 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
3424 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
3425 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
3426 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
3427 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
3428 {"pm", OperatorInfo::Member, /*Named*/ true, Node::Prec::PtrMem,
3429 "operator->*"},
3430 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
3431 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
3432 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
3433 "operator->"},
3434 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
3435 "operator?"},
3436 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
3437 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
3438 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3439 "reinterpret_cast"},
3440 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3441 "operator%"},
3442 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3443 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},
3444 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3445 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3446 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},
3447 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3448 "typeid "},
3449 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
3450};
3451template <typename Derived, typename Alloc>
3453 sizeof(Ops[0]);
3454
3455// If the next 2 chars are an operator encoding, consume them and return their
3456// OperatorInfo. Otherwise return nullptr.
3457template <typename Derived, typename Alloc>
3460 if (numLeft() < 2)
3461 return nullptr;
3462
3463 // We can't use lower_bound as that can link to symbols in the C++ library,
3464 // and this must remain independent of that.
3465 size_t lower = 0u, upper = NumOps - 1; // Inclusive bounds.
3466 while (upper != lower) {
3467 size_t middle = (upper + lower) / 2;
3468 if (Ops[middle] < First)
3469 lower = middle + 1;
3470 else
3471 upper = middle;
3472 }
3473 if (Ops[lower] != First)
3474 return nullptr;
3475
3476 First += 2;
3477 return &Ops[lower];
3478}
3479
3480// <operator-name> ::= See parseOperatorEncoding()
3481// ::= li <source-name> # operator ""
3482// ::= v <digit> <source-name> # vendor extended operator
3483template <typename Derived, typename Alloc>
3484Node *
3486 if (const auto *Op = parseOperatorEncoding()) {
3487 if (Op->getKind() == OperatorInfo::CCast) {
3488 // ::= cv <type> # (cast)
3489 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);
3490 // If we're parsing an encoding, State != nullptr and the conversion
3491 // operators' <type> could have a <template-param> that refers to some
3492 // <template-arg>s further ahead in the mangled name.
3495 State != nullptr);
3496 Node *Ty = getDerived().parseType();
3497 if (Ty == nullptr)
3498 return nullptr;
3499 if (State) State->CtorDtorConversion = true;
3501 }
3502
3503 if (Op->getKind() >= OperatorInfo::Unnameable)
3504 /* Not a nameable operator. */
3505 return nullptr;
3506 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3507 /* Not a nameable MemberExpr */
3508 return nullptr;
3509
3510 return make<NameType>(Op->getName());
3511 }
3512
3513 if (consumeIf("li")) {
3514 // ::= li <source-name> # operator ""
3515 Node *SN = getDerived().parseSourceName(State);
3516 if (SN == nullptr)
3517 return nullptr;
3518 return make<LiteralOperator>(SN);
3519 }
3520
3521 if (consumeIf('v')) {
3522 // ::= v <digit> <source-name> # vendor extended operator
3523 if (look() >= '0' && look() <= '9') {
3524 First++;
3525 Node *SN = getDerived().parseSourceName(State);
3526 if (SN == nullptr)
3527 return nullptr;
3529 }
3530 return nullptr;
3531 }
3532
3533 return nullptr;
3534}
3535
3536// <ctor-dtor-name> ::= C1 # complete object constructor
3537// ::= C2 # base object constructor
3538// ::= C3 # complete object allocating constructor
3539// extension ::= C4 # gcc old-style "[unified]" constructor
3540// extension ::= C5 # the COMDAT used for ctors
3541// ::= D0 # deleting destructor
3542// ::= D1 # complete object destructor
3543// ::= D2 # base object destructor
3544// extension ::= D4 # gcc old-style "[unified]" destructor
3545// extension ::= D5 # the COMDAT used for dtors
3546template <typename Derived, typename Alloc>
3547Node *
3549 NameState *State) {
3550 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3551 // Expand the special substitution.
3553 static_cast<SpecialSubstitution *>(SoFar));
3554 if (!SoFar)
3555 return nullptr;
3556 }
3557
3558 if (consumeIf('C')) {
3559 bool IsInherited = consumeIf('I');
3560 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3561 look() != '5')
3562 return nullptr;
3563 int Variant = look() - '0';
3564 ++First;
3565 if (State) State->CtorDtorConversion = true;
3566 if (IsInherited) {
3567 if (getDerived().parseName(State) == nullptr)
3568 return nullptr;
3569 }
3570 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
3571 }
3572
3573 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3574 look(1) == '4' || look(1) == '5')) {
3575 int Variant = look(1) - '0';
3576 First += 2;
3577 if (State) State->CtorDtorConversion = true;
3578 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
3579 }
3580
3581 return nullptr;
3582}
3583
3584// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3585// <unqualified-name> E
3586// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3587// <template-args> E
3588//
3589// <prefix> ::= <prefix> <unqualified-name>
3590// ::= <template-prefix> <template-args>
3591// ::= <template-param>
3592// ::= <decltype>
3593// ::= # empty
3594// ::= <substitution>
3595// ::= <prefix> <data-member-prefix>
3596// [*] extension
3597//
3598// <data-member-prefix> := <member source-name> [<template-args>] M
3599//
3600// <template-prefix> ::= <prefix> <template unqualified-name>
3601// ::= <template-param>
3602// ::= <substitution>
3603template <typename Derived, typename Alloc>
3604Node *
3606 if (!consumeIf('N'))
3607 return nullptr;
3608
3609 // 'H' specifies that the encoding that follows
3610 // has an explicit object parameter.
3611 if (!consumeIf('H')) {
3612 Qualifiers CVTmp = parseCVQualifiers();
3613 if (State)
3614 State->CVQualifiers = CVTmp;
3615
3616 if (consumeIf('O')) {
3617 if (State)
3618 State->ReferenceQualifier = FrefQualRValue;
3619 } else if (consumeIf('R')) {
3620 if (State)
3621 State->ReferenceQualifier = FrefQualLValue;
3622 } else {
3623 if (State)
3624 State->ReferenceQualifier = FrefQualNone;
3625 }
3626 } else if (State) {
3627 State->HasExplicitObjectParameter = true;
3628 }
3629
3630 Node *SoFar = nullptr;
3631 while (!consumeIf('E')) {
3632 if (State)
3633 // Only set end-with-template on the case that does that.
3634 State->EndsWithTemplateArgs = false;
3635
3636 if (look() == 'T') {
3637 // ::= <template-param>
3638 if (SoFar != nullptr)
3639 return nullptr; // Cannot have a prefix.
3640 SoFar = getDerived().parseTemplateParam();
3641 } else if (look() == 'I') {
3642 // ::= <template-prefix> <template-args>
3643 if (SoFar == nullptr)
3644 return nullptr; // Must have a prefix.
3645 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
3646 if (TA == nullptr)
3647 return nullptr;
3648 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3649 // Semantically <template-args> <template-args> cannot be generated by a
3650 // C++ entity. There will always be [something like] a name between
3651 // them.
3652 return nullptr;
3653 if (State)
3654 State->EndsWithTemplateArgs = true;
3655 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3656 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3657 // ::= <decltype>
3658 if (SoFar != nullptr)
3659 return nullptr; // Cannot have a prefix.
3660 SoFar = getDerived().parseDecltype();
3661 } else {
3662 ModuleName *Module = nullptr;
3663
3664 if (look() == 'S') {
3665 // ::= <substitution>
3666 Node *S = nullptr;
3667 if (look(1) == 't') {
3668 First += 2;
3669 S = make<NameType>("std");
3670 } else {
3671 S = getDerived().parseSubstitution();
3672 }
3673 if (!S)
3674 return nullptr;
3675 if (S->getKind() == Node::KModuleName) {
3676 Module = static_cast<ModuleName *>(S);
3677 } else if (SoFar != nullptr) {
3678 return nullptr; // Cannot have a prefix.
3679 } else {
3680 SoFar = S;
3681 continue; // Do not push a new substitution.
3682 }
3683 }
3684
3685 // ::= [<prefix>] <unqualified-name>
3686 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
3687 }
3688
3689 if (SoFar == nullptr)
3690 return nullptr;
3691 Subs.push_back(SoFar);
3692
3693 // No longer used.
3694 // <data-member-prefix> := <member source-name> [<template-args>] M
3695 consumeIf('M');
3696 }
3697
3698 if (SoFar == nullptr || Subs.empty())
3699 return nullptr;
3700
3701 Subs.pop_back();
3702 return SoFar;
3703}
3704
3705// <simple-id> ::= <source-name> [ <template-args> ]
3706template <typename Derived, typename Alloc>
3708 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
3709 if (SN == nullptr)
3710 return nullptr;
3711 if (look() == 'I') {
3712 Node *TA = getDerived().parseTemplateArgs();
3713 if (TA == nullptr)
3714 return nullptr;
3715 return make<NameWithTemplateArgs>(SN, TA);
3716 }
3717 return SN;
3718}
3719
3720// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3721// ::= <simple-id> # e.g., ~A<2*N>
3722template <typename Derived, typename Alloc>
3724 Node *Result;
3725 if (std::isdigit(look()))
3726 Result = getDerived().parseSimpleId();
3727 else
3728 Result = getDerived().parseUnresolvedType();
3729 if (Result == nullptr)
3730 return nullptr;
3731 return make<DtorName>(Result);
3732}
3733
3734// <unresolved-type> ::= <template-param>
3735// ::= <decltype>
3736// ::= <substitution>
3737template <typename Derived, typename Alloc>
3739 if (look() == 'T') {
3740 Node *TP = getDerived().parseTemplateParam();
3741 if (TP == nullptr)
3742 return nullptr;
3743 Subs.push_back(TP);
3744 return TP;
3745 }
3746 if (look() == 'D') {
3747 Node *DT = getDerived().parseDecltype();
3748 if (DT == nullptr)
3749 return nullptr;
3750 Subs.push_back(DT);
3751 return DT;
3752 }
3753 return getDerived().parseSubstitution();
3754}
3755
3756// <base-unresolved-name> ::= <simple-id> # unresolved name
3757// extension ::= <operator-name> # unresolved operator-function-id
3758// extension ::= <operator-name> <template-args> # unresolved operator template-id
3759// ::= on <operator-name> # unresolved operator-function-id
3760// ::= on <operator-name> <template-args> # unresolved operator template-id
3761// ::= dn <destructor-name> # destructor or pseudo-destructor;
3762// # e.g. ~X or ~X<N-1>
3763template <typename Derived, typename Alloc>
3765 if (std::isdigit(look()))
3766 return getDerived().parseSimpleId();
3767
3768 if (consumeIf("dn"))
3769 return getDerived().parseDestructorName();
3770
3771 consumeIf("on");
3772
3773 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
3774 if (Oper == nullptr)
3775 return nullptr;
3776 if (look() == 'I') {
3777 Node *TA = getDerived().parseTemplateArgs();
3778 if (TA == nullptr)
3779 return nullptr;
3780 return make<NameWithTemplateArgs>(Oper, TA);
3781 }
3782 return Oper;
3783}
3784
3785// <unresolved-name>
3786// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3787// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3788// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3789// # A::x, N::y, A<T>::z; "gs" means leading "::"
3790// [gs] has been parsed by caller.
3791// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3792// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3793// # T::N::x /decltype(p)::N::x
3794// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3795//
3796// <unresolved-qualifier-level> ::= <simple-id>
3797template <typename Derived, typename Alloc>
3799 Node *SoFar = nullptr;
3800
3801 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3802 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3803 if (consumeIf("srN")) {
3804 SoFar = getDerived().parseUnresolvedType();
3805 if (SoFar == nullptr)
3806 return nullptr;
3807
3808 if (look() == 'I') {
3809 Node *TA = getDerived().parseTemplateArgs();
3810 if (TA == nullptr)
3811 return nullptr;
3812 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3813 if (!SoFar)
3814 return nullptr;
3815 }
3816
3817 while (!consumeIf('E')) {
3818 Node *Qual = getDerived().parseSimpleId();
3819 if (Qual == nullptr)
3820 return nullptr;
3821 SoFar = make<QualifiedName>(SoFar, Qual);
3822 if (!SoFar)
3823 return nullptr;
3824 }
3825
3826 Node *Base = getDerived().parseBaseUnresolvedName();
3827 if (Base == nullptr)
3828 return nullptr;
3829 return make<QualifiedName>(SoFar, Base);
3830 }
3831
3832 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3833 if (!consumeIf("sr")) {
3834 SoFar = getDerived().parseBaseUnresolvedName();
3835 if (SoFar == nullptr)
3836 return nullptr;
3837 if (Global)
3838 SoFar = make<GlobalQualifiedName>(SoFar);
3839 return SoFar;
3840 }
3841
3842 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3843 if (std::isdigit(look())) {
3844 do {
3845 Node *Qual = getDerived().parseSimpleId();
3846 if (Qual == nullptr)
3847 return nullptr;
3848 if (SoFar)
3849 SoFar = make<QualifiedName>(SoFar, Qual);
3850 else if (Global)
3851 SoFar = make<GlobalQualifiedName>(Qual);
3852 else
3853 SoFar = Qual;
3854 if (!SoFar)
3855 return nullptr;
3856 } while (!consumeIf('E'));
3857 }
3858 // sr <unresolved-type> <base-unresolved-name>
3859 // sr <unresolved-type> <template-args> <base-unresolved-name>
3860 else {
3861 SoFar = getDerived().parseUnresolvedType();
3862 if (SoFar == nullptr)
3863 return nullptr;
3864
3865 if (look() == 'I') {
3866 Node *TA = getDerived().parseTemplateArgs();
3867 if (TA == nullptr)
3868 return nullptr;
3869 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
3870 if (!SoFar)
3871 return nullptr;
3872 }
3873 }
3874
3875 DEMANGLE_ASSERT(SoFar != nullptr, "");
3876
3877 Node *Base = getDerived().parseBaseUnresolvedName();
3878 if (Base == nullptr)
3879 return nullptr;
3880 return make<QualifiedName>(SoFar, Base);
3881}
3882
3883// <abi-tags> ::= <abi-tag> [<abi-tags>]
3884// <abi-tag> ::= B <source-name>
3885template <typename Derived, typename Alloc>
3887 while (consumeIf('B')) {
3888 std::string_view SN = parseBareSourceName();
3889 if (SN.empty())
3890 return nullptr;
3891 N = make<AbiTagAttr>(N, SN);
3892 if (!N)
3893 return nullptr;
3894 }
3895 return N;
3896}
3897
3898// <number> ::= [n] <non-negative decimal integer>
3899template <typename Alloc, typename Derived>
3900std::string_view
3902 const char *Tmp = First;
3903 if (AllowNegative)
3904 consumeIf('n');
3905 if (numLeft() == 0 || !std::isdigit(*First))
3906 return std::string_view();
3907 while (numLeft() != 0 && std::isdigit(*First))
3908 ++First;
3909 return std::string_view(Tmp, First - Tmp);
3910}
3911
3912// <positive length number> ::= [0-9]*
3913template <typename Alloc, typename Derived>
3915 *Out = 0;
3916 if (look() < '0' || look() > '9')
3917 return true;
3918 while (look() >= '0' && look() <= '9') {
3919 *Out *= 10;
3920 *Out += static_cast<size_t>(consume() - '0');
3921 }
3922 return false;
3923}
3924
3925template <typename Alloc, typename Derived>
3927 size_t Int = 0;
3928 if (parsePositiveInteger(&Int) || numLeft() < Int)
3929 return {};
3930 std::string_view R(First, Int);
3931 First += Int;
3932 return R;
3933}
3934
3935// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3936//
3937// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3938// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3939// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3940//
3941// <ref-qualifier> ::= R # & ref-qualifier
3942// <ref-qualifier> ::= O # && ref-qualifier
3943template <typename Derived, typename Alloc>
3945 Qualifiers CVQuals = parseCVQualifiers();
3946
3947 Node *ExceptionSpec = nullptr;
3948 if (consumeIf("Do")) {
3949 ExceptionSpec = make<NameType>("noexcept");
3950 if (!ExceptionSpec)
3951 return nullptr;
3952 } else if (consumeIf("DO")) {
3953 Node *E = getDerived().parseExpr();
3954 if (E == nullptr || !consumeIf('E'))
3955 return nullptr;
3956 ExceptionSpec = make<NoexceptSpec>(E);
3957 if (!ExceptionSpec)
3958 return nullptr;
3959 } else if (consumeIf("Dw")) {
3960 size_t SpecsBegin = Names.size();
3961 while (!consumeIf('E')) {
3962 Node *T = getDerived().parseType();
3963 if (T == nullptr)
3964 return nullptr;
3965 Names.push_back(T);
3966 }
3967 ExceptionSpec =
3969 if (!ExceptionSpec)
3970 return nullptr;
3971 }
3972
3973 consumeIf("Dx"); // transaction safe
3974
3975 if (!consumeIf('F'))
3976 return nullptr;
3977 consumeIf('Y'); // extern "C"
3978 Node *ReturnType = getDerived().parseType();
3979 if (ReturnType == nullptr)
3980 return nullptr;
3981
3982 FunctionRefQual ReferenceQualifier = FrefQualNone;
3983 size_t ParamsBegin = Names.size();
3984 while (true) {
3985 if (consumeIf('E'))
3986 break;
3987 if (consumeIf('v'))
3988 continue;
3989 if (consumeIf("RE")) {
3990 ReferenceQualifier = FrefQualLValue;
3991 break;
3992 }
3993 if (consumeIf("OE")) {
3994 ReferenceQualifier = FrefQualRValue;
3995 break;
3996 }
3997 Node *T = getDerived().parseType();
3998 if (T == nullptr)
3999 return nullptr;
4000 Names.push_back(T);
4001 }
4002
4003 NodeArray Params = popTrailingNodeArray(ParamsBegin);
4004 return make<FunctionType>(ReturnType, Params, CVQuals,
4005 ReferenceQualifier, ExceptionSpec);
4006}
4007
4008// extension:
4009// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
4010// ::= Dv [<dimension expression>] _ <element type>
4011// <extended element type> ::= <element type>
4012// ::= p # AltiVec vector pixel
4013template <typename Derived, typename Alloc>
4015 if (!consumeIf("Dv"))
4016 return nullptr;
4017 if (look() >= '1' && look() <= '9') {
4018 Node *DimensionNumber = make<NameType>(parseNumber());
4019 if (!DimensionNumber)
4020 return nullptr;
4021 if (!consumeIf('_'))
4022 return nullptr;
4023 if (consumeIf('p'))
4024 return make<PixelVectorType>(DimensionNumber);
4025 Node *ElemType = getDerived().parseType();
4026 if (ElemType == nullptr)
4027 return nullptr;
4028 return make<VectorType>(ElemType, DimensionNumber);
4029 }
4030
4031 if (!consumeIf('_')) {
4032 Node *DimExpr = getDerived().parseExpr();
4033 if (!DimExpr)
4034 return nullptr;
4035 if (!consumeIf('_'))
4036 return nullptr;
4037 Node *ElemType = getDerived().parseType();
4038 if (!ElemType)
4039 return nullptr;
4040 return make<VectorType>(ElemType, DimExpr);
4041 }
4042 Node *ElemType = getDerived().parseType();
4043 if (!ElemType)
4044 return nullptr;
4045 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
4046}
4047
4048// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
4049// ::= DT <expression> E # decltype of an expression (C++0x)
4050template <typename Derived, typename Alloc>
4052 if (!consumeIf('D'))
4053 return nullptr;
4054 if (!consumeIf('t') && !consumeIf('T'))
4055 return nullptr;
4056 Node *E = getDerived().parseExpr();
4057 if (E == nullptr)
4058 return nullptr;
4059 if (!consumeIf('E'))
4060 return nullptr;
4061 return make<EnclosingExpr>("decltype", E);
4062}
4063
4064// <array-type> ::= A <positive dimension number> _ <element type>
4065// ::= A [<dimension expression>] _ <element type>
4066template <typename Derived, typename Alloc>
4068 if (!consumeIf('A'))
4069 return nullptr;
4070
4071 Node *Dimension = nullptr;
4072
4073 if (std::isdigit(look())) {
4074 Dimension = make<NameType>(parseNumber());
4075 if (!Dimension)
4076 return nullptr;
4077 if (!consumeIf('_'))
4078 return nullptr;
4079 } else if (!consumeIf('_')) {
4080 Node *DimExpr = getDerived().parseExpr();
4081 if (DimExpr == nullptr)
4082 return nullptr;
4083 if (!consumeIf('_'))
4084 return nullptr;
4085 Dimension = DimExpr;
4086 }
4087
4088 Node *Ty = getDerived().parseType();
4089 if (Ty == nullptr)
4090 return nullptr;
4091 return make<ArrayType>(Ty, Dimension);
4092}
4093
4094// <pointer-to-member-type> ::= M <class type> <member type>
4095template <typename Derived, typename Alloc>
4097 if (!consumeIf('M'))
4098 return nullptr;
4099 Node *ClassType = getDerived().parseType();
4100 if (ClassType == nullptr)
4101 return nullptr;
4102 Node *MemberType = getDerived().parseType();
4103 if (MemberType == nullptr)
4104 return nullptr;
4105 return make<PointerToMemberType>(ClassType, MemberType);
4106}
4107
4108// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
4109// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
4110// ::= Tu <name> # dependent elaborated type specifier using 'union'
4111// ::= Te <name> # dependent elaborated type specifier using 'enum'
4112template <typename Derived, typename Alloc>
4114 std::string_view ElabSpef;
4115 if (consumeIf("Ts"))
4116 ElabSpef = "struct";
4117 else if (consumeIf("Tu"))
4118 ElabSpef = "union";
4119 else if (consumeIf("Te"))
4120 ElabSpef = "enum";
4121
4122 Node *Name = getDerived().parseName();
4123 if (Name == nullptr)
4124 return nullptr;
4125
4126 if (!ElabSpef.empty())
4127 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
4128
4129 return Name;
4130}
4131
4132// <qualified-type> ::= <qualifiers> <type>
4133// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
4134// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
4135template <typename Derived, typename Alloc>
4137 if (consumeIf('U')) {
4138 std::string_view Qual = parseBareSourceName();
4139 if (Qual.empty())
4140 return nullptr;
4141
4142 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
4143 if (starts_with(Qual, "objcproto")) {
4144 constexpr size_t Len = sizeof("objcproto") - 1;
4145 std::string_view ProtoSourceName(Qual.data() + Len, Qual.size() - Len);
4146 std::string_view Proto;
4147 {
4148 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.data()),
4149 SaveLast(Last, &*ProtoSourceName.rbegin() + 1);
4150 Proto = parseBareSourceName();
4151 }
4152 if (Proto.empty())
4153 return nullptr;
4154 Node *Child = getDerived().parseQualifiedType();
4155 if (Child == nullptr)
4156 return nullptr;
4157 return make<ObjCProtoName>(Child, Proto);
4158 }
4159
4160 Node *TA = nullptr;
4161 if (look() == 'I') {
4162 TA = getDerived().parseTemplateArgs();
4163 if (TA == nullptr)
4164 return nullptr;
4165 }
4166
4167 Node *Child = getDerived().parseQualifiedType();
4168 if (Child == nullptr)
4169 return nullptr;
4170 return make<VendorExtQualType>(Child, Qual, TA);
4171 }
4172
4173 Qualifiers Quals = parseCVQualifiers();
4174 Node *Ty = getDerived().parseType();
4175 if (Ty == nullptr)
4176 return nullptr;
4177 if (Quals != QualNone)
4178 Ty = make<QualType>(Ty, Quals);
4179 return Ty;
4180}
4181
4182// <type> ::= <builtin-type>
4183// ::= <qualified-type>
4184// ::= <function-type>
4185// ::= <class-enum-type>
4186// ::= <array-type>
4187// ::= <pointer-to-member-type>
4188// ::= <template-param>
4189// ::= <template-template-param> <template-args>
4190// ::= <decltype>
4191// ::= P <type> # pointer
4192// ::= R <type> # l-value reference
4193// ::= O <type> # r-value reference (C++11)
4194// ::= C <type> # complex pair (C99)
4195// ::= G <type> # imaginary (C99)
4196// ::= <substitution> # See Compression below
4197// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
4198// extension ::= <vector-type> # <vector-type> starts with Dv
4199//
4200// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
4201// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
4202template <typename Derived, typename Alloc>
4204 Node *Result = nullptr;
4205
4206 switch (look()) {
4207 // ::= <qualified-type>
4208 case 'r':
4209 case 'V':
4210 case 'K': {
4211 unsigned AfterQuals = 0;
4212 if (look(AfterQuals) == 'r') ++AfterQuals;
4213 if (look(AfterQuals) == 'V') ++AfterQuals;
4214 if (look(AfterQuals) == 'K') ++AfterQuals;
4215
4216 if (look(AfterQuals) == 'F' ||
4217 (look(AfterQuals) == 'D' &&
4218 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
4219 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
4220 Result = getDerived().parseFunctionType();
4221 break;
4222 }
4224 }
4225 case 'U': {
4226 Result = getDerived().parseQualifiedType();
4227 break;
4228 }
4229 // <builtin-type> ::= v # void
4230 case 'v':
4231 ++First;
4232 return make<NameType>("void");
4233 // ::= w # wchar_t
4234 case 'w':
4235 ++First;
4236 return make<NameType>("wchar_t");
4237 // ::= b # bool
4238 case 'b':
4239 ++First;
4240 return make<NameType>("bool");
4241 // ::= c # char
4242 case 'c':
4243 ++First;
4244 return make<NameType>("char");
4245 // ::= a # signed char
4246 case 'a':
4247 ++First;
4248 return make<NameType>("signed char");
4249 // ::= h # unsigned char
4250 case 'h':
4251 ++First;
4252 return make<NameType>("unsigned char");
4253 // ::= s # short
4254 case 's':
4255 ++First;
4256 return make<NameType>("short");
4257 // ::= t # unsigned short
4258 case 't':
4259 ++First;
4260 return make<NameType>("unsigned short");
4261 // ::= i # int
4262 case 'i':
4263 ++First;
4264 return make<NameType>("int");
4265 // ::= j # unsigned int
4266 case 'j':
4267 ++First;
4268 return make<NameType>("unsigned int");
4269 // ::= l # long
4270 case 'l':
4271 ++First;
4272 return make<NameType>("long");
4273 // ::= m # unsigned long
4274 case 'm':
4275 ++First;
4276 return make<NameType>("unsigned long");
4277 // ::= x # long long, __int64
4278 case 'x':
4279 ++First;
4280 return make<NameType>("long long");
4281 // ::= y # unsigned long long, __int64
4282 case 'y':
4283 ++First;
4284 return make<NameType>("unsigned long long");
4285 // ::= n # __int128
4286 case 'n':
4287 ++First;
4288 return make<NameType>("__int128");
4289 // ::= o # unsigned __int128
4290 case 'o':
4291 ++First;
4292 return make<NameType>("unsigned __int128");
4293 // ::= f # float
4294 case 'f':
4295 ++First;
4296 return make<NameType>("float");
4297 // ::= d # double
4298 case 'd':
4299 ++First;
4300 return make<NameType>("double");
4301 // ::= e # long double, __float80
4302 case 'e':
4303 ++First;
4304 return make<NameType>("long double");
4305 // ::= g # __float128
4306 case 'g':
4307 ++First;
4308 return make<NameType>("__float128");
4309 // ::= z # ellipsis
4310 case 'z':
4311 ++First;
4312 return make<NameType>("...");
4313
4314 // <builtin-type> ::= u <source-name> # vendor extended type
4315 case 'u': {
4316 ++First;
4317 std::string_view Res = parseBareSourceName();
4318 if (Res.empty())
4319 return nullptr;
4320 // Typically, <builtin-type>s are not considered substitution candidates,
4321 // but the exception to that exception is vendor extended types (Itanium C++
4322 // ABI 5.9.1).
4323 if (consumeIf('I')) {
4324 Node *BaseType = parseType();
4325 if (BaseType == nullptr)
4326 return nullptr;
4327 if (!consumeIf('E'))
4328 return nullptr;
4329 Result = make<TransformedType>(Res, BaseType);
4330 } else
4331 Result = make<NameType>(Res);
4332 break;
4333 }
4334 case 'D':
4335 switch (look(1)) {
4336 // ::= Dd # IEEE 754r decimal floating point (64 bits)
4337 case 'd':
4338 First += 2;
4339 return make<NameType>("decimal64");
4340 // ::= De # IEEE 754r decimal floating point (128 bits)
4341 case 'e':
4342 First += 2;
4343 return make<NameType>("decimal128");
4344 // ::= Df # IEEE 754r decimal floating point (32 bits)
4345 case 'f':
4346 First += 2;
4347 return make<NameType>("decimal32");
4348 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
4349 case 'h':
4350 First += 2;
4351 return make<NameType>("half");
4352 // ::= DF16b # C++23 std::bfloat16_t
4353 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
4354 case 'F': {
4355 First += 2;
4356 if (consumeIf("16b"))
4357 return make<NameType>("std::bfloat16_t");
4358 Node *DimensionNumber = make<NameType>(parseNumber());
4359 if (!DimensionNumber)
4360 return nullptr;
4361 if (!consumeIf('_'))
4362 return nullptr;
4363 return make<BinaryFPType>(DimensionNumber);
4364 }
4365 // ::= [DS] DA # N1169 fixed-point [_Sat] T _Accum
4366 // ::= [DS] DR # N1169 fixed-point [_Sat] T _Frac
4367 // <fixed-point-size>
4368 // ::= s # short
4369 // ::= t # unsigned short
4370 // ::= i # plain
4371 // ::= j # unsigned
4372 // ::= l # long
4373 // ::= m # unsigned long
4374 case 'A': {
4375 char c = look(2);
4376 First += 3;
4377 switch (c) {
4378 case 's':
4379 return make<NameType>("short _Accum");
4380 case 't':
4381 return make<NameType>("unsigned short _Accum");
4382 case 'i':
4383 return make<NameType>("_Accum");
4384 case 'j':
4385 return make<NameType>("unsigned _Accum");
4386 case 'l':
4387 return make<NameType>("long _Accum");
4388 case 'm':
4389 return make<NameType>("unsigned long _Accum");
4390 default:
4391 return nullptr;
4392 }
4393 }
4394 case 'R': {
4395 char c = look(2);
4396 First += 3;
4397 switch (c) {
4398 case 's':
4399 return make<NameType>("short _Fract");
4400 case 't':
4401 return make<NameType>("unsigned short _Fract");
4402 case 'i':
4403 return make<NameType>("_Fract");
4404 case 'j':
4405 return make<NameType>("unsigned _Fract");
4406 case 'l':
4407 return make<NameType>("long _Fract");
4408 case 'm':
4409 return make<NameType>("unsigned long _Fract");
4410 default:
4411 return nullptr;
4412 }
4413 }
4414 case 'S': {
4415 First += 2;
4416 if (look() != 'D')
4417 return nullptr;
4418 if (look(1) == 'A') {
4419 char c = look(2);
4420 First += 3;
4421 switch (c) {
4422 case 's':
4423 return make<NameType>("_Sat short _Accum");
4424 case 't':
4425 return make<NameType>("_Sat unsigned short _Accum");
4426 case 'i':
4427 return make<NameType>("_Sat _Accum");
4428 case 'j':
4429 return make<NameType>("_Sat unsigned _Accum");
4430 case 'l':
4431 return make<NameType>("_Sat long _Accum");
4432 case 'm':
4433 return make<NameType>("_Sat unsigned long _Accum");
4434 default:
4435 return nullptr;
4436 }
4437 }
4438 if (look(1) == 'R') {
4439 char c = look(2);
4440 First += 3;
4441 switch (c) {
4442 case 's':
4443 return make<NameType>("_Sat short _Fract");
4444 case 't':
4445 return make<NameType>("_Sat unsigned short _Fract");
4446 case 'i':
4447 return make<NameType>("_Sat _Fract");
4448 case 'j':
4449 return make<NameType>("_Sat unsigned _Fract");
4450 case 'l':
4451 return make<NameType>("_Sat long _Fract");
4452 case 'm':
4453 return make<NameType>("_Sat unsigned long _Fract");
4454 default:
4455 return nullptr;
4456 }
4457 }
4458 return nullptr;
4459 }
4460 // ::= DB <number> _ # C23 signed _BitInt(N)
4461 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
4462 // ::= DU <number> _ # C23 unsigned _BitInt(N)
4463 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
4464 case 'B':
4465 case 'U': {
4466 bool Signed = look(1) == 'B';
4467 First += 2;
4468 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())
4469 : getDerived().parseExpr();
4470 if (!Size)
4471 return nullptr;
4472 if (!consumeIf('_'))
4473 return nullptr;
4474 // The front end expects this to be available for Substitution
4475 Result = make<BitIntType>(Size, Signed);
4476 break;
4477 }
4478 // ::= Di # char32_t
4479 case 'i':
4480 First += 2;
4481 return make<NameType>("char32_t");
4482 // ::= Ds # char16_t
4483 case 's':
4484 First += 2;
4485 return make<NameType>("char16_t");
4486 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
4487 case 'u':
4488 First += 2;
4489 return make<NameType>("char8_t");
4490 // ::= Da # auto (in dependent new-expressions)
4491 case 'a':
4492 First += 2;
4493 return make<NameType>("auto");
4494 // ::= Dc # decltype(auto)
4495 case 'c':
4496 First += 2;
4497 return make<NameType>("decltype(auto)");
4498 // ::= Dk <type-constraint> # constrained auto
4499 // ::= DK <type-constraint> # constrained decltype(auto)
4500 case 'k':
4501 case 'K': {
4502 std::string_view Kind = look(1) == 'k' ? " auto" : " decltype(auto)";
4503 First += 2;
4504 Node *Constraint = getDerived().parseName();
4505 if (!Constraint)
4506 return nullptr;
4507 return make<PostfixQualifiedType>(Constraint, Kind);
4508 }
4509 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
4510 case 'n':
4511 First += 2;
4512 return make<NameType>("std::nullptr_t");
4513
4514 // ::= <decltype>
4515 case 't':
4516 case 'T': {
4517 Result = getDerived().parseDecltype();
4518 break;
4519 }
4520 // extension ::= <vector-type> # <vector-type> starts with Dv
4521 case 'v': {
4522 Result = getDerived().parseVectorType();
4523 break;
4524 }
4525 // ::= Dp <type> # pack expansion (C++0x)
4526 case 'p': {
4527 First += 2;
4528 Node *Child = getDerived().parseType();
4529 if (!Child)
4530 return nullptr;
4531 Result = make<ParameterPackExpansion>(Child);
4532 break;
4533 }
4534 // Exception specifier on a function type.
4535 case 'o':
4536 case 'O':
4537 case 'w':
4538 // Transaction safe function type.
4539 case 'x':
4540 Result = getDerived().parseFunctionType();
4541 break;
4542 }
4543 break;
4544 // ::= <function-type>
4545 case 'F': {
4546 Result = getDerived().parseFunctionType();
4547 break;
4548 }
4549 // ::= <array-type>
4550 case 'A': {
4551 Result = getDerived().parseArrayType();
4552 break;
4553 }
4554 // ::= <pointer-to-member-type>
4555 case 'M': {
4556 Result = getDerived().parsePointerToMemberType();
4557 break;
4558 }
4559 // ::= <template-param>
4560 case 'T': {
4561 // This could be an elaborate type specifier on a <class-enum-type>.
4562 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
4563 Result = getDerived().parseClassEnumType();
4564 break;
4565 }
4566
4567 Result = getDerived().parseTemplateParam();
4568 if (Result == nullptr)
4569 return nullptr;
4570
4571 // Result could be either of:
4572 // <type> ::= <template-param>
4573 // <type> ::= <template-template-param> <template-args>
4574 //
4575 // <template-template-param> ::= <template-param>
4576 // ::= <substitution>
4577 //
4578 // If this is followed by some <template-args>, and we're permitted to
4579 // parse them, take the second production.
4580
4581 if (TryToParseTemplateArgs && look() == 'I') {
4582 Subs.push_back(Result);
4583 Node *TA = getDerived().parseTemplateArgs();
4584 if (TA == nullptr)
4585 return nullptr;
4586 Result = make<NameWithTemplateArgs>(Result, TA);
4587 }
4588 break;
4589 }
4590 // ::= P <type> # pointer
4591 case 'P': {
4592 ++First;
4593 Node *Ptr = getDerived().parseType();
4594 if (Ptr == nullptr)
4595 return nullptr;
4596 Result = make<PointerType>(Ptr);
4597 break;
4598 }
4599 // ::= R <type> # l-value reference
4600 case 'R': {
4601 ++First;
4602 Node *Ref = getDerived().parseType();
4603 if (Ref == nullptr)
4604 return nullptr;
4606 break;
4607 }
4608 // ::= O <type> # r-value reference (C++11)
4609 case 'O': {
4610 ++First;
4611 Node *Ref = getDerived().parseType();
4612 if (Ref == nullptr)
4613 return nullptr;
4615 break;
4616 }
4617 // ::= C <type> # complex pair (C99)
4618 case 'C': {
4619 ++First;
4620 Node *P = getDerived().parseType();
4621 if (P == nullptr)
4622 return nullptr;
4623 Result = make<PostfixQualifiedType>(P, " complex");
4624 break;
4625 }
4626 // ::= G <type> # imaginary (C99)
4627 case 'G': {
4628 ++First;
4629 Node *P = getDerived().parseType();
4630 if (P == nullptr)
4631 return P;
4632 Result = make<PostfixQualifiedType>(P, " imaginary");
4633 break;
4634 }
4635 // ::= <substitution> # See Compression below
4636 case 'S': {
4637 if (look(1) != 't') {
4638 bool IsSubst = false;
4639 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4640 if (!Result)
4641 return nullptr;
4642
4643 // Sub could be either of:
4644 // <type> ::= <substitution>
4645 // <type> ::= <template-template-param> <template-args>
4646 //
4647 // <template-template-param> ::= <template-param>
4648 // ::= <substitution>
4649 //
4650 // If this is followed by some <template-args>, and we're permitted to
4651 // parse them, take the second production.
4652
4653 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4654 if (!IsSubst)
4655 Subs.push_back(Result);
4656 Node *TA = getDerived().parseTemplateArgs();
4657 if (TA == nullptr)
4658 return nullptr;
4659 Result = make<NameWithTemplateArgs>(Result, TA);
4660 } else if (IsSubst) {
4661 // If all we parsed was a substitution, don't re-insert into the
4662 // substitution table.
4663 return Result;
4664 }
4665 break;
4666 }
4668 }
4669 // ::= <class-enum-type>
4670 default: {
4671 Result = getDerived().parseClassEnumType();
4672 break;
4673 }
4674 }
4675
4676 // If we parsed a type, insert it into the substitution table. Note that all
4677 // <builtin-type>s and <substitution>s have already bailed out, because they
4678 // don't get substitutions.
4679 if (Result != nullptr)
4680 Subs.push_back(Result);
4681 return Result;
4682}
4683
4684template <typename Derived, typename Alloc>
4685Node *
4687 Node::Prec Prec) {
4688 Node *E = getDerived().parseExpr();
4689 if (E == nullptr)
4690 return nullptr;
4691 return make<PrefixExpr>(Kind, E, Prec);
4692}
4693
4694template <typename Derived, typename Alloc>
4695Node *
4697 Node::Prec Prec) {
4698 Node *LHS = getDerived().parseExpr();
4699 if (LHS == nullptr)
4700 return nullptr;
4701 Node *RHS = getDerived().parseExpr();
4702 if (RHS == nullptr)
4703 return nullptr;
4704 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
4705}
4706
4707template <typename Derived, typename Alloc>
4709 std::string_view Lit) {
4710 std::string_view Tmp = parseNumber(true);
4711 if (!Tmp.empty() && consumeIf('E'))
4712 return make<IntegerLiteral>(Lit, Tmp);
4713 return nullptr;
4714}
4715
4716// <CV-Qualifiers> ::= [r] [V] [K]
4717template <typename Alloc, typename Derived>
4719 Qualifiers CVR = QualNone;
4720 if (consumeIf('r'))
4721 CVR |= QualRestrict;
4722 if (consumeIf('V'))
4723 CVR |= QualVolatile;
4724 if (consumeIf('K'))
4725 CVR |= QualConst;
4726 return CVR;
4727}
4728
4729// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4730// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4731// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4732// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
4733// ::= fpT # 'this' expression (not part of standard?)
4734template <typename Derived, typename Alloc>
4736 if (consumeIf("fpT"))
4737 return make<NameType>("this");
4738 if (consumeIf("fp")) {
4740 std::string_view Num = parseNumber();
4741 if (!consumeIf('_'))
4742 return nullptr;
4743 return make<FunctionParam>(Num);
4744 }
4745 if (consumeIf("fL")) {
4746 if (parseNumber().empty())
4747 return nullptr;
4748 if (!consumeIf('p'))
4749 return nullptr;
4751 std::string_view Num = parseNumber();
4752 if (!consumeIf('_'))
4753 return nullptr;
4754 return make<FunctionParam>(Num);
4755 }
4756 return nullptr;
4757}
4758
4759// cv <type> <expression> # conversion with one argument
4760// cv <type> _ <expression>* E # conversion with a different number of arguments
4761template <typename Derived, typename Alloc>
4763 if (!consumeIf("cv"))
4764 return nullptr;
4765 Node *Ty;
4766 {
4768 Ty = getDerived().parseType();
4769 }
4770
4771 if (Ty == nullptr)
4772 return nullptr;
4773
4774 if (consumeIf('_')) {
4775 size_t ExprsBegin = Names.size();
4776 while (!consumeIf('E')) {
4777 Node *E = getDerived().parseExpr();
4778 if (E == nullptr)
4779 return E;
4780 Names.push_back(E);
4781 }
4782 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4783 return make<ConversionExpr>(Ty, Exprs);
4784 }
4785
4786 Node *E[1] = {getDerived().parseExpr()};
4787 if (E[0] == nullptr)
4788 return nullptr;
4789 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4790}
4791
4792// <expr-primary> ::= L <type> <value number> E # integer literal
4793// ::= L <type> <value float> E # floating literal
4794// ::= L <string type> E # string literal
4795// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
4796// ::= L <lambda type> E # lambda expression
4797// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4798// ::= L <mangled-name> E # external name
4799template <typename Derived, typename Alloc>
4801 if (!consumeIf('L'))
4802 return nullptr;
4803 switch (look()) {
4804 case 'w':
4805 ++First;
4806 return getDerived().parseIntegerLiteral("wchar_t");
4807 case 'b':
4808 if (consumeIf("b0E"))
4809 return make<BoolExpr>(0);
4810 if (consumeIf("b1E"))
4811 return make<BoolExpr>(1);
4812 return nullptr;
4813 case 'c':
4814 ++First;
4815 return getDerived().parseIntegerLiteral("char");
4816 case 'a':
4817 ++First;
4818 return getDerived().parseIntegerLiteral("signed char");
4819 case 'h':
4820 ++First;
4821 return getDerived().parseIntegerLiteral("unsigned char");
4822 case 's':
4823 ++First;
4824 return getDerived().parseIntegerLiteral("short");
4825 case 't':
4826 ++First;
4827 return getDerived().parseIntegerLiteral("unsigned short");
4828 case 'i':
4829 ++First;
4830 return getDerived().parseIntegerLiteral("");
4831 case 'j':
4832 ++First;
4833 return getDerived().parseIntegerLiteral("u");
4834 case 'l':
4835 ++First;
4836 return getDerived().parseIntegerLiteral("l");
4837 case 'm':
4838 ++First;
4839 return getDerived().parseIntegerLiteral("ul");
4840 case 'x':
4841 ++First;
4842 return getDerived().parseIntegerLiteral("ll");
4843 case 'y':
4844 ++First;
4845 return getDerived().parseIntegerLiteral("ull");
4846 case 'n':
4847 ++First;
4848 return getDerived().parseIntegerLiteral("__int128");
4849 case 'o':
4850 ++First;
4851 return getDerived().parseIntegerLiteral("unsigned __int128");
4852 case 'f':
4853 ++First;
4854 return getDerived().template parseFloatingLiteral<float>();
4855 case 'd':
4856 ++First;
4857 return getDerived().template parseFloatingLiteral<double>();
4858 case 'e':
4859 ++First;
4860#if defined(__powerpc__) || defined(__s390__)
4861 // Handle cases where long doubles encoded with e have the same size
4862 // and representation as doubles.
4863 return getDerived().template parseFloatingLiteral<double>();
4864#else
4866#endif
4867 case '_':
4868 if (consumeIf("_Z")) {
4869 Node *R = getDerived().parseEncoding();
4870 if (R != nullptr && consumeIf('E'))
4871 return R;
4872 }
4873 return nullptr;
4874 case 'A': {
4875 Node *T = getDerived().parseType();
4876 if (T == nullptr)
4877 return nullptr;
4878 // FIXME: We need to include the string contents in the mangling.
4879 if (consumeIf('E'))
4880 return make<StringLiteral>(T);
4881 return nullptr;
4882 }
4883 case 'D':
4884 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
4885 return make<NameType>("nullptr");
4886 return nullptr;
4887 case 'T':
4888 // Invalid mangled name per
4889 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4890 return nullptr;
4891 case 'U': {
4892 // FIXME: Should we support LUb... for block literals?
4893 if (look(1) != 'l')
4894 return nullptr;
4895 Node *T = parseUnnamedTypeName(nullptr);
4896 if (!T || !consumeIf('E'))
4897 return nullptr;
4898 return make<LambdaExpr>(T);
4899 }
4900 default: {
4901 // might be named type
4902 Node *T = getDerived().parseType();
4903 if (T == nullptr)
4904 return nullptr;
4905 std::string_view N = parseNumber(/*AllowNegative=*/true);
4906 if (N.empty())
4907 return nullptr;
4908 if (!consumeIf('E'))
4909 return nullptr;
4910 return make<EnumLiteral>(T, N);
4911 }
4912 }
4913}
4914
4915// <braced-expression> ::= <expression>
4916// ::= di <field source-name> <braced-expression> # .name = expr
4917// ::= dx <index expression> <braced-expression> # [expr] = expr
4918// ::= dX <range begin expression> <range end expression> <braced-expression>
4919template <typename Derived, typename Alloc>
4921 if (look() == 'd') {
4922 switch (look(1)) {
4923 case 'i': {
4924 First += 2;
4925 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
4926 if (Field == nullptr)
4927 return nullptr;
4928 Node *Init = getDerived().parseBracedExpr();
4929 if (Init == nullptr)
4930 return nullptr;
4931 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4932 }
4933 case 'x': {
4934 First += 2;
4935 Node *Index = getDerived().parseExpr();
4936 if (Index == nullptr)
4937 return nullptr;
4938 Node *Init = getDerived().parseBracedExpr();
4939 if (Init == nullptr)
4940 return nullptr;
4941 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4942 }
4943 case 'X': {
4944 First += 2;
4945 Node *RangeBegin = getDerived().parseExpr();
4946 if (RangeBegin == nullptr)
4947 return nullptr;
4948 Node *RangeEnd = getDerived().parseExpr();
4949 if (RangeEnd == nullptr)
4950 return nullptr;
4951 Node *Init = getDerived().parseBracedExpr();
4952 if (Init == nullptr)
4953 return nullptr;
4954 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4955 }
4956 }
4957 }
4958 return getDerived().parseExpr();
4959}
4960
4961// (not yet in the spec)
4962// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4963// ::= fR <binary-operator-name> <expression> <expression>
4964// ::= fl <binary-operator-name> <expression>
4965// ::= fr <binary-operator-name> <expression>
4966template <typename Derived, typename Alloc>
4968 if (!consumeIf('f'))
4969 return nullptr;
4970
4971 bool IsLeftFold = false, HasInitializer = false;
4972 switch (look()) {
4973 default:
4974 return nullptr;
4975 case 'L':
4976 IsLeftFold = true;
4977 HasInitializer = true;
4978 break;
4979 case 'R':
4980 HasInitializer = true;
4981 break;
4982 case 'l':
4983 IsLeftFold = true;
4984 break;
4985 case 'r':
4986 break;
4987 }
4988 ++First;
4989
4990 const auto *Op = parseOperatorEncoding();
4991 if (!Op)
4992 return nullptr;
4993 if (!(Op->getKind() == OperatorInfo::Binary
4994 || (Op->getKind() == OperatorInfo::Member
4995 && Op->getName().back() == '*')))
4996 return nullptr;
4997
4998 Node *Pack = getDerived().parseExpr();
4999 if (Pack == nullptr)
5000 return nullptr;
5001
5002 Node *Init = nullptr;
5003 if (HasInitializer) {
5004 Init = getDerived().parseExpr();
5005 if (Init == nullptr)
5006 return nullptr;
5007 }
5008
5009 if (IsLeftFold && Init)
5010 std::swap(Pack, Init);
5011
5012 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
5013}
5014
5015// <expression> ::= mc <parameter type> <expr> [<offset number>] E
5016//
5017// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
5018template <typename Derived, typename Alloc>
5019Node *
5021 Node::Prec Prec) {
5022 Node *Ty = getDerived().parseType();
5023 if (!Ty)
5024 return nullptr;
5025 Node *Expr = getDerived().parseExpr();
5026 if (!Expr)
5027 return nullptr;
5028 std::string_view Offset = getDerived().parseNumber(true);
5029 if (!consumeIf('E'))
5030 return nullptr;
5031 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
5032}
5033
5034// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
5035// <union-selector> ::= _ [<number>]
5036//
5037// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
5038template <typename Derived, typename Alloc>
5040 Node *Ty = getDerived().parseType();
5041 if (!Ty)
5042 return nullptr;
5043 Node *Expr = getDerived().parseExpr();
5044 if (!Expr)
5045 return nullptr;
5046 std::string_view Offset = getDerived().parseNumber(true);
5047 size_t SelectorsBegin = Names.size();
5048 while (consumeIf('_')) {
5049 Node *Selector = make<NameType>(parseNumber());
5050 if (!Selector)
5051 return nullptr;
5052 Names.push_back(Selector);
5053 }
5054 bool OnePastTheEnd = consumeIf('p');
5055 if (!consumeIf('E'))
5056 return nullptr;
5057 return make<SubobjectExpr>(
5058 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
5059}
5060
5061template <typename Derived, typename Alloc>
5063 // Within this expression, all enclosing template parameter lists are in
5064 // scope.
5065 ScopedOverride<bool> SaveIncompleteTemplateParameterTracking(
5067 return getDerived().parseExpr();
5068}
5069
5070template <typename Derived, typename Alloc>
5072 NodeArray Params;
5073 if (consumeIf("rQ")) {
5074 // <expression> ::= rQ <bare-function-type> _ <requirement>+ E
5075 size_t ParamsBegin = Names.size();
5076 while (!consumeIf('_')) {
5077 Node *Type = getDerived().parseType();
5078 if (Type == nullptr)
5079 return nullptr;
5080 Names.push_back(Type);
5081 }
5082 Params = popTrailingNodeArray(ParamsBegin);
5083 } else if (!consumeIf("rq")) {
5084 // <expression> ::= rq <requirement>+ E
5085 return nullptr;
5086 }
5087
5088 size_t ReqsBegin = Names.size();
5089 do {
5090 Node *Constraint = nullptr;
5091 if (consumeIf('X')) {
5092 // <requirement> ::= X <expression> [N] [R <type-constraint>]
5093 Node *Expr = getDerived().parseExpr();
5094 if (Expr == nullptr)
5095 return nullptr;
5096 bool Noexcept = consumeIf('N');
5097 Node *TypeReq = nullptr;
5098 if (consumeIf('R')) {
5099 TypeReq = getDerived().parseName();
5100 if (TypeReq == nullptr)
5101 return nullptr;
5102 }
5103 Constraint = make<ExprRequirement>(Expr, Noexcept, TypeReq);
5104 } else if (consumeIf('T')) {
5105 // <requirement> ::= T <type>
5106 Node *Type = getDerived().parseType();
5107 if (Type == nullptr)
5108 return nullptr;
5109 Constraint = make<TypeRequirement>(Type);
5110 } else if (consumeIf('Q')) {
5111 // <requirement> ::= Q <constraint-expression>
5112 //
5113 // FIXME: We use <expression> instead of <constraint-expression>. Either
5114 // the requires expression is already inside a constraint expression, in
5115 // which case it makes no difference, or we're in a requires-expression
5116 // that might be partially-substituted, where the language behavior is
5117 // not yet settled and clang mangles after substitution.
5118 Node *NestedReq = getDerived().parseExpr();
5119 if (NestedReq == nullptr)
5120 return nullptr;
5121 Constraint = make<NestedRequirement>(NestedReq);
5122 }
5123 if (Constraint == nullptr)
5124 return nullptr;
5125 Names.push_back(Constraint);
5126 } while (!consumeIf('E'));
5127
5128 return make<RequiresExpr>(Params, popTrailingNodeArray(ReqsBegin));
5129}
5130
5131// <expression> ::= <unary operator-name> <expression>
5132// ::= <binary operator-name> <expression> <expression>
5133// ::= <ternary operator-name> <expression> <expression> <expression>
5134// ::= cl <expression>+ E # call
5135// ::= cp <base-unresolved-name> <expression>* E # (name) (expr-list), call that would use argument-dependent lookup but for the parentheses
5136// ::= cv <type> <expression> # conversion with one argument
5137// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
5138// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
5139// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
5140// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
5141// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
5142// ::= [gs] dl <expression> # delete expression
5143// ::= [gs] da <expression> # delete[] expression
5144// ::= pp_ <expression> # prefix ++
5145// ::= mm_ <expression> # prefix --
5146// ::= ti <type> # typeid (type)
5147// ::= te <expression> # typeid (expression)
5148// ::= dc <type> <expression> # dynamic_cast<type> (expression)
5149// ::= sc <type> <expression> # static_cast<type> (expression)
5150// ::= cc <type> <expression> # const_cast<type> (expression)
5151// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
5152// ::= st <type> # sizeof (a type)
5153// ::= sz <expression> # sizeof (an expression)
5154// ::= at <type> # alignof (a type)
5155// ::= az <expression> # alignof (an expression)
5156// ::= nx <expression> # noexcept (expression)
5157// ::= <template-param>
5158// ::= <function-param>
5159// ::= dt <expression> <unresolved-name> # expr.name
5160// ::= pt <expression> <unresolved-name> # expr->name
5161// ::= ds <expression> <expression> # expr.*expr
5162// ::= sZ <template-param> # size of a parameter pack
5163// ::= sZ <function-param> # size of a function parameter pack
5164// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
5165// ::= sp <expression> # pack expansion
5166// ::= tw <expression> # throw expression
5167// ::= tr # throw with no operand (rethrow)
5168// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
5169// # freestanding dependent name (e.g., T::x),
5170// # objectless nonstatic member reference
5171// ::= fL <binary-operator-name> <expression> <expression>
5172// ::= fR <binary-operator-name> <expression> <expression>
5173// ::= fl <binary-operator-name> <expression>
5174// ::= fr <binary-operator-name> <expression>
5175// ::= <expr-primary>
5176template <typename Derived, typename Alloc>
5178 bool Global = consumeIf("gs");
5179
5180 const auto *Op = parseOperatorEncoding();
5181 if (Op) {
5182 auto Sym = Op->getSymbol();
5183 switch (Op->getKind()) {
5185 // Binary operator: lhs @ rhs
5186 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
5188 // Prefix unary operator: @ expr
5189 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
5190 case OperatorInfo::Postfix: {
5191 // Postfix unary operator: expr @
5192 if (consumeIf('_'))
5193 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
5194 Node *Ex = getDerived().parseExpr();
5195 if (Ex == nullptr)
5196 return nullptr;
5197 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
5198 }
5199 case OperatorInfo::Array: {
5200 // Array Index: lhs [ rhs ]
5201 Node *Base = getDerived().parseExpr();
5202 if (Base == nullptr)
5203 return nullptr;
5204 Node *Index = getDerived().parseExpr();
5205 if (Index == nullptr)
5206 return nullptr;
5207 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
5208 }
5209 case OperatorInfo::Member: {
5210 // Member access lhs @ rhs
5211 Node *LHS = getDerived().parseExpr();
5212 if (LHS == nullptr)
5213 return nullptr;
5214 Node *RHS = getDerived().parseExpr();
5215 if (RHS == nullptr)
5216 return nullptr;
5217 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
5218 }
5219 case OperatorInfo::New: {
5220 // New
5221 // # new (expr-list) type [(init)]
5222 // [gs] nw <expression>* _ <type> [pi <expression>*] E
5223 // # new[] (expr-list) type [(init)]
5224 // [gs] na <expression>* _ <type> [pi <expression>*] E
5225 size_t Exprs = Names.size();
5226 while (!consumeIf('_')) {
5227 Node *Ex = getDerived().parseExpr();
5228 if (Ex == nullptr)
5229 return nullptr;
5230 Names.push_back(Ex);
5231 }
5232 NodeArray ExprList = popTrailingNodeArray(Exprs);
5233 Node *Ty = getDerived().parseType();
5234 if (Ty == nullptr)
5235 return nullptr;
5236 bool HaveInits = consumeIf("pi");
5237 size_t InitsBegin = Names.size();
5238 while (!consumeIf('E')) {
5239 if (!HaveInits)
5240 return nullptr;
5241 Node *Init = getDerived().parseExpr();
5242 if (Init == nullptr)
5243 return Init;
5244 Names.push_back(Init);
5245 }
5246 NodeArray Inits = popTrailingNodeArray(InitsBegin);
5247 return make<NewExpr>(ExprList, Ty, Inits, Global,
5248 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
5249 }
5250 case OperatorInfo::Del: {
5251 // Delete
5252 Node *Ex = getDerived().parseExpr();
5253 if (Ex == nullptr)
5254 return nullptr;
5255 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
5256 Op->getPrecedence());
5257 }
5258 case OperatorInfo::Call: {
5259 // Function Call
5260 Node *Callee = getDerived().parseExpr();
5261 if (Callee == nullptr)
5262 return nullptr;
5263 size_t ExprsBegin = Names.size();
5264 while (!consumeIf('E')) {
5265 Node *E = getDerived().parseExpr();
5266 if (E == nullptr)
5267 return nullptr;
5268 Names.push_back(E);
5269 }
5270 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
5271 /*IsParen=*/Op->getFlag(), Op->getPrecedence());
5272 }
5273 case OperatorInfo::CCast: {
5274 // C Cast: (type)expr
5275 Node *Ty;
5276 {
5278 Ty = getDerived().parseType();
5279 }
5280 if (Ty == nullptr)
5281 return nullptr;
5282
5283 size_t ExprsBegin = Names.size();
5284 bool IsMany = consumeIf('_');
5285 while (!consumeIf('E')) {
5286 Node *E = getDerived().parseExpr();
5287 if (E == nullptr)
5288 return E;
5289 Names.push_back(E);
5290 if (!IsMany)
5291 break;
5292 }
5293 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
5294 if (!IsMany && Exprs.size() != 1)
5295 return nullptr;
5296 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
5297 }
5299 // Conditional operator: expr ? expr : expr
5300 Node *Cond = getDerived().parseExpr();
5301 if (Cond == nullptr)
5302 return nullptr;
5303 Node *LHS = getDerived().parseExpr();
5304 if (LHS == nullptr)
5305 return nullptr;
5306 Node *RHS = getDerived().parseExpr();
5307 if (RHS == nullptr)
5308 return nullptr;
5309 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
5310 }
5312 // Named cast operation, @<type>(expr)
5313 Node *Ty = getDerived().parseType();
5314 if (Ty == nullptr)
5315 return nullptr;
5316 Node *Ex = getDerived().parseExpr();
5317 if (Ex == nullptr)
5318 return nullptr;
5319 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
5320 }
5321 case OperatorInfo::OfIdOp: {
5322 // [sizeof/alignof/typeid] ( <type>|<expr> )
5323 Node *Arg =
5324 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
5325 if (!Arg)
5326 return nullptr;
5327 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
5328 }
5330 // Not valid as an expression operand.
5331 return nullptr;
5332 }
5333 }
5335 }
5336
5337 if (numLeft() < 2)
5338 return nullptr;
5339
5340 if (look() == 'L')
5341 return getDerived().parseExprPrimary();
5342 if (look() == 'T')
5343 return getDerived().parseTemplateParam();
5344 if (look() == 'f') {
5345 // Disambiguate a fold expression from a <function-param>.
5346 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
5347 return getDerived().parseFunctionParam();
5348 return getDerived().parseFoldExpr();
5349 }
5350 if (consumeIf("il")) {
5351 size_t InitsBegin = Names.size();
5352 while (!consumeIf('E')) {
5353 Node *E = getDerived().parseBracedExpr();
5354 if (E == nullptr)
5355 return nullptr;
5356 Names.push_back(E);
5357 }
5358 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
5359 }
5360 if (consumeIf("mc"))
5362 if (consumeIf("nx")) {
5363 Node *Ex = getDerived().parseExpr();
5364 if (Ex == nullptr)
5365 return Ex;
5366 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
5367 }
5368 if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q'))
5369 return parseRequiresExpr();
5370 if (consumeIf("so"))
5371 return parseSubobjectExpr();
5372 if (consumeIf("sp")) {
5373 Node *Child = getDerived().parseExpr();
5374 if (Child == nullptr)
5375 return nullptr;
5376 return make<ParameterPackExpansion>(Child);
5377 }
5378 if (consumeIf("sZ")) {
5379 if (look() == 'T') {
5380 Node *R = getDerived().parseTemplateParam();
5381 if (R == nullptr)
5382 return nullptr;
5383 return make<SizeofParamPackExpr>(R);
5384 }
5385 Node *FP = getDerived().parseFunctionParam();
5386 if (FP == nullptr)
5387 return nullptr;
5388 return make<EnclosingExpr>("sizeof... ", FP);
5389 }
5390 if (consumeIf("sP")) {
5391 size_t ArgsBegin = Names.size();
5392 while (!consumeIf('E')) {
5393 Node *Arg = getDerived().parseTemplateArg();
5394 if (Arg == nullptr)
5395 return nullptr;
5396 Names.push_back(Arg);
5397 }
5398 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
5399 if (!Pack)
5400 return nullptr;
5401 return make<EnclosingExpr>("sizeof... ", Pack);
5402 }
5403 if (consumeIf("tl")) {
5404 Node *Ty = getDerived().parseType();
5405 if (Ty == nullptr)
5406 return nullptr;
5407 size_t InitsBegin = Names.size();
5408 while (!consumeIf('E')) {
5409 Node *E = getDerived().parseBracedExpr();
5410 if (E == nullptr)
5411 return nullptr;
5412 Names.push_back(E);
5413 }
5414 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
5415 }
5416 if (consumeIf("tr"))
5417 return make<NameType>("throw");
5418 if (consumeIf("tw")) {
5419 Node *Ex = getDerived().parseExpr();
5420 if (Ex == nullptr)
5421 return nullptr;
5422 return make<ThrowExpr>(Ex);
5423 }
5424 if (consumeIf('u')) {
5425 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
5426 if (!Name)
5427 return nullptr;
5428 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
5429 // standard encoding expects a <template-arg>, and would be otherwise be
5430 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
5431 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
5432 // actual conflict here.
5433 bool IsUUID = false;
5434 Node *UUID = nullptr;
5435 if (Name->getBaseName() == "__uuidof") {
5436 if (consumeIf('t')) {
5437 UUID = getDerived().parseType();
5438 IsUUID = true;
5439 } else if (consumeIf('z')) {
5440 UUID = getDerived().parseExpr();
5441 IsUUID = true;
5442 }
5443 }
5444 size_t ExprsBegin = Names.size();
5445 if (IsUUID) {
5446 if (UUID == nullptr)
5447 return nullptr;
5448 Names.push_back(UUID);
5449 } else {
5450 while (!consumeIf('E')) {
5451 Node *E = getDerived().parseTemplateArg();
5452 if (E == nullptr)
5453 return E;
5454 Names.push_back(E);
5455 }
5456 }
5457 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
5458 /*IsParen=*/false, Node::Prec::Postfix);
5459 }
5460
5461 // Only unresolved names remain.
5462 return getDerived().parseUnresolvedName(Global);
5463}
5464
5465// <call-offset> ::= h <nv-offset> _
5466// ::= v <v-offset> _
5467//
5468// <nv-offset> ::= <offset number>
5469// # non-virtual base override
5470//
5471// <v-offset> ::= <offset number> _ <virtual offset number>
5472// # virtual base override, with vcall offset
5473template <typename Alloc, typename Derived>
5475 // Just scan through the call offset, we never add this information into the
5476 // output.
5477 if (consumeIf('h'))
5478 return parseNumber(true).empty() || !consumeIf('_');
5479 if (consumeIf('v'))
5480 return parseNumber(true).empty() || !consumeIf('_') ||
5481 parseNumber(true).empty() || !consumeIf('_');
5482 return true;
5483}
5484
5485// <special-name> ::= TV <type> # virtual table
5486// ::= TT <type> # VTT structure (construction vtable index)
5487// ::= TI <type> # typeinfo structure
5488// ::= TS <type> # typeinfo name (null-terminated byte string)
5489// ::= Tc <call-offset> <call-offset> <base encoding>
5490// # base is the nominal target function of thunk
5491// # first call-offset is 'this' adjustment
5492// # second call-offset is result adjustment
5493// ::= T <call-offset> <base encoding>
5494// # base is the nominal target function of thunk
5495// # Guard variable for one-time initialization
5496// ::= GV <object name>
5497// # No <type>
5498// ::= TW <object name> # Thread-local wrapper
5499// ::= TH <object name> # Thread-local initialization
5500// ::= GR <object name> _ # First temporary
5501// ::= GR <object name> <seq-id> _ # Subsequent temporaries
5502// # construction vtable for second-in-first
5503// extension ::= TC <first type> <number> _ <second type>
5504// extension ::= GR <object name> # reference temporary for object
5505// extension ::= GI <module name> # module global initializer
5506template <typename Derived, typename Alloc>
5508 switch (look()) {
5509 case 'T':
5510 switch (look(1)) {
5511 // TA <template-arg> # template parameter object
5512 //
5513 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
5514 case 'A': {
5515 First += 2;
5516 Node *Arg = getDerived().parseTemplateArg();
5517 if (Arg == nullptr)
5518 return nullptr;
5519 return make<SpecialName>("template parameter object for ", Arg);
5520 }
5521 // TV <type> # virtual table
5522 case 'V': {
5523 First += 2;
5524 Node *Ty = getDerived().parseType();
5525 if (Ty == nullptr)
5526 return nullptr;
5527 return make<SpecialName>("vtable for ", Ty);
5528 }
5529 // TT <type> # VTT structure (construction vtable index)
5530 case 'T': {
5531 First += 2;
5532 Node *Ty = getDerived().parseType();
5533 if (Ty == nullptr)
5534 return nullptr;
5535 return make<SpecialName>("VTT for ", Ty);
5536 }
5537 // TI <type> # typeinfo structure
5538 case 'I': {
5539 First += 2;
5540 Node *Ty = getDerived().parseType();
5541 if (Ty == nullptr)
5542 return nullptr;
5543 return make<SpecialName>("typeinfo for ", Ty);
5544 }
5545 // TS <type> # typeinfo name (null-terminated byte string)
5546 case 'S': {
5547 First += 2;
5548 Node *Ty = getDerived().parseType();
5549 if (Ty == nullptr)
5550 return nullptr;
5551 return make<SpecialName>("typeinfo name for ", Ty);
5552 }
5553 // Tc <call-offset> <call-offset> <base encoding>
5554 case 'c': {
5555 First += 2;
5557 return nullptr;
5558 Node *Encoding = getDerived().parseEncoding();
5559 if (Encoding == nullptr)
5560 return nullptr;
5561 return make<SpecialName>("covariant return thunk to ", Encoding);
5562 }
5563 // extension ::= TC <first type> <number> _ <second type>
5564 // # construction vtable for second-in-first
5565 case 'C': {
5566 First += 2;
5567 Node *FirstType = getDerived().parseType();
5568 if (FirstType == nullptr)
5569 return nullptr;
5570 if (parseNumber(true).empty() || !consumeIf('_'))
5571 return nullptr;
5572 Node *SecondType = getDerived().parseType();
5573 if (SecondType == nullptr)
5574 return nullptr;
5575 return make<CtorVtableSpecialName>(SecondType, FirstType);
5576 }
5577 // TW <object name> # Thread-local wrapper
5578 case 'W': {
5579 First += 2;
5580 Node *Name = getDerived().parseName();
5581 if (Name == nullptr)
5582 return nullptr;
5583 return make<SpecialName>("thread-local wrapper routine for ", Name);
5584 }
5585 // TH <object name> # Thread-local initialization
5586 case 'H': {
5587 First += 2;
5588 Node *Name = getDerived().parseName();
5589 if (Name == nullptr)
5590 return nullptr;
5591 return make<SpecialName>("thread-local initialization routine for ", Name);
5592 }
5593 // T <call-offset> <base encoding>
5594 default: {
5595 ++First;
5596 bool IsVirt = look() == 'v';
5597 if (parseCallOffset())
5598 return nullptr;
5599 Node *BaseEncoding = getDerived().parseEncoding();
5600 if (BaseEncoding == nullptr)
5601 return nullptr;
5602 if (IsVirt)
5603 return make<SpecialName>("virtual thunk to ", BaseEncoding);
5604 else
5605 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
5606 }
5607 }
5608 case 'G':
5609 switch (look(1)) {
5610 // GV <object name> # Guard variable for one-time initialization
5611 case 'V': {
5612 First += 2;
5613 Node *Name = getDerived().parseName();
5614 if (Name == nullptr)
5615 return nullptr;
5616 return make<SpecialName>("guard variable for ", Name);
5617 }
5618 // GR <object name> # reference temporary for object
5619 // GR <object name> _ # First temporary
5620 // GR <object name> <seq-id> _ # Subsequent temporaries
5621 case 'R': {
5622 First += 2;
5623 Node *Name = getDerived().parseName();
5624 if (Name == nullptr)
5625 return nullptr;
5626 size_t Count;
5627 bool ParsedSeqId = !parseSeqId(&Count);
5628 if (!consumeIf('_') && ParsedSeqId)
5629 return nullptr;
5630 return make<SpecialName>("reference temporary for ", Name);
5631 }
5632 // GI <module-name> v
5633 case 'I': {
5634 First += 2;
5635 ModuleName *Module = nullptr;
5637 return nullptr;
5638 if (Module == nullptr)
5639 return nullptr;
5640 return make<SpecialName>("initializer for module ", Module);
5641 }
5642 }
5643 }
5644 return nullptr;
5645}
5646
5647// <encoding> ::= <function name> <bare-function-type>
5648// [`Q` <requires-clause expr>]
5649// ::= <data name>
5650// ::= <special-name>
5651template <typename Derived, typename Alloc>
5653 // The template parameters of an encoding are unrelated to those of the
5654 // enclosing context.
5655 SaveTemplateParams SaveTemplateParamsScope(this);
5656
5657 if (look() == 'G' || look() == 'T')
5658 return getDerived().parseSpecialName();
5659
5660 auto IsEndOfEncoding = [&] {
5661 // The set of chars that can potentially follow an <encoding> (none of which
5662 // can start a <type>). Enumerating these allows us to avoid speculative
5663 // parsing.
5664 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5665 };
5666
5667 NameState NameInfo(this);
5668 Node *Name = getDerived().parseName(&NameInfo);
5669 if (Name == nullptr)
5670 return nullptr;
5671
5672 if (resolveForwardTemplateRefs(NameInfo))
5673 return nullptr;
5674
5675 if (IsEndOfEncoding())
5676 return Name;
5677
5678 // ParseParams may be false at the top level only, when called from parse().
5679 // For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be
5680 // false when demangling 3fooILZ3BarEET_f but is always true when demangling
5681 // 3Bar.
5682 if (!ParseParams) {
5683 while (consume())
5684 ;
5685 return Name;
5686 }
5687
5688 Node *Attrs = nullptr;
5689 if (consumeIf("Ua9enable_ifI")) {
5690 size_t BeforeArgs = Names.size();
5691 while (!consumeIf('E')) {
5692 Node *Arg = getDerived().parseTemplateArg();
5693 if (Arg == nullptr)
5694 return nullptr;
5695 Names.push_back(Arg);
5696 }
5697 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
5698 if (!Attrs)
5699 return nullptr;
5700 }
5701
5702 Node *ReturnType = nullptr;
5703 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
5704 ReturnType = getDerived().parseType();
5705 if (ReturnType == nullptr)
5706 return nullptr;
5707 }
5708
5709 NodeArray Params;
5710 if (!consumeIf('v')) {
5711 size_t ParamsBegin = Names.size();
5712 do {
5713 Node *Ty = getDerived().parseType();
5714 if (Ty == nullptr)
5715 return nullptr;
5716
5717 const bool IsFirstParam = ParamsBegin == Names.size();
5718 if (NameInfo.HasExplicitObjectParameter && IsFirstParam)
5720
5721 if (Ty == nullptr)
5722 return nullptr;
5723
5724 Names.push_back(Ty);
5725 } while (!IsEndOfEncoding() && look() != 'Q');
5726 Params = popTrailingNodeArray(ParamsBegin);
5727 }
5728
5729 Node *Requires = nullptr;
5730 if (consumeIf('Q')) {
5731 Requires = getDerived().parseConstraintExpr();
5732 if (!Requires)
5733 return nullptr;
5734 }
5735
5736 return make<FunctionEncoding>(ReturnType, Name, Params, Attrs, Requires,
5737 NameInfo.CVQualifiers,
5738 NameInfo.ReferenceQualifier);
5739}
5740
5741template <class Float>
5742struct FloatData;
5743
5744template <>
5745struct FloatData<float>
5746{
5747 static const size_t mangled_size = 8;
5748 static const size_t max_demangled_size = 24;
5749 static constexpr const char* spec = "%af";
5750};
5751
5752template <>
5753struct FloatData<double>
5754{
5755 static const size_t mangled_size = 16;
5756 static const size_t max_demangled_size = 32;
5757 static constexpr const char* spec = "%a";
5758};
5759
5760template <>
5761struct FloatData<long double>
5762{
5763#if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 106
5764 static const size_t mangled_size = 32;
5765#elif __LDBL_MANT_DIG__ == 53 || defined(_MSC_VER)
5766 // MSVC doesn't define __LDBL_MANT_DIG__, but it has long double equal to
5767 // regular double on all current architectures.
5768 static const size_t mangled_size = 16;
5769#elif __LDBL_MANT_DIG__ == 64
5770 static const size_t mangled_size = 20;
5771#else
5772#error Unknown size for __LDBL_MANT_DIG__
5773#endif
5774 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5775 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5776 // Negatives are one character longer than positives.
5777 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5778 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5779 static const size_t max_demangled_size = 42;
5780 static constexpr const char *spec = "%LaL";
5781};
5782
5783template <typename Alloc, typename Derived>
5784template <class Float>
5786 const size_t N = FloatData<Float>::mangled_size;
5787 if (numLeft() <= N)
5788 return nullptr;
5789 std::string_view Data(First, N);
5790 for (char C : Data)
5791 if (!(C >= '0' && C <= '9') && !(C >= 'a' && C <= 'f'))
5792 return nullptr;
5793 First += N;
5794 if (!consumeIf('E'))
5795 return nullptr;
5796 return make<FloatLiteralImpl<Float>>(Data);
5797}
5798
5799// <seq-id> ::= <0-9A-Z>+
5800template <typename Alloc, typename Derived>
5802 if (!(look() >= '0' && look() <= '9') &&
5803 !(look() >= 'A' && look() <= 'Z'))
5804 return true;
5805
5806 size_t Id = 0;
5807 while (true) {
5808 if (look() >= '0' && look() <= '9') {
5809 Id *= 36;
5810 Id += static_cast<size_t>(look() - '0');
5811 } else if (look() >= 'A' && look() <= 'Z') {
5812 Id *= 36;
5813 Id += static_cast<size_t>(look() - 'A') + 10;
5814 } else {
5815 *Out = Id;
5816 return false;
5817 }
5818 ++First;
5819 }
5820}
5821
5822// <substitution> ::= S <seq-id> _
5823// ::= S_
5824// <substitution> ::= Sa # ::std::allocator
5825// <substitution> ::= Sb # ::std::basic_string
5826// <substitution> ::= Ss # ::std::basic_string < char,
5827// ::std::char_traits<char>,
5828// ::std::allocator<char> >
5829// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5830// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5831// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
5832// The St case is handled specially in parseNestedName.
5833template <typename Derived, typename Alloc>
5835 if (!consumeIf('S'))
5836 return nullptr;
5837
5838 if (look() >= 'a' && look() <= 'z') {
5839 SpecialSubKind Kind;
5840 switch (look()) {
5841 case 'a':
5843 break;
5844 case 'b':
5846 break;
5847 case 'd':
5849 break;
5850 case 'i':
5852 break;
5853 case 'o':
5855 break;
5856 case 's':
5858 break;
5859 default:
5860 return nullptr;
5861 }
5862 ++First;
5863 auto *SpecialSub = make<SpecialSubstitution>(Kind);
5864 if (!SpecialSub)
5865 return nullptr;
5866
5867 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5868 // has ABI tags, the tags are appended to the substitution; the result is a
5869 // substitutable component.
5870 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
5871 if (WithTags != SpecialSub) {
5872 Subs.push_back(WithTags);
5873 SpecialSub = WithTags;
5874 }
5875 return SpecialSub;
5876 }
5877
5878 // ::= S_
5879 if (consumeIf('_')) {
5880 if (Subs.empty())
5881 return nullptr;
5882 return Subs[0];
5883 }
5884
5885 // ::= S <seq-id> _
5886 size_t Index = 0;
5887 if (parseSeqId(&Index))
5888 return nullptr;
5889 ++Index;
5890 if (!consumeIf('_') || Index >= Subs.size())
5891 return nullptr;
5892 return Subs[Index];
5893}
5894
5895// <template-param> ::= T_ # first template parameter
5896// ::= T <parameter-2 non-negative number> _
5897// ::= TL <level-1> __
5898// ::= TL <level-1> _ <parameter-2 non-negative number> _
5899template <typename Derived, typename Alloc>
5901 const char *Begin = First;
5902 if (!consumeIf('T'))
5903 return nullptr;
5904
5905 size_t Level = 0;
5906 if (consumeIf('L')) {
5907 if (parsePositiveInteger(&Level))
5908 return nullptr;
5909 ++Level;
5910 if (!consumeIf('_'))
5911 return nullptr;
5912 }
5913
5914 size_t Index = 0;
5915 if (!consumeIf('_')) {
5916 if (parsePositiveInteger(&Index))
5917 return nullptr;
5918 ++Index;
5919 if (!consumeIf('_'))
5920 return nullptr;
5921 }
5922
5923 // We don't track enclosing template parameter levels well enough to reliably
5924 // substitute them all within a <constraint-expression>, so print the
5925 // parameter numbering instead for now.
5926 // TODO: Track all enclosing template parameters and substitute them here.
5928 return make<NameType>(std::string_view(Begin, First - 1 - Begin));
5929 }
5930
5931 // If we're in a context where this <template-param> refers to a
5932 // <template-arg> further ahead in the mangled name (currently just conversion
5933 // operator types), then we should only look it up in the right context.
5934 // This can only happen at the outermost level.
5935 if (PermitForwardTemplateReferences && Level == 0) {
5936 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5937 if (!ForwardRef)
5938 return nullptr;
5939 DEMANGLE_ASSERT(ForwardRef->getKind() == Node::KForwardTemplateReference,
5940 "");
5941 ForwardTemplateRefs.push_back(
5942 static_cast<ForwardTemplateReference *>(ForwardRef));
5943 return ForwardRef;
5944 }
5945
5946 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5947 Index >= TemplateParams[Level]->size()) {
5948 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5949 // list are mangled as the corresponding artificial template type parameter.
5950 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5951 // This will be popped by the ScopedTemplateParamList in
5952 // parseUnnamedTypeName.
5953 if (Level == TemplateParams.size())
5954 TemplateParams.push_back(nullptr);
5955 return make<NameType>("auto");
5956 }
5957
5958 return nullptr;
5959 }
5960
5961 return (*TemplateParams[Level])[Index];
5962}
5963
5964// <template-param-decl> ::= Ty # type parameter
5965// ::= Tk <concept name> [<template-args>] # constrained type parameter
5966// ::= Tn <type> # non-type parameter
5967// ::= Tt <template-param-decl>* E # template parameter
5968// ::= Tp <template-param-decl> # parameter pack
5969template <typename Derived, typename Alloc>
5971 TemplateParamList *Params) {
5972 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5973 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5974 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5975 if (N && Params)
5976 Params->push_back(N);
5977 return N;
5978 };
5979
5980 if (consumeIf("Ty")) {
5981 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5982 if (!Name)
5983 return nullptr;
5984 return make<TypeTemplateParamDecl>(Name);
5985 }
5986
5987 if (consumeIf("Tk")) {
5988 // We don't track enclosing template parameter levels well enough to
5989 // reliably demangle template parameter substitutions, so print an arbitrary
5990 // string in place of a parameter for now.
5991 // TODO: Track all enclosing template parameters and demangle substitutions.
5992 ScopedOverride<bool> SaveIncompleteTemplateParameterTrackingExpr(
5994 Node *Constraint = getDerived().parseName();
5995 if (!Constraint)
5996 return nullptr;
5997 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5998 if (!Name)
5999 return nullptr;
6000 return make<ConstrainedTypeTemplateParamDecl>(Constraint, Name);
6001 }
6002
6003 if (consumeIf("Tn")) {
6004 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
6005 if (!Name)
6006 return nullptr;
6007 Node *Type = parseType();
6008 if (!Type)
6009 return nullptr;
6011 }
6012
6013 if (consumeIf("Tt")) {
6014 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
6015 if (!Name)
6016 return nullptr;
6017 size_t ParamsBegin = Names.size();
6018 ScopedTemplateParamList TemplateTemplateParamParams(this);
6019 Node *Requires = nullptr;
6020 while (!consumeIf('E')) {
6021 Node *P = parseTemplateParamDecl(TemplateTemplateParamParams.params());
6022 if (!P)
6023 return nullptr;
6024 Names.push_back(P);
6025 if (consumeIf('Q')) {
6026 Requires = getDerived().parseConstraintExpr();
6027 if (Requires == nullptr || !consumeIf('E'))
6028 return nullptr;
6029 break;
6030 }
6031 }
6032 NodeArray InnerParams = popTrailingNodeArray(ParamsBegin);
6033 return make<TemplateTemplateParamDecl>(Name, InnerParams, Requires);
6034 }
6035
6036 if (consumeIf("Tp")) {
6037 Node *P = parseTemplateParamDecl(Params);
6038 if (!P)
6039 return nullptr;
6041 }
6042
6043 return nullptr;
6044}
6045
6046// <template-arg> ::= <type> # type or template
6047// ::= X <expression> E # expression
6048// ::= <expr-primary> # simple expressions
6049// ::= J <template-arg>* E # argument pack
6050// ::= LZ <encoding> E # extension
6051// ::= <template-param-decl> <template-arg>
6052template <typename Derived, typename Alloc>
6054 switch (look()) {
6055 case 'X': {
6056 ++First;
6057 Node *Arg = getDerived().parseExpr();
6058 if (Arg == nullptr || !consumeIf('E'))
6059 return nullptr;
6060 return Arg;
6061 }
6062 case 'J': {
6063 ++First;
6064 size_t ArgsBegin = Names.size();
6065 while (!consumeIf('E')) {
6066 Node *Arg = getDerived().parseTemplateArg();
6067 if (Arg == nullptr)
6068 return nullptr;
6069 Names.push_back(Arg);
6070 }
6071 NodeArray Args = popTrailingNodeArray(ArgsBegin);
6072 return make<TemplateArgumentPack>(Args);
6073 }
6074 case 'L': {
6075 // ::= LZ <encoding> E # extension
6076 if (look(1) == 'Z') {
6077 First += 2;
6078 Node *Arg = getDerived().parseEncoding();
6079 if (Arg == nullptr || !consumeIf('E'))
6080 return nullptr;
6081 return Arg;
6082 }
6083 // ::= <expr-primary> # simple expressions
6084 return getDerived().parseExprPrimary();
6085 }
6086 case 'T': {
6087 // Either <template-param> or a <template-param-decl> <template-arg>.
6089 return getDerived().parseType();
6090 Node *Param = getDerived().parseTemplateParamDecl(nullptr);
6091 if (!Param)
6092 return nullptr;
6093 Node *Arg = getDerived().parseTemplateArg();
6094 if (!Arg)
6095 return nullptr;
6096 return make<TemplateParamQualifiedArg>(Param, Arg);
6097 }
6098 default:
6099 return getDerived().parseType();
6100 }
6101}
6102
6103// <template-args> ::= I <template-arg>* [Q <requires-clause expr>] E
6104// extension, the abi says <template-arg>+
6105template <typename Derived, typename Alloc>
6106Node *
6108 if (!consumeIf('I'))
6109 return nullptr;
6110
6111 // <template-params> refer to the innermost <template-args>. Clear out any
6112 // outer args that we may have inserted into TemplateParams.
6113 if (TagTemplates) {
6114 TemplateParams.clear();
6116 OuterTemplateParams.clear();
6117 }
6118
6119 size_t ArgsBegin = Names.size();
6120 Node *Requires = nullptr;
6121 while (!consumeIf('E')) {
6122 if (TagTemplates) {
6123 Node *Arg = getDerived().parseTemplateArg();
6124 if (Arg == nullptr)
6125 return nullptr;
6126 Names.push_back(Arg);
6127 Node *TableEntry = Arg;
6128 if (Arg->getKind() == Node::KTemplateParamQualifiedArg) {
6129 TableEntry =
6130 static_cast<TemplateParamQualifiedArg *>(TableEntry)->getArg();
6131 }
6132 if (Arg->getKind() == Node::KTemplateArgumentPack) {
6134 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
6135 if (!TableEntry)
6136 return nullptr;
6137 }
6139 } else {
6140 Node *Arg = getDerived().parseTemplateArg();
6141 if (Arg == nullptr)
6142 return nullptr;
6143 Names.push_back(Arg);
6144 }
6145 if (consumeIf('Q')) {
6146 Requires = getDerived().parseConstraintExpr();
6147 if (!Requires || !consumeIf('E'))
6148 return nullptr;
6149 break;
6150 }
6151 }
6152 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin), Requires);
6153}
6154
6155// <mangled-name> ::= _Z <encoding>
6156// ::= <type>
6157// extension ::= ___Z <encoding> _block_invoke
6158// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
6159// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
6160template <typename Derived, typename Alloc>
6162 if (consumeIf("_Z") || consumeIf("__Z")) {
6163 Node *Encoding = getDerived().parseEncoding(ParseParams);
6164 if (Encoding == nullptr)
6165 return nullptr;
6166 if (look() == '.') {
6167 Encoding =
6168 make<DotSuffix>(Encoding, std::string_view(First, Last - First));
6169 First = Last;
6170 }
6171 if (numLeft() != 0)
6172 return nullptr;
6173 return Encoding;
6174 }
6175
6176 if (consumeIf("___Z") || consumeIf("____Z")) {
6177 Node *Encoding = getDerived().parseEncoding(ParseParams);
6178 if (Encoding == nullptr || !consumeIf("_block_invoke"))
6179 return nullptr;
6180 bool RequireNumber = consumeIf('_');
6181 if (parseNumber().empty() && RequireNumber)
6182 return nullptr;
6183 if (look() == '.')
6184 First = Last;
6185 if (numLeft() != 0)
6186 return nullptr;
6187 return make<SpecialName>("invocation function for block in ", Encoding);
6188 }
6189
6190 Node *Ty = getDerived().parseType();
6191 if (numLeft() != 0)
6192 return nullptr;
6193 return Ty;
6194}
6195
6196template <typename Alloc>
6201
6202inline void OutputBuffer::printLeft(const Node &N) { N.printLeft(*this); }
6203
6204inline void OutputBuffer::printRight(const Node &N) { N.printRight(*this); }
6205
6207
6208#if defined(__clang__)
6209#pragma clang diagnostic pop
6210#endif
6211
6212#endif // DEMANGLE_ITANIUMDEMANGLE_H
#define Fail
AMDGPU Prepare AGPR Alloc
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
DXIL Resource Implicit Binding
#define DEMANGLE_ABI
DEMANGLE_ABI is the export/visibility macro used to mark symbols 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
DEMANGLE_ABI const char * parse_discriminator(const char *first, const char *last)
Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2)
TemplateParamKind
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
FunctionRefQual
@ FrefQualLValue
@ FrefQualNone
@ FrefQualRValue
ReferenceKind
FloatLiteralImpl< long double > LongDoubleLiteral
SpecialSubKind
FloatLiteralImpl< float > FloatLiteral
Qualifiers
@ QualVolatile
@ QualRestrict
@ QualConst
@ QualNone
FloatLiteralImpl< double > DoubleLiteral
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
Machine Check Debug Module
#define T
nvptx lower args
OptimizedStructLayoutField Field
#define P(N)
if(PassOpts->AAPipeline)
static StringRef getName(Value *V)
const SmallVectorImpl< MachineOperand > & Cond
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
static Split data
DEMANGLE_NAMESPACE_BEGIN bool starts_with(std::string_view self, char C) noexcept
std::pair< llvm::MachO::Target, std::string > UUID
static bool consume(InternalInstruction *insn, T &ptr)
Value * RHS
Value * LHS
SaveTemplateParams(AbstractManglingParser *TheParser)
ScopedTemplateParamList(AbstractManglingParser *TheParser)
void printLeft(OutputBuffer &OB) const override
ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
void match(Fn F) const
void printRight(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
bool printInitListAsType(OutputBuffer &OB, const NodeArray &Elements) const override
void match(Fn F) const
bool hasArraySlow(OutputBuffer &) const override
ArrayType(const Node *Base_, Node *Dimension_)
bool hasRHSComponentSlow(OutputBuffer &) const override
BinaryExpr(const Node *LHS_, std::string_view InfixOperator_, const Node *RHS_, Prec Prec_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
BinaryFPType(const Node *Dimension_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
BitIntType(const Node *Size_, bool Signed_)
BoolExpr(bool Value_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
void printLeft(OutputBuffer &OB) const override
BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
void match(Fn F) const
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
CallExpr(const Node *Callee_, NodeArray Args_, bool IsParen_, Prec Prec_)
CastExpr(std::string_view CastKind_, const Node *To_, const Node *From_, Prec Prec_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void printDeclarator(OutputBuffer &OB) const
ClosureTypeName(NodeArray TemplateParams_, const Node *Requires1_, NodeArray Params_, const Node *Requires2_, std::string_view Count_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_, Prec Prec_)
ConstrainedTypeTemplateParamDecl(Node *Constraint_, Node *Name_)
void printRight(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
ConversionOperatorType(const Node *Ty_)
void match(Fn F) const
CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
void printLeft(OutputBuffer &OB) const override
DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
void match(Fn F) const
void match(Fn F) const
DotSuffix(const Node *Prefix_, std::string_view Suffix_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
DtorName(const Node *Base_)
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
DynamicExceptionSpec(NodeArray Types_)
void match(Fn F) const
ElaboratedTypeSpefType(std::string_view Kind_, Node *Child_)
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
EnableIfAttr(NodeArray Conditions_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
EnclosingExpr(std::string_view Prefix_, const Node *Infix_, Prec Prec_=Prec::Primary)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
EnumLiteral(const Node *Ty_, std::string_view Integer_)
void match(Fn F) const
std::string_view getBaseName() const override
ExpandedSpecialSubstitution(SpecialSubKind SSK_)
ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)
ExplicitObjectParameter(Node *Base_)
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
ExprRequirement(const Node *Expr_, bool IsNoexcept_, const Node *TypeConstraint_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
FloatLiteralImpl(std::string_view Contents_)
void printLeft(OutputBuffer &OB) const override
FoldExpr(bool IsLeftFold_, std::string_view OperatorName_, const Node *Pack_, const Node *Init_)
void match(Fn F) const
void printRight(OutputBuffer &OB) const override
Qualifiers getCVQuals() const
FunctionRefQual getRefQual() const
const Node * getAttrs() const
const Node * getReturnType() const
bool hasRHSComponentSlow(OutputBuffer &) const override
const Node * getRequires() const
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
const Node * getName() const
bool hasFunctionSlow(OutputBuffer &) const override
FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_, const Node *Attrs_, const Node *Requires_, Qualifiers CVQuals_, FunctionRefQual RefQual_)
NodeArray getParams() const
void printLeft(OutputBuffer &OB) const override
FunctionParam(std::string_view Number_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_, FunctionRefQual RefQual_, const Node *ExceptionSpec_)
bool hasRHSComponentSlow(OutputBuffer &) const override
void printRight(OutputBuffer &OB) const override
void match(Fn F) const
bool hasFunctionSlow(OutputBuffer &) const override
GlobalQualifiedName(Node *Child_)
std::string_view getBaseName() const override
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
InitListExpr(const Node *Ty_, NodeArray Inits_)
std::string_view value() const
IntegerLiteral(std::string_view Type_, std::string_view Value_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
LambdaExpr(const Node *Type_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
void match(Fn F) const
LiteralOperator(const Node *OpName_)
void printLeft(OutputBuffer &OB) const override
MemberExpr(const Node *LHS_, std::string_view Kind_, const Node *RHS_, Prec Prec_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
NameType(std::string_view Name_)
std::string_view getBaseName() const override
std::string_view getName() const
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
NestedRequirement(const Node *Constraint_)
void match(Fn F) const
NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_, bool IsArray_, Prec Prec_)
void printLeft(OutputBuffer &OB) const override
NodeArray(Node **Elements_, size_t NumElements_)
bool empty() const
Node ** begin() const
size_t size() const
void printWithComma(OutputBuffer &OB) const
Node ** end() const
bool printAsString(OutputBuffer &OB) const
Node * operator[](size_t Idx) const
void print(OutputBuffer &OB) const
Prec getPrecedence() const
Prec
Operator precedence for expression nodes.
virtual bool printInitListAsType(OutputBuffer &, const NodeArray &) const
void visit(Fn F) const
Visit the most-derived object corresponding to this object.
void printAsOperand(OutputBuffer &OB, Prec P=Prec::Default, bool StrictlyWorse=false) const
Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_=Cache::No, Cache FunctionCache_=Cache::No)
bool hasRHSComponent(OutputBuffer &OB) const
DEMANGLE_DUMP_METHOD void dump() const
friend class OutputBuffer
bool hasFunction(OutputBuffer &OB) const
Cache
Three-way bool to track a cached value.
Node(Kind K_, Prec Precedence_=Prec::Primary, Cache RHSComponentCache_=Cache::No, Cache ArrayCache_=Cache::No, Cache FunctionCache_=Cache::No)
Cache getRHSComponentCache() const
bool hasArray(OutputBuffer &OB) const
Cache getArrayCache() const
virtual bool hasRHSComponentSlow(OutputBuffer &) const
Cache ArrayCache
Track if this node is a (possibly qualified) array type.
virtual bool hasArraySlow(OutputBuffer &) const
Kind getKind() const
virtual std::string_view getBaseName() const
virtual const Node * getSyntaxNode(OutputBuffer &) const
virtual bool hasFunctionSlow(OutputBuffer &) const
virtual ~Node()=default
Cache getFunctionCache() const
Cache RHSComponentCache
Tracks if this node has a component on its right side, in which case we need to call printRight.
Cache FunctionCache
Track if this node is a (possibly qualified) function type.
NoexceptSpec(const Node *E_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
void printRight(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
bool isObjCObject() const
ObjCProtoName(const Node *Ty_, std::string_view Protocol_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
std::string_view getProtocol() const
virtual void printRight(const Node &N)
virtual void printLeft(const Node &N)
Called by the demangler when printing the demangle tree.
PODSmallVector & operator=(PODSmallVector &&Other)
PODSmallVector(const PODSmallVector &)=delete
void push_back(const T &Elem)
bool empty() const
PODSmallVector & operator=(const PODSmallVector &)=delete
PODSmallVector(PODSmallVector &&Other)
size_t size() const
void shrinkToSize(size_t Index)
T & operator[](size_t Index)
const Node * getChild() const
ParameterPackExpansion(const Node *Child_)
void printLeft(OutputBuffer &OB) const override
ParameterPack(NodeArray Data_)
void printRight(OutputBuffer &OB) const override
bool hasArraySlow(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
const Node * getSyntaxNode(OutputBuffer &OB) const override
void match(Fn F) const
bool hasFunctionSlow(OutputBuffer &OB) const override
bool hasRHSComponentSlow(OutputBuffer &OB) const override
PixelVectorType(const Node *Dimension_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_, std::string_view Offset_, Prec Prec_)
void match(Fn F) const
void printRight(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
bool hasRHSComponentSlow(OutputBuffer &OB) const override
PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
bool hasRHSComponentSlow(OutputBuffer &OB) const override
PointerType(const Node *Pointee_)
void match(Fn F) const
const Node * getPointee() const
void printRight(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
PostfixExpr(const Node *Child_, std::string_view Operator_, Prec Prec_)
void printLeft(OutputBuffer &OB) const override
PostfixQualifiedType(const Node *Ty_, std::string_view Postfix_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
PrefixExpr(std::string_view Prefix_, Node *Child_, Prec Prec_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
bool hasFunctionSlow(OutputBuffer &OB) const override
QualType(const Node *Child_, Qualifiers Quals_)
void printLeft(OutputBuffer &OB) const override
const Qualifiers Quals
void printQuals(OutputBuffer &OB) const
Qualifiers getQuals() const
const Node * Child
void printRight(OutputBuffer &OB) const override
const Node * getChild() const
bool hasRHSComponentSlow(OutputBuffer &OB) const override
bool hasArraySlow(OutputBuffer &OB) const override
void match(Fn F) const
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
std::string_view getBaseName() const override
QualifiedName(const Node *Qualifier_, const Node *Name_)
void printLeft(OutputBuffer &OB) const override
bool hasRHSComponentSlow(OutputBuffer &OB) const override
ReferenceType(const Node *Pointee_, ReferenceKind RK_)
void printRight(OutputBuffer &OB) const override
void match(Fn F) const
void match(Fn F) const
RequiresExpr(NodeArray Parameters_, NodeArray Requirements_)
void printLeft(OutputBuffer &OB) const override
SizeofParamPackExpr(const Node *Pack_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
SpecialName(std::string_view Special_, const Node *Child_)
void match(Fn F) const
void match(Fn F) const
std::string_view getBaseName() const override
SpecialSubstitution(SpecialSubKind SSK_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
StringLiteral(const Node *Type_)
void printLeft(OutputBuffer &OB) const override
StructuredBindingName(NodeArray Bindings_)
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
SubobjectExpr(const Node *Type_, const Node *SubExpr_, std::string_view Offset_, NodeArray UnionSelectors_, bool OnePastTheEnd_)
void printLeft(OutputBuffer &OB) const override
SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
NodeArray getParams()
TemplateArgs(NodeArray Params_, Node *Requires_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
A variadic template argument.
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
TemplateArgumentPack(NodeArray Elements_)
NodeArray getElements() const
void printRight(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
TemplateParamPackDecl(Node *Param_)
TemplateParamQualifiedArg(Node *Param_, Node *Arg_)
void printLeft(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
TemplateTemplateParamDecl(Node *Name_, NodeArray Params_, Node *Requires_)
void printRight(OutputBuffer &OB) const override
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
ThrowExpr(const Node *Op_)
TransformedType(std::string_view Transform_, Node *BaseType_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
TypeRequirement(const Node *Type_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
TypeTemplateParamDecl(Node *Name_)
void printRight(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
UnnamedTypeName(std::string_view Count_)
VectorType(const Node *BaseType_, const Node *Dimension_)
const Node * getDimension() const
void printLeft(OutputBuffer &OB) const override
const Node * getBaseType() const
void match(Fn F) const
VendorExtQualType(const Node *Ty_, std::string_view Ext_, const Node *TA_)
void printLeft(OutputBuffer &OB) const override
std::string_view getExt() const
const Node * getTA() const
void match(Fn F) const
const Node * getTy() const
constexpr Node::Kind getFloatLiteralKind(float *)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869
#define N
void printLeft(OutputBuffer &OB) const override
std::string_view Tag
AbiTagAttr(Node *Base_, std::string_view Tag_)
void match(Fn F) const
std::string_view getBaseName() const override
Holds some extra information about a <name> that is being parsed.
NameState(AbstractManglingParser *Enclosing)
constexpr OperatorInfo(const char(&E)[3], OIKind K, bool F, Node::Prec P, const char *N)
bool operator<(const OperatorInfo &Other) const
bool operator==(const char *Peek) const
bool operator!=(const char *Peek) const
bool operator<(const char *Peek) const
bool parseModuleNameOpt(ModuleName *&Module)
PODSmallVector< Node *, 32 > Subs
PODSmallVector< Node *, 8 > TemplateParamList
void reset(const char *First_, const char *Last_)
PODSmallVector< ForwardTemplateReference *, 4 > ForwardTemplateRefs
PODSmallVector< Node *, 32 > Names
Node * parseTemplateArgs(bool TagTemplates=false)
Node * parseType()
Parse the <type> production.
Node * parseTemplateParamDecl(TemplateParamList *Params)
Node * parsePrefixExpr(std::string_view Kind, Node::Prec Prec)
Node * parseUnresolvedName(bool Global)
Parse the <unresolved-name> production.
Node * parsePointerToMemberConversionExpr(Node::Prec Prec)
bool resolveForwardTemplateRefs(NameState &State)
Node * parseIntegerLiteral(std::string_view Lit)
Node * make(Args &&... args)
bool parseSeqId(size_t *Out)
Node * parseEncoding(bool ParseParams=true)
Node * parseName(NameState *State=nullptr)
Parse the <name> production>
Node * parseBinaryExpr(std::string_view Kind, Node::Prec Prec)
std::string_view parseNumber(bool AllowNegative=false)
TemplateParamList OuterTemplateParams
Node * parse(bool ParseParams=true)
Top-level entry point into the parser.
static const OperatorInfo Ops[]
NodeArray makeNodeArray(It begin, It end)
Node * parseLocalName(NameState *State)
AbstractManglingParser(const char *First_, const char *Last_)
char look(unsigned Lookahead=0) const
bool parsePositiveInteger(size_t *Out)
Node * parseCtorDtorName(Node *&SoFar, NameState *State)
Node * parseExpr()
Parse the <expression> production.
Node * parseAbiTags(Node *N)
Node * parseNestedName(NameState *State)
unsigned NumSyntheticTemplateParameters[3]
Node * parseSourceName(NameState *State)
Node * parseUnscopedName(NameState *State, bool *isSubstName)
bool consumeIf(std::string_view S)
Node * parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module)
std::string_view parseBareSourceName()
NodeArray popTrailingNodeArray(size_t FromPosition)
PODSmallVector< TemplateParamList *, 4 > TemplateParams
const OperatorInfo * parseOperatorEncoding()
Node * parseOperatorName(NameState *State)
Node * parseUnnamedTypeName(NameState *State)
static const size_t NumOps
static const size_t mangled_size
static const size_t max_demangled_size
static constexpr const char * spec
static constexpr const char * spec
static const size_t mangled_size
static const size_t max_demangled_size
static const size_t max_demangled_size
static constexpr const char * spec
A forward-reference to a template argument that was not known at the point where the template paramet...
const Node * getSyntaxNode(OutputBuffer &OB) const override
bool hasRHSComponentSlow(OutputBuffer &OB) const override
void printLeft(OutputBuffer &OB) const override
bool hasFunctionSlow(OutputBuffer &OB) const override
bool hasArraySlow(OutputBuffer &OB) const override
void printRight(OutputBuffer &OB) const override
ForwardTemplateReference(size_t Index_)
void match(Fn F) const =delete
LocalName(Node *Encoding_, Node *Entity_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
std::string_view getBaseName() const override
MemberLikeFriendName(Node *Qual_, Node *Name_)
void printLeft(OutputBuffer &OB) const override
std::string_view getBaseName() const override
ModuleName * Module
void printLeft(OutputBuffer &OB) const override
ModuleEntity(ModuleName *Module_, Node *Name_)
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_=false)
ModuleName * Parent
void printLeft(OutputBuffer &OB) const override
std::string_view getBaseName() const override
NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
void match(Fn F) const
std::string_view getBaseName() const override
NestedName(Node *Qual_, Node *Name_)
void printLeft(OutputBuffer &OB) const override
void match(Fn F) const
void match(Fn F) const
void printLeft(OutputBuffer &OB) const override
NodeArrayNode(NodeArray Array_)
Determine the kind of a node from its type.