blob: 9e9d183da7c2a0ed24f5b8ce3f1009fb841f011c [file] [log] [blame]
Richard Smithc20d1442018-08-20 20:14:49 +00001//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// WARNING: This file defines its contents within an anonymous namespace. It
11// should not be included anywhere other than cxa_demangle.h.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LIBCXX_DEMANGLE_ITANIUMDEMANGLE_H
16#define LIBCXX_DEMANGLE_ITANIUMDEMANGLE_H
17
18// FIXME: (possibly) incomplete list of features that clang mangles that this
19// file does not yet support:
20// - C++ modules TS
21
22#include "Compiler.h"
23#include "StringView.h"
24#include "Utility.h"
25
26#include <cassert>
27#include <cctype>
28#include <cstdio>
29#include <cstdlib>
30#include <cstring>
31#include <numeric>
32#include <utility>
33
34#define FOR_EACH_NODE_KIND(X) \
35 X(NodeArrayNode) \
36 X(DotSuffix) \
37 X(VendorExtQualType) \
38 X(QualType) \
39 X(ConversionOperatorType) \
40 X(PostfixQualifiedType) \
41 X(ElaboratedTypeSpefType) \
42 X(NameType) \
43 X(AbiTagAttr) \
44 X(EnableIfAttr) \
45 X(ObjCProtoName) \
46 X(PointerType) \
47 X(ReferenceType) \
48 X(PointerToMemberType) \
49 X(ArrayType) \
50 X(FunctionType) \
51 X(NoexceptSpec) \
52 X(DynamicExceptionSpec) \
53 X(FunctionEncoding) \
54 X(LiteralOperator) \
55 X(SpecialName) \
56 X(CtorVtableSpecialName) \
57 X(QualifiedName) \
58 X(NestedName) \
59 X(LocalName) \
60 X(VectorType) \
61 X(PixelVectorType) \
62 X(ParameterPack) \
63 X(TemplateArgumentPack) \
64 X(ParameterPackExpansion) \
65 X(TemplateArgs) \
66 X(ForwardTemplateReference) \
67 X(NameWithTemplateArgs) \
68 X(GlobalQualifiedName) \
69 X(StdQualifiedName) \
70 X(ExpandedSpecialSubstitution) \
71 X(SpecialSubstitution) \
72 X(CtorDtorName) \
73 X(DtorName) \
74 X(UnnamedTypeName) \
75 X(ClosureTypeName) \
76 X(StructuredBindingName) \
77 X(BinaryExpr) \
78 X(ArraySubscriptExpr) \
79 X(PostfixExpr) \
80 X(ConditionalExpr) \
81 X(MemberExpr) \
82 X(EnclosingExpr) \
83 X(CastExpr) \
84 X(SizeofParamPackExpr) \
85 X(CallExpr) \
86 X(NewExpr) \
87 X(DeleteExpr) \
88 X(PrefixExpr) \
89 X(FunctionParam) \
90 X(ConversionExpr) \
91 X(InitListExpr) \
92 X(FoldExpr) \
93 X(ThrowExpr) \
94 X(BoolExpr) \
95 X(IntegerCastExpr) \
96 X(IntegerLiteral) \
97 X(FloatLiteral) \
98 X(DoubleLiteral) \
99 X(LongDoubleLiteral) \
100 X(BracedExpr) \
101 X(BracedRangeExpr)
102
103namespace {
104namespace itanium_demangle {
105// Base class of all AST nodes. The AST is built by the parser, then is
106// traversed by the printLeft/Right functions to produce a demangled string.
107class Node {
108public:
109 enum Kind : unsigned char {
110#define ENUMERATOR(NodeKind) K ## NodeKind,
111 FOR_EACH_NODE_KIND(ENUMERATOR)
112#undef ENUMERATOR
113 };
114
115 /// Three-way bool to track a cached value. Unknown is possible if this node
116 /// has an unexpanded parameter pack below it that may affect this cache.
117 enum class Cache : unsigned char { Yes, No, Unknown, };
118
119private:
120 Kind K;
121
122 // FIXME: Make these protected.
123public:
124 /// Tracks if this node has a component on its right side, in which case we
125 /// need to call printRight.
126 Cache RHSComponentCache;
127
128 /// Track if this node is a (possibly qualified) array type. This can affect
129 /// how we format the output string.
130 Cache ArrayCache;
131
132 /// Track if this node is a (possibly qualified) function type. This can
133 /// affect how we format the output string.
134 Cache FunctionCache;
135
136public:
137 Node(Kind K_, Cache RHSComponentCache_ = Cache::No,
138 Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No)
139 : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),
140 FunctionCache(FunctionCache_) {}
141
142 /// Visit the most-derived object corresponding to this object.
143 template<typename Fn> void visit(Fn F) const;
144
145 // The following function is provided by all derived classes:
146 //
147 // Call F with arguments that, when passed to the constructor of this node,
148 // would construct an equivalent node.
149 //template<typename Fn> void match(Fn F) const;
150
151 bool hasRHSComponent(OutputStream &S) const {
152 if (RHSComponentCache != Cache::Unknown)
153 return RHSComponentCache == Cache::Yes;
154 return hasRHSComponentSlow(S);
155 }
156
157 bool hasArray(OutputStream &S) const {
158 if (ArrayCache != Cache::Unknown)
159 return ArrayCache == Cache::Yes;
160 return hasArraySlow(S);
161 }
162
163 bool hasFunction(OutputStream &S) const {
164 if (FunctionCache != Cache::Unknown)
165 return FunctionCache == Cache::Yes;
166 return hasFunctionSlow(S);
167 }
168
169 Kind getKind() const { return K; }
170
171 virtual bool hasRHSComponentSlow(OutputStream &) const { return false; }
172 virtual bool hasArraySlow(OutputStream &) const { return false; }
173 virtual bool hasFunctionSlow(OutputStream &) const { return false; }
174
175 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
176 // get at a node that actually represents some concrete syntax.
177 virtual const Node *getSyntaxNode(OutputStream &) const {
178 return this;
179 }
180
181 void print(OutputStream &S) const {
182 printLeft(S);
183 if (RHSComponentCache != Cache::No)
184 printRight(S);
185 }
186
187 // Print the "left" side of this Node into OutputStream.
188 virtual void printLeft(OutputStream &) const = 0;
189
190 // Print the "right". This distinction is necessary to represent C++ types
191 // that appear on the RHS of their subtype, such as arrays or functions.
192 // Since most types don't have such a component, provide a default
193 // implementation.
194 virtual void printRight(OutputStream &) const {}
195
196 virtual StringView getBaseName() const { return StringView(); }
197
198 // Silence compiler warnings, this dtor will never be called.
199 virtual ~Node() = default;
200
201#ifndef NDEBUG
202 DUMP_METHOD void dump() const;
203#endif
204};
205
206class NodeArray {
207 Node **Elements;
208 size_t NumElements;
209
210public:
211 NodeArray() : Elements(nullptr), NumElements(0) {}
212 NodeArray(Node **Elements_, size_t NumElements_)
213 : Elements(Elements_), NumElements(NumElements_) {}
214
215 bool empty() const { return NumElements == 0; }
216 size_t size() const { return NumElements; }
217
218 Node **begin() const { return Elements; }
219 Node **end() const { return Elements + NumElements; }
220
221 Node *operator[](size_t Idx) const { return Elements[Idx]; }
222
223 void printWithComma(OutputStream &S) const {
224 bool FirstElement = true;
225 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
226 size_t BeforeComma = S.getCurrentPosition();
227 if (!FirstElement)
228 S += ", ";
229 size_t AfterComma = S.getCurrentPosition();
230 Elements[Idx]->print(S);
231
232 // Elements[Idx] is an empty parameter pack expansion, we should erase the
233 // comma we just printed.
234 if (AfterComma == S.getCurrentPosition()) {
235 S.setCurrentPosition(BeforeComma);
236 continue;
237 }
238
239 FirstElement = false;
240 }
241 }
242};
243
244struct NodeArrayNode : Node {
245 NodeArray Array;
246 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
247
248 template<typename Fn> void match(Fn F) const { F(Array); }
249
250 void printLeft(OutputStream &S) const override {
251 Array.printWithComma(S);
252 }
253};
254
255class DotSuffix final : public Node {
256 const Node *Prefix;
257 const StringView Suffix;
258
259public:
260 DotSuffix(const Node *Prefix_, StringView Suffix_)
261 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
262
263 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
264
265 void printLeft(OutputStream &s) const override {
266 Prefix->print(s);
267 s += " (";
268 s += Suffix;
269 s += ")";
270 }
271};
272
273class VendorExtQualType final : public Node {
274 const Node *Ty;
275 StringView Ext;
276
277public:
278 VendorExtQualType(const Node *Ty_, StringView Ext_)
279 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {}
280
281 template<typename Fn> void match(Fn F) const { F(Ty, Ext); }
282
283 void printLeft(OutputStream &S) const override {
284 Ty->print(S);
285 S += " ";
286 S += Ext;
287 }
288};
289
290enum FunctionRefQual : unsigned char {
291 FrefQualNone,
292 FrefQualLValue,
293 FrefQualRValue,
294};
295
296enum Qualifiers {
297 QualNone = 0,
298 QualConst = 0x1,
299 QualVolatile = 0x2,
300 QualRestrict = 0x4,
301};
302
303inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
304 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
305}
306
307class QualType : public Node {
308protected:
309 const Qualifiers Quals;
310 const Node *Child;
311
312 void printQuals(OutputStream &S) const {
313 if (Quals & QualConst)
314 S += " const";
315 if (Quals & QualVolatile)
316 S += " volatile";
317 if (Quals & QualRestrict)
318 S += " restrict";
319 }
320
321public:
322 QualType(const Node *Child_, Qualifiers Quals_)
323 : Node(KQualType, Child_->RHSComponentCache,
324 Child_->ArrayCache, Child_->FunctionCache),
325 Quals(Quals_), Child(Child_) {}
326
327 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
328
329 bool hasRHSComponentSlow(OutputStream &S) const override {
330 return Child->hasRHSComponent(S);
331 }
332 bool hasArraySlow(OutputStream &S) const override {
333 return Child->hasArray(S);
334 }
335 bool hasFunctionSlow(OutputStream &S) const override {
336 return Child->hasFunction(S);
337 }
338
339 void printLeft(OutputStream &S) const override {
340 Child->printLeft(S);
341 printQuals(S);
342 }
343
344 void printRight(OutputStream &S) const override { Child->printRight(S); }
345};
346
347class ConversionOperatorType final : public Node {
348 const Node *Ty;
349
350public:
351 ConversionOperatorType(const Node *Ty_)
352 : Node(KConversionOperatorType), Ty(Ty_) {}
353
354 template<typename Fn> void match(Fn F) const { F(Ty); }
355
356 void printLeft(OutputStream &S) const override {
357 S += "operator ";
358 Ty->print(S);
359 }
360};
361
362class PostfixQualifiedType final : public Node {
363 const Node *Ty;
364 const StringView Postfix;
365
366public:
367 PostfixQualifiedType(Node *Ty_, StringView Postfix_)
368 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
369
370 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
371
372 void printLeft(OutputStream &s) const override {
373 Ty->printLeft(s);
374 s += Postfix;
375 }
376};
377
378class NameType final : public Node {
379 const StringView Name;
380
381public:
382 NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
383
384 template<typename Fn> void match(Fn F) const { F(Name); }
385
386 StringView getName() const { return Name; }
387 StringView getBaseName() const override { return Name; }
388
389 void printLeft(OutputStream &s) const override { s += Name; }
390};
391
392class ElaboratedTypeSpefType : public Node {
393 StringView Kind;
394 Node *Child;
395public:
396 ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
397 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
398
399 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
400
401 void printLeft(OutputStream &S) const override {
402 S += Kind;
403 S += ' ';
404 Child->print(S);
405 }
406};
407
408struct AbiTagAttr : Node {
409 Node *Base;
410 StringView Tag;
411
412 AbiTagAttr(Node* Base_, StringView Tag_)
413 : Node(KAbiTagAttr, Base_->RHSComponentCache,
414 Base_->ArrayCache, Base_->FunctionCache),
415 Base(Base_), Tag(Tag_) {}
416
417 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
418
419 void printLeft(OutputStream &S) const override {
420 Base->printLeft(S);
421 S += "[abi:";
422 S += Tag;
423 S += "]";
424 }
425};
426
427class EnableIfAttr : public Node {
428 NodeArray Conditions;
429public:
430 EnableIfAttr(NodeArray Conditions_)
431 : Node(KEnableIfAttr), Conditions(Conditions_) {}
432
433 template<typename Fn> void match(Fn F) const { F(Conditions); }
434
435 void printLeft(OutputStream &S) const override {
436 S += " [enable_if:";
437 Conditions.printWithComma(S);
438 S += ']';
439 }
440};
441
442class ObjCProtoName : public Node {
443 const Node *Ty;
444 StringView Protocol;
445
446 friend class PointerType;
447
448public:
449 ObjCProtoName(const Node *Ty_, StringView Protocol_)
450 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
451
452 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
453
454 bool isObjCObject() const {
455 return Ty->getKind() == KNameType &&
456 static_cast<const NameType *>(Ty)->getName() == "objc_object";
457 }
458
459 void printLeft(OutputStream &S) const override {
460 Ty->print(S);
461 S += "<";
462 S += Protocol;
463 S += ">";
464 }
465};
466
467class PointerType final : public Node {
468 const Node *Pointee;
469
470public:
471 PointerType(const Node *Pointee_)
472 : Node(KPointerType, Pointee_->RHSComponentCache),
473 Pointee(Pointee_) {}
474
475 template<typename Fn> void match(Fn F) const { F(Pointee); }
476
477 bool hasRHSComponentSlow(OutputStream &S) const override {
478 return Pointee->hasRHSComponent(S);
479 }
480
481 void printLeft(OutputStream &s) const override {
482 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
483 if (Pointee->getKind() != KObjCProtoName ||
484 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
485 Pointee->printLeft(s);
486 if (Pointee->hasArray(s))
487 s += " ";
488 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
489 s += "(";
490 s += "*";
491 } else {
492 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
493 s += "id<";
494 s += objcProto->Protocol;
495 s += ">";
496 }
497 }
498
499 void printRight(OutputStream &s) const override {
500 if (Pointee->getKind() != KObjCProtoName ||
501 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
502 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
503 s += ")";
504 Pointee->printRight(s);
505 }
506 }
507};
508
509enum class ReferenceKind {
510 LValue,
511 RValue,
512};
513
514// Represents either a LValue or an RValue reference type.
515class ReferenceType : public Node {
516 const Node *Pointee;
517 ReferenceKind RK;
518
519 mutable bool Printing = false;
520
521 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
522 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
523 // other combination collapses to a lvalue ref.
524 std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const {
525 auto SoFar = std::make_pair(RK, Pointee);
526 for (;;) {
527 const Node *SN = SoFar.second->getSyntaxNode(S);
528 if (SN->getKind() != KReferenceType)
529 break;
530 auto *RT = static_cast<const ReferenceType *>(SN);
531 SoFar.second = RT->Pointee;
532 SoFar.first = std::min(SoFar.first, RT->RK);
533 }
534 return SoFar;
535 }
536
537public:
538 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
539 : Node(KReferenceType, Pointee_->RHSComponentCache),
540 Pointee(Pointee_), RK(RK_) {}
541
542 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
543
544 bool hasRHSComponentSlow(OutputStream &S) const override {
545 return Pointee->hasRHSComponent(S);
546 }
547
548 void printLeft(OutputStream &s) const override {
549 if (Printing)
550 return;
551 SwapAndRestore<bool> SavePrinting(Printing, true);
552 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
553 Collapsed.second->printLeft(s);
554 if (Collapsed.second->hasArray(s))
555 s += " ";
556 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
557 s += "(";
558
559 s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
560 }
561 void printRight(OutputStream &s) const override {
562 if (Printing)
563 return;
564 SwapAndRestore<bool> SavePrinting(Printing, true);
565 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
566 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
567 s += ")";
568 Collapsed.second->printRight(s);
569 }
570};
571
572class PointerToMemberType final : public Node {
573 const Node *ClassType;
574 const Node *MemberType;
575
576public:
577 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
578 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
579 ClassType(ClassType_), MemberType(MemberType_) {}
580
581 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
582
583 bool hasRHSComponentSlow(OutputStream &S) const override {
584 return MemberType->hasRHSComponent(S);
585 }
586
587 void printLeft(OutputStream &s) const override {
588 MemberType->printLeft(s);
589 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
590 s += "(";
591 else
592 s += " ";
593 ClassType->print(s);
594 s += "::*";
595 }
596
597 void printRight(OutputStream &s) const override {
598 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
599 s += ")";
600 MemberType->printRight(s);
601 }
602};
603
604class NodeOrString {
605 const void *First;
606 const void *Second;
607
608public:
609 /* implicit */ NodeOrString(StringView Str) {
610 const char *FirstChar = Str.begin();
611 const char *SecondChar = Str.end();
612 if (SecondChar == nullptr) {
613 assert(FirstChar == SecondChar);
614 ++FirstChar, ++SecondChar;
615 }
616 First = static_cast<const void *>(FirstChar);
617 Second = static_cast<const void *>(SecondChar);
618 }
619
620 /* implicit */ NodeOrString(Node *N)
621 : First(static_cast<const void *>(N)), Second(nullptr) {}
622 NodeOrString() : First(nullptr), Second(nullptr) {}
623
624 bool isString() const { return Second && First; }
625 bool isNode() const { return First && !Second; }
626 bool isEmpty() const { return !First && !Second; }
627
628 StringView asString() const {
629 assert(isString());
630 return StringView(static_cast<const char *>(First),
631 static_cast<const char *>(Second));
632 }
633
634 const Node *asNode() const {
635 assert(isNode());
636 return static_cast<const Node *>(First);
637 }
638};
639
640class ArrayType final : public Node {
641 const Node *Base;
642 NodeOrString Dimension;
643
644public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +0000645 ArrayType(const Node *Base_, NodeOrString Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000646 : Node(KArrayType,
647 /*RHSComponentCache=*/Cache::Yes,
648 /*ArrayCache=*/Cache::Yes),
649 Base(Base_), Dimension(Dimension_) {}
650
651 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
652
653 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
654 bool hasArraySlow(OutputStream &) const override { return true; }
655
656 void printLeft(OutputStream &S) const override { Base->printLeft(S); }
657
658 void printRight(OutputStream &S) const override {
659 if (S.back() != ']')
660 S += " ";
661 S += "[";
662 if (Dimension.isString())
663 S += Dimension.asString();
664 else if (Dimension.isNode())
665 Dimension.asNode()->print(S);
666 S += "]";
667 Base->printRight(S);
668 }
669};
670
671class FunctionType final : public Node {
672 const Node *Ret;
673 NodeArray Params;
674 Qualifiers CVQuals;
675 FunctionRefQual RefQual;
676 const Node *ExceptionSpec;
677
678public:
679 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
680 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
681 : Node(KFunctionType,
682 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
683 /*FunctionCache=*/Cache::Yes),
684 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
685 ExceptionSpec(ExceptionSpec_) {}
686
687 template<typename Fn> void match(Fn F) const {
688 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
689 }
690
691 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
692 bool hasFunctionSlow(OutputStream &) const override { return true; }
693
694 // Handle C++'s ... quirky decl grammar by using the left & right
695 // distinction. Consider:
696 // int (*f(float))(char) {}
697 // f is a function that takes a float and returns a pointer to a function
698 // that takes a char and returns an int. If we're trying to print f, start
699 // by printing out the return types's left, then print our parameters, then
700 // finally print right of the return type.
701 void printLeft(OutputStream &S) const override {
702 Ret->printLeft(S);
703 S += " ";
704 }
705
706 void printRight(OutputStream &S) const override {
707 S += "(";
708 Params.printWithComma(S);
709 S += ")";
710 Ret->printRight(S);
711
712 if (CVQuals & QualConst)
713 S += " const";
714 if (CVQuals & QualVolatile)
715 S += " volatile";
716 if (CVQuals & QualRestrict)
717 S += " restrict";
718
719 if (RefQual == FrefQualLValue)
720 S += " &";
721 else if (RefQual == FrefQualRValue)
722 S += " &&";
723
724 if (ExceptionSpec != nullptr) {
725 S += ' ';
726 ExceptionSpec->print(S);
727 }
728 }
729};
730
731class NoexceptSpec : public Node {
732 const Node *E;
733public:
734 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
735
736 template<typename Fn> void match(Fn F) const { F(E); }
737
738 void printLeft(OutputStream &S) const override {
739 S += "noexcept(";
740 E->print(S);
741 S += ")";
742 }
743};
744
745class DynamicExceptionSpec : public Node {
746 NodeArray Types;
747public:
748 DynamicExceptionSpec(NodeArray Types_)
749 : Node(KDynamicExceptionSpec), Types(Types_) {}
750
751 template<typename Fn> void match(Fn F) const { F(Types); }
752
753 void printLeft(OutputStream &S) const override {
754 S += "throw(";
755 Types.printWithComma(S);
756 S += ')';
757 }
758};
759
760class FunctionEncoding final : public Node {
761 const Node *Ret;
762 const Node *Name;
763 NodeArray Params;
764 const Node *Attrs;
765 Qualifiers CVQuals;
766 FunctionRefQual RefQual;
767
768public:
769 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
770 const Node *Attrs_, Qualifiers CVQuals_,
771 FunctionRefQual RefQual_)
772 : Node(KFunctionEncoding,
773 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
774 /*FunctionCache=*/Cache::Yes),
775 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
776 CVQuals(CVQuals_), RefQual(RefQual_) {}
777
778 template<typename Fn> void match(Fn F) const {
779 F(Ret, Name, Params, Attrs, CVQuals, RefQual);
780 }
781
782 Qualifiers getCVQuals() const { return CVQuals; }
783 FunctionRefQual getRefQual() const { return RefQual; }
784 NodeArray getParams() const { return Params; }
785 const Node *getReturnType() const { return Ret; }
786
787 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
788 bool hasFunctionSlow(OutputStream &) const override { return true; }
789
790 const Node *getName() const { return Name; }
791
792 void printLeft(OutputStream &S) const override {
793 if (Ret) {
794 Ret->printLeft(S);
795 if (!Ret->hasRHSComponent(S))
796 S += " ";
797 }
798 Name->print(S);
799 }
800
801 void printRight(OutputStream &S) const override {
802 S += "(";
803 Params.printWithComma(S);
804 S += ")";
805 if (Ret)
806 Ret->printRight(S);
807
808 if (CVQuals & QualConst)
809 S += " const";
810 if (CVQuals & QualVolatile)
811 S += " volatile";
812 if (CVQuals & QualRestrict)
813 S += " restrict";
814
815 if (RefQual == FrefQualLValue)
816 S += " &";
817 else if (RefQual == FrefQualRValue)
818 S += " &&";
819
820 if (Attrs != nullptr)
821 Attrs->print(S);
822 }
823};
824
825class LiteralOperator : public Node {
826 const Node *OpName;
827
828public:
829 LiteralOperator(const Node *OpName_)
830 : Node(KLiteralOperator), OpName(OpName_) {}
831
832 template<typename Fn> void match(Fn F) const { F(OpName); }
833
834 void printLeft(OutputStream &S) const override {
835 S += "operator\"\" ";
836 OpName->print(S);
837 }
838};
839
840class SpecialName final : public Node {
841 const StringView Special;
842 const Node *Child;
843
844public:
845 SpecialName(StringView Special_, const Node *Child_)
846 : Node(KSpecialName), Special(Special_), Child(Child_) {}
847
848 template<typename Fn> void match(Fn F) const { F(Special, Child); }
849
850 void printLeft(OutputStream &S) const override {
851 S += Special;
852 Child->print(S);
853 }
854};
855
856class CtorVtableSpecialName final : public Node {
857 const Node *FirstType;
858 const Node *SecondType;
859
860public:
861 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
862 : Node(KCtorVtableSpecialName),
863 FirstType(FirstType_), SecondType(SecondType_) {}
864
865 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
866
867 void printLeft(OutputStream &S) const override {
868 S += "construction vtable for ";
869 FirstType->print(S);
870 S += "-in-";
871 SecondType->print(S);
872 }
873};
874
875struct NestedName : Node {
876 Node *Qual;
877 Node *Name;
878
879 NestedName(Node *Qual_, Node *Name_)
880 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
881
882 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
883
884 StringView getBaseName() const override { return Name->getBaseName(); }
885
886 void printLeft(OutputStream &S) const override {
887 Qual->print(S);
888 S += "::";
889 Name->print(S);
890 }
891};
892
893struct LocalName : Node {
894 Node *Encoding;
895 Node *Entity;
896
897 LocalName(Node *Encoding_, Node *Entity_)
898 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
899
900 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
901
902 void printLeft(OutputStream &S) const override {
903 Encoding->print(S);
904 S += "::";
905 Entity->print(S);
906 }
907};
908
909class QualifiedName final : public Node {
910 // qualifier::name
911 const Node *Qualifier;
912 const Node *Name;
913
914public:
915 QualifiedName(const Node *Qualifier_, const Node *Name_)
916 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
917
918 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
919
920 StringView getBaseName() const override { return Name->getBaseName(); }
921
922 void printLeft(OutputStream &S) const override {
923 Qualifier->print(S);
924 S += "::";
925 Name->print(S);
926 }
927};
928
929class VectorType final : public Node {
930 const Node *BaseType;
931 const NodeOrString Dimension;
932
933public:
934 VectorType(const Node *BaseType_, NodeOrString Dimension_)
935 : Node(KVectorType), BaseType(BaseType_),
936 Dimension(Dimension_) {}
937
938 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
939
940 void printLeft(OutputStream &S) const override {
941 BaseType->print(S);
942 S += " vector[";
943 if (Dimension.isNode())
944 Dimension.asNode()->print(S);
945 else if (Dimension.isString())
946 S += Dimension.asString();
947 S += "]";
948 }
949};
950
951class PixelVectorType final : public Node {
952 const NodeOrString Dimension;
953
954public:
955 PixelVectorType(NodeOrString Dimension_)
956 : Node(KPixelVectorType), Dimension(Dimension_) {}
957
958 template<typename Fn> void match(Fn F) const { F(Dimension); }
959
960 void printLeft(OutputStream &S) const override {
961 // FIXME: This should demangle as "vector pixel".
962 S += "pixel vector[";
963 S += Dimension.asString();
964 S += "]";
965 }
966};
967
968/// An unexpanded parameter pack (either in the expression or type context). If
969/// this AST is correct, this node will have a ParameterPackExpansion node above
970/// it.
971///
972/// This node is created when some <template-args> are found that apply to an
973/// <encoding>, and is stored in the TemplateParams table. In order for this to
974/// appear in the final AST, it has to referenced via a <template-param> (ie,
975/// T_).
976class ParameterPack final : public Node {
977 NodeArray Data;
978
979 // Setup OutputStream for a pack expansion unless we're already expanding one.
980 void initializePackExpansion(OutputStream &S) const {
981 if (S.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
982 S.CurrentPackMax = static_cast<unsigned>(Data.size());
983 S.CurrentPackIndex = 0;
984 }
985 }
986
987public:
988 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
989 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
990 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
991 return P->ArrayCache == Cache::No;
992 }))
993 ArrayCache = Cache::No;
994 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
995 return P->FunctionCache == Cache::No;
996 }))
997 FunctionCache = Cache::No;
998 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
999 return P->RHSComponentCache == Cache::No;
1000 }))
1001 RHSComponentCache = Cache::No;
1002 }
1003
1004 template<typename Fn> void match(Fn F) const { F(Data); }
1005
1006 bool hasRHSComponentSlow(OutputStream &S) const override {
1007 initializePackExpansion(S);
1008 size_t Idx = S.CurrentPackIndex;
1009 return Idx < Data.size() && Data[Idx]->hasRHSComponent(S);
1010 }
1011 bool hasArraySlow(OutputStream &S) const override {
1012 initializePackExpansion(S);
1013 size_t Idx = S.CurrentPackIndex;
1014 return Idx < Data.size() && Data[Idx]->hasArray(S);
1015 }
1016 bool hasFunctionSlow(OutputStream &S) const override {
1017 initializePackExpansion(S);
1018 size_t Idx = S.CurrentPackIndex;
1019 return Idx < Data.size() && Data[Idx]->hasFunction(S);
1020 }
1021 const Node *getSyntaxNode(OutputStream &S) const override {
1022 initializePackExpansion(S);
1023 size_t Idx = S.CurrentPackIndex;
1024 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this;
1025 }
1026
1027 void printLeft(OutputStream &S) const override {
1028 initializePackExpansion(S);
1029 size_t Idx = S.CurrentPackIndex;
1030 if (Idx < Data.size())
1031 Data[Idx]->printLeft(S);
1032 }
1033 void printRight(OutputStream &S) const override {
1034 initializePackExpansion(S);
1035 size_t Idx = S.CurrentPackIndex;
1036 if (Idx < Data.size())
1037 Data[Idx]->printRight(S);
1038 }
1039};
1040
1041/// A variadic template argument. This node represents an occurrence of
1042/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1043/// one of it's Elements is. The parser inserts a ParameterPack into the
1044/// TemplateParams table if the <template-args> this pack belongs to apply to an
1045/// <encoding>.
1046class TemplateArgumentPack final : public Node {
1047 NodeArray Elements;
1048public:
1049 TemplateArgumentPack(NodeArray Elements_)
1050 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1051
1052 template<typename Fn> void match(Fn F) const { F(Elements); }
1053
1054 NodeArray getElements() const { return Elements; }
1055
1056 void printLeft(OutputStream &S) const override {
1057 Elements.printWithComma(S);
1058 }
1059};
1060
1061/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1062/// which each have Child->ParameterPackSize elements.
1063class ParameterPackExpansion final : public Node {
1064 const Node *Child;
1065
1066public:
1067 ParameterPackExpansion(const Node *Child_)
1068 : Node(KParameterPackExpansion), Child(Child_) {}
1069
1070 template<typename Fn> void match(Fn F) const { F(Child); }
1071
1072 const Node *getChild() const { return Child; }
1073
1074 void printLeft(OutputStream &S) const override {
1075 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
1076 SwapAndRestore<unsigned> SavePackIdx(S.CurrentPackIndex, Max);
1077 SwapAndRestore<unsigned> SavePackMax(S.CurrentPackMax, Max);
1078 size_t StreamPos = S.getCurrentPosition();
1079
1080 // Print the first element in the pack. If Child contains a ParameterPack,
1081 // it will set up S.CurrentPackMax and print the first element.
1082 Child->print(S);
1083
1084 // No ParameterPack was found in Child. This can occur if we've found a pack
1085 // expansion on a <function-param>.
1086 if (S.CurrentPackMax == Max) {
1087 S += "...";
1088 return;
1089 }
1090
1091 // We found a ParameterPack, but it has no elements. Erase whatever we may
1092 // of printed.
1093 if (S.CurrentPackMax == 0) {
1094 S.setCurrentPosition(StreamPos);
1095 return;
1096 }
1097
1098 // Else, iterate through the rest of the elements in the pack.
1099 for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) {
1100 S += ", ";
1101 S.CurrentPackIndex = I;
1102 Child->print(S);
1103 }
1104 }
1105};
1106
1107class TemplateArgs final : public Node {
1108 NodeArray Params;
1109
1110public:
1111 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1112
1113 template<typename Fn> void match(Fn F) const { F(Params); }
1114
1115 NodeArray getParams() { return Params; }
1116
1117 void printLeft(OutputStream &S) const override {
1118 S += "<";
1119 Params.printWithComma(S);
1120 if (S.back() == '>')
1121 S += " ";
1122 S += ">";
1123 }
1124};
1125
Richard Smithb485b352018-08-24 23:30:26 +00001126/// A forward-reference to a template argument that was not known at the point
1127/// where the template parameter name was parsed in a mangling.
1128///
1129/// This is created when demangling the name of a specialization of a
1130/// conversion function template:
1131///
1132/// \code
1133/// struct A {
1134/// template<typename T> operator T*();
1135/// };
1136/// \endcode
1137///
1138/// When demangling a specialization of the conversion function template, we
1139/// encounter the name of the template (including the \c T) before we reach
1140/// the template argument list, so we cannot substitute the parameter name
1141/// for the corresponding argument while parsing. Instead, we create a
1142/// \c ForwardTemplateReference node that is resolved after we parse the
1143/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001144struct ForwardTemplateReference : Node {
1145 size_t Index;
1146 Node *Ref = nullptr;
1147
1148 // If we're currently printing this node. It is possible (though invalid) for
1149 // a forward template reference to refer to itself via a substitution. This
1150 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1151 // out if more than one print* function is active.
1152 mutable bool Printing = false;
1153
1154 ForwardTemplateReference(size_t Index_)
1155 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1156 Cache::Unknown),
1157 Index(Index_) {}
1158
1159 // We don't provide a matcher for these, because the value of the node is
1160 // not determined by its construction parameters, and it generally needs
1161 // special handling.
1162 template<typename Fn> void match(Fn F) const = delete;
1163
1164 bool hasRHSComponentSlow(OutputStream &S) const override {
1165 if (Printing)
1166 return false;
1167 SwapAndRestore<bool> SavePrinting(Printing, true);
1168 return Ref->hasRHSComponent(S);
1169 }
1170 bool hasArraySlow(OutputStream &S) const override {
1171 if (Printing)
1172 return false;
1173 SwapAndRestore<bool> SavePrinting(Printing, true);
1174 return Ref->hasArray(S);
1175 }
1176 bool hasFunctionSlow(OutputStream &S) const override {
1177 if (Printing)
1178 return false;
1179 SwapAndRestore<bool> SavePrinting(Printing, true);
1180 return Ref->hasFunction(S);
1181 }
1182 const Node *getSyntaxNode(OutputStream &S) const override {
1183 if (Printing)
1184 return this;
1185 SwapAndRestore<bool> SavePrinting(Printing, true);
1186 return Ref->getSyntaxNode(S);
1187 }
1188
1189 void printLeft(OutputStream &S) const override {
1190 if (Printing)
1191 return;
1192 SwapAndRestore<bool> SavePrinting(Printing, true);
1193 Ref->printLeft(S);
1194 }
1195 void printRight(OutputStream &S) const override {
1196 if (Printing)
1197 return;
1198 SwapAndRestore<bool> SavePrinting(Printing, true);
1199 Ref->printRight(S);
1200 }
1201};
1202
1203struct NameWithTemplateArgs : Node {
1204 // name<template_args>
1205 Node *Name;
1206 Node *TemplateArgs;
1207
1208 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1209 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1210
1211 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1212
1213 StringView getBaseName() const override { return Name->getBaseName(); }
1214
1215 void printLeft(OutputStream &S) const override {
1216 Name->print(S);
1217 TemplateArgs->print(S);
1218 }
1219};
1220
1221class GlobalQualifiedName final : public Node {
1222 Node *Child;
1223
1224public:
1225 GlobalQualifiedName(Node* Child_)
1226 : Node(KGlobalQualifiedName), Child(Child_) {}
1227
1228 template<typename Fn> void match(Fn F) const { F(Child); }
1229
1230 StringView getBaseName() const override { return Child->getBaseName(); }
1231
1232 void printLeft(OutputStream &S) const override {
1233 S += "::";
1234 Child->print(S);
1235 }
1236};
1237
1238struct StdQualifiedName : Node {
1239 Node *Child;
1240
1241 StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {}
1242
1243 template<typename Fn> void match(Fn F) const { F(Child); }
1244
1245 StringView getBaseName() const override { return Child->getBaseName(); }
1246
1247 void printLeft(OutputStream &S) const override {
1248 S += "std::";
1249 Child->print(S);
1250 }
1251};
1252
1253enum class SpecialSubKind {
1254 allocator,
1255 basic_string,
1256 string,
1257 istream,
1258 ostream,
1259 iostream,
1260};
1261
1262class ExpandedSpecialSubstitution final : public Node {
1263 SpecialSubKind SSK;
1264
1265public:
1266 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1267 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1268
1269 template<typename Fn> void match(Fn F) const { F(SSK); }
1270
1271 StringView getBaseName() const override {
1272 switch (SSK) {
1273 case SpecialSubKind::allocator:
1274 return StringView("allocator");
1275 case SpecialSubKind::basic_string:
1276 return StringView("basic_string");
1277 case SpecialSubKind::string:
1278 return StringView("basic_string");
1279 case SpecialSubKind::istream:
1280 return StringView("basic_istream");
1281 case SpecialSubKind::ostream:
1282 return StringView("basic_ostream");
1283 case SpecialSubKind::iostream:
1284 return StringView("basic_iostream");
1285 }
1286 _LIBCPP_UNREACHABLE();
1287 }
1288
1289 void printLeft(OutputStream &S) const override {
1290 switch (SSK) {
1291 case SpecialSubKind::allocator:
Richard Smithb485b352018-08-24 23:30:26 +00001292 S += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001293 break;
1294 case SpecialSubKind::basic_string:
Richard Smithb485b352018-08-24 23:30:26 +00001295 S += "std::basic_string";
1296 break;
Richard Smithc20d1442018-08-20 20:14:49 +00001297 case SpecialSubKind::string:
1298 S += "std::basic_string<char, std::char_traits<char>, "
1299 "std::allocator<char> >";
1300 break;
1301 case SpecialSubKind::istream:
1302 S += "std::basic_istream<char, std::char_traits<char> >";
1303 break;
1304 case SpecialSubKind::ostream:
1305 S += "std::basic_ostream<char, std::char_traits<char> >";
1306 break;
1307 case SpecialSubKind::iostream:
1308 S += "std::basic_iostream<char, std::char_traits<char> >";
1309 break;
1310 }
1311 }
1312};
1313
1314class SpecialSubstitution final : public Node {
1315public:
1316 SpecialSubKind SSK;
1317
1318 SpecialSubstitution(SpecialSubKind SSK_)
1319 : Node(KSpecialSubstitution), SSK(SSK_) {}
1320
1321 template<typename Fn> void match(Fn F) const { F(SSK); }
1322
1323 StringView getBaseName() const override {
1324 switch (SSK) {
1325 case SpecialSubKind::allocator:
1326 return StringView("allocator");
1327 case SpecialSubKind::basic_string:
1328 return StringView("basic_string");
1329 case SpecialSubKind::string:
1330 return StringView("string");
1331 case SpecialSubKind::istream:
1332 return StringView("istream");
1333 case SpecialSubKind::ostream:
1334 return StringView("ostream");
1335 case SpecialSubKind::iostream:
1336 return StringView("iostream");
1337 }
1338 _LIBCPP_UNREACHABLE();
1339 }
1340
1341 void printLeft(OutputStream &S) const override {
1342 switch (SSK) {
1343 case SpecialSubKind::allocator:
1344 S += "std::allocator";
1345 break;
1346 case SpecialSubKind::basic_string:
1347 S += "std::basic_string";
1348 break;
1349 case SpecialSubKind::string:
1350 S += "std::string";
1351 break;
1352 case SpecialSubKind::istream:
1353 S += "std::istream";
1354 break;
1355 case SpecialSubKind::ostream:
1356 S += "std::ostream";
1357 break;
1358 case SpecialSubKind::iostream:
1359 S += "std::iostream";
1360 break;
1361 }
1362 }
1363};
1364
1365class CtorDtorName final : public Node {
1366 const Node *Basename;
1367 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001368 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001369
1370public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001371 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1372 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1373 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001374
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001375 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001376
1377 void printLeft(OutputStream &S) const override {
1378 if (IsDtor)
1379 S += "~";
1380 S += Basename->getBaseName();
1381 }
1382};
1383
1384class DtorName : public Node {
1385 const Node *Base;
1386
1387public:
1388 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1389
1390 template<typename Fn> void match(Fn F) const { F(Base); }
1391
1392 void printLeft(OutputStream &S) const override {
1393 S += "~";
1394 Base->printLeft(S);
1395 }
1396};
1397
1398class UnnamedTypeName : public Node {
1399 const StringView Count;
1400
1401public:
1402 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1403
1404 template<typename Fn> void match(Fn F) const { F(Count); }
1405
1406 void printLeft(OutputStream &S) const override {
1407 S += "'unnamed";
1408 S += Count;
1409 S += "\'";
1410 }
1411};
1412
1413class ClosureTypeName : public Node {
1414 NodeArray Params;
1415 StringView Count;
1416
1417public:
1418 ClosureTypeName(NodeArray Params_, StringView Count_)
1419 : Node(KClosureTypeName), Params(Params_), Count(Count_) {}
1420
1421 template<typename Fn> void match(Fn F) const { F(Params, Count); }
1422
1423 void printLeft(OutputStream &S) const override {
1424 S += "\'lambda";
1425 S += Count;
1426 S += "\'(";
1427 Params.printWithComma(S);
1428 S += ")";
1429 }
1430};
1431
1432class StructuredBindingName : public Node {
1433 NodeArray Bindings;
1434public:
1435 StructuredBindingName(NodeArray Bindings_)
1436 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1437
1438 template<typename Fn> void match(Fn F) const { F(Bindings); }
1439
1440 void printLeft(OutputStream &S) const override {
1441 S += '[';
1442 Bindings.printWithComma(S);
1443 S += ']';
1444 }
1445};
1446
1447// -- Expression Nodes --
1448
1449class BinaryExpr : public Node {
1450 const Node *LHS;
1451 const StringView InfixOperator;
1452 const Node *RHS;
1453
1454public:
1455 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_)
1456 : Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {
1457 }
1458
1459 template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }
1460
1461 void printLeft(OutputStream &S) const override {
1462 // might be a template argument expression, then we need to disambiguate
1463 // with parens.
1464 if (InfixOperator == ">")
1465 S += "(";
1466
1467 S += "(";
1468 LHS->print(S);
1469 S += ") ";
1470 S += InfixOperator;
1471 S += " (";
1472 RHS->print(S);
1473 S += ")";
1474
1475 if (InfixOperator == ">")
1476 S += ")";
1477 }
1478};
1479
1480class ArraySubscriptExpr : public Node {
1481 const Node *Op1;
1482 const Node *Op2;
1483
1484public:
1485 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_)
1486 : Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {}
1487
1488 template<typename Fn> void match(Fn F) const { F(Op1, Op2); }
1489
1490 void printLeft(OutputStream &S) const override {
1491 S += "(";
1492 Op1->print(S);
1493 S += ")[";
1494 Op2->print(S);
1495 S += "]";
1496 }
1497};
1498
1499class PostfixExpr : public Node {
1500 const Node *Child;
1501 const StringView Operator;
1502
1503public:
1504 PostfixExpr(const Node *Child_, StringView Operator_)
1505 : Node(KPostfixExpr), Child(Child_), Operator(Operator_) {}
1506
1507 template<typename Fn> void match(Fn F) const { F(Child, Operator); }
1508
1509 void printLeft(OutputStream &S) const override {
1510 S += "(";
1511 Child->print(S);
1512 S += ")";
1513 S += Operator;
1514 }
1515};
1516
1517class ConditionalExpr : public Node {
1518 const Node *Cond;
1519 const Node *Then;
1520 const Node *Else;
1521
1522public:
1523 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_)
1524 : Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {}
1525
1526 template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }
1527
1528 void printLeft(OutputStream &S) const override {
1529 S += "(";
1530 Cond->print(S);
1531 S += ") ? (";
1532 Then->print(S);
1533 S += ") : (";
1534 Else->print(S);
1535 S += ")";
1536 }
1537};
1538
1539class MemberExpr : public Node {
1540 const Node *LHS;
1541 const StringView Kind;
1542 const Node *RHS;
1543
1544public:
1545 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_)
1546 : Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
1547
1548 template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }
1549
1550 void printLeft(OutputStream &S) const override {
1551 LHS->print(S);
1552 S += Kind;
1553 RHS->print(S);
1554 }
1555};
1556
1557class EnclosingExpr : public Node {
1558 const StringView Prefix;
1559 const Node *Infix;
1560 const StringView Postfix;
1561
1562public:
1563 EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_)
1564 : Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_),
1565 Postfix(Postfix_) {}
1566
1567 template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); }
1568
1569 void printLeft(OutputStream &S) const override {
1570 S += Prefix;
1571 Infix->print(S);
1572 S += Postfix;
1573 }
1574};
1575
1576class CastExpr : public Node {
1577 // cast_kind<to>(from)
1578 const StringView CastKind;
1579 const Node *To;
1580 const Node *From;
1581
1582public:
1583 CastExpr(StringView CastKind_, const Node *To_, const Node *From_)
1584 : Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {}
1585
1586 template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }
1587
1588 void printLeft(OutputStream &S) const override {
1589 S += CastKind;
1590 S += "<";
1591 To->printLeft(S);
1592 S += ">(";
1593 From->printLeft(S);
1594 S += ")";
1595 }
1596};
1597
1598class SizeofParamPackExpr : public Node {
1599 const Node *Pack;
1600
1601public:
1602 SizeofParamPackExpr(const Node *Pack_)
1603 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1604
1605 template<typename Fn> void match(Fn F) const { F(Pack); }
1606
1607 void printLeft(OutputStream &S) const override {
1608 S += "sizeof...(";
1609 ParameterPackExpansion PPE(Pack);
1610 PPE.printLeft(S);
1611 S += ")";
1612 }
1613};
1614
1615class CallExpr : public Node {
1616 const Node *Callee;
1617 NodeArray Args;
1618
1619public:
1620 CallExpr(const Node *Callee_, NodeArray Args_)
1621 : Node(KCallExpr), Callee(Callee_), Args(Args_) {}
1622
1623 template<typename Fn> void match(Fn F) const { F(Callee, Args); }
1624
1625 void printLeft(OutputStream &S) const override {
1626 Callee->print(S);
1627 S += "(";
1628 Args.printWithComma(S);
1629 S += ")";
1630 }
1631};
1632
1633class NewExpr : public Node {
1634 // new (expr_list) type(init_list)
1635 NodeArray ExprList;
1636 Node *Type;
1637 NodeArray InitList;
1638 bool IsGlobal; // ::operator new ?
1639 bool IsArray; // new[] ?
1640public:
1641 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
1642 bool IsArray_)
1643 : Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_),
1644 IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1645
1646 template<typename Fn> void match(Fn F) const {
1647 F(ExprList, Type, InitList, IsGlobal, IsArray);
1648 }
1649
1650 void printLeft(OutputStream &S) const override {
1651 if (IsGlobal)
1652 S += "::operator ";
1653 S += "new";
1654 if (IsArray)
1655 S += "[]";
1656 S += ' ';
1657 if (!ExprList.empty()) {
1658 S += "(";
1659 ExprList.printWithComma(S);
1660 S += ")";
1661 }
1662 Type->print(S);
1663 if (!InitList.empty()) {
1664 S += "(";
1665 InitList.printWithComma(S);
1666 S += ")";
1667 }
1668
1669 }
1670};
1671
1672class DeleteExpr : public Node {
1673 Node *Op;
1674 bool IsGlobal;
1675 bool IsArray;
1676
1677public:
1678 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_)
1679 : Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1680
1681 template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }
1682
1683 void printLeft(OutputStream &S) const override {
1684 if (IsGlobal)
1685 S += "::";
1686 S += "delete";
1687 if (IsArray)
1688 S += "[] ";
1689 Op->print(S);
1690 }
1691};
1692
1693class PrefixExpr : public Node {
1694 StringView Prefix;
1695 Node *Child;
1696
1697public:
1698 PrefixExpr(StringView Prefix_, Node *Child_)
1699 : Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {}
1700
1701 template<typename Fn> void match(Fn F) const { F(Prefix, Child); }
1702
1703 void printLeft(OutputStream &S) const override {
1704 S += Prefix;
1705 S += "(";
1706 Child->print(S);
1707 S += ")";
1708 }
1709};
1710
1711class FunctionParam : public Node {
1712 StringView Number;
1713
1714public:
1715 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
1716
1717 template<typename Fn> void match(Fn F) const { F(Number); }
1718
1719 void printLeft(OutputStream &S) const override {
1720 S += "fp";
1721 S += Number;
1722 }
1723};
1724
1725class ConversionExpr : public Node {
1726 const Node *Type;
1727 NodeArray Expressions;
1728
1729public:
1730 ConversionExpr(const Node *Type_, NodeArray Expressions_)
1731 : Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {}
1732
1733 template<typename Fn> void match(Fn F) const { F(Type, Expressions); }
1734
1735 void printLeft(OutputStream &S) const override {
1736 S += "(";
1737 Type->print(S);
1738 S += ")(";
1739 Expressions.printWithComma(S);
1740 S += ")";
1741 }
1742};
1743
1744class InitListExpr : public Node {
1745 const Node *Ty;
1746 NodeArray Inits;
1747public:
1748 InitListExpr(const Node *Ty_, NodeArray Inits_)
1749 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
1750
1751 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
1752
1753 void printLeft(OutputStream &S) const override {
1754 if (Ty)
1755 Ty->print(S);
1756 S += '{';
1757 Inits.printWithComma(S);
1758 S += '}';
1759 }
1760};
1761
1762class BracedExpr : public Node {
1763 const Node *Elem;
1764 const Node *Init;
1765 bool IsArray;
1766public:
1767 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
1768 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
1769
1770 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
1771
1772 void printLeft(OutputStream &S) const override {
1773 if (IsArray) {
1774 S += '[';
1775 Elem->print(S);
1776 S += ']';
1777 } else {
1778 S += '.';
1779 Elem->print(S);
1780 }
1781 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1782 S += " = ";
1783 Init->print(S);
1784 }
1785};
1786
1787class BracedRangeExpr : public Node {
1788 const Node *First;
1789 const Node *Last;
1790 const Node *Init;
1791public:
1792 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
1793 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
1794
1795 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
1796
1797 void printLeft(OutputStream &S) const override {
1798 S += '[';
1799 First->print(S);
1800 S += " ... ";
1801 Last->print(S);
1802 S += ']';
1803 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1804 S += " = ";
1805 Init->print(S);
1806 }
1807};
1808
1809class FoldExpr : public Node {
1810 const Node *Pack, *Init;
1811 StringView OperatorName;
1812 bool IsLeftFold;
1813
1814public:
1815 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
1816 const Node *Init_)
1817 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
1818 IsLeftFold(IsLeftFold_) {}
1819
1820 template<typename Fn> void match(Fn F) const {
1821 F(IsLeftFold, OperatorName, Pack, Init);
1822 }
1823
1824 void printLeft(OutputStream &S) const override {
1825 auto PrintPack = [&] {
1826 S += '(';
1827 ParameterPackExpansion(Pack).print(S);
1828 S += ')';
1829 };
1830
1831 S += '(';
1832
1833 if (IsLeftFold) {
1834 // init op ... op pack
1835 if (Init != nullptr) {
1836 Init->print(S);
1837 S += ' ';
1838 S += OperatorName;
1839 S += ' ';
1840 }
1841 // ... op pack
1842 S += "... ";
1843 S += OperatorName;
1844 S += ' ';
1845 PrintPack();
1846 } else { // !IsLeftFold
1847 // pack op ...
1848 PrintPack();
1849 S += ' ';
1850 S += OperatorName;
1851 S += " ...";
1852 // pack op ... op init
1853 if (Init != nullptr) {
1854 S += ' ';
1855 S += OperatorName;
1856 S += ' ';
1857 Init->print(S);
1858 }
1859 }
1860 S += ')';
1861 }
1862};
1863
1864class ThrowExpr : public Node {
1865 const Node *Op;
1866
1867public:
1868 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
1869
1870 template<typename Fn> void match(Fn F) const { F(Op); }
1871
1872 void printLeft(OutputStream &S) const override {
1873 S += "throw ";
1874 Op->print(S);
1875 }
1876};
1877
1878class BoolExpr : public Node {
1879 bool Value;
1880
1881public:
1882 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
1883
1884 template<typename Fn> void match(Fn F) const { F(Value); }
1885
1886 void printLeft(OutputStream &S) const override {
1887 S += Value ? StringView("true") : StringView("false");
1888 }
1889};
1890
1891class IntegerCastExpr : public Node {
1892 // ty(integer)
1893 const Node *Ty;
1894 StringView Integer;
1895
1896public:
1897 IntegerCastExpr(const Node *Ty_, StringView Integer_)
1898 : Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {}
1899
1900 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
1901
1902 void printLeft(OutputStream &S) const override {
1903 S += "(";
1904 Ty->print(S);
1905 S += ")";
1906 S += Integer;
1907 }
1908};
1909
1910class IntegerLiteral : public Node {
1911 StringView Type;
1912 StringView Value;
1913
1914public:
1915 IntegerLiteral(StringView Type_, StringView Value_)
1916 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
1917
1918 template<typename Fn> void match(Fn F) const { F(Type, Value); }
1919
1920 void printLeft(OutputStream &S) const override {
1921 if (Type.size() > 3) {
1922 S += "(";
1923 S += Type;
1924 S += ")";
1925 }
1926
1927 if (Value[0] == 'n') {
1928 S += "-";
1929 S += Value.dropFront(1);
1930 } else
1931 S += Value;
1932
1933 if (Type.size() <= 3)
1934 S += Type;
1935 }
1936};
1937
1938template <class Float> struct FloatData;
1939
1940namespace float_literal_impl {
1941constexpr Node::Kind getFloatLiteralKind(float *) {
1942 return Node::KFloatLiteral;
1943}
1944constexpr Node::Kind getFloatLiteralKind(double *) {
1945 return Node::KDoubleLiteral;
1946}
1947constexpr Node::Kind getFloatLiteralKind(long double *) {
1948 return Node::KLongDoubleLiteral;
1949}
1950}
1951
1952template <class Float> class FloatLiteralImpl : public Node {
1953 const StringView Contents;
1954
1955 static constexpr Kind KindForClass =
1956 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
1957
1958public:
1959 FloatLiteralImpl(StringView Contents_)
1960 : Node(KindForClass), Contents(Contents_) {}
1961
1962 template<typename Fn> void match(Fn F) const { F(Contents); }
1963
1964 void printLeft(OutputStream &s) const override {
1965 const char *first = Contents.begin();
1966 const char *last = Contents.end() + 1;
1967
1968 const size_t N = FloatData<Float>::mangled_size;
1969 if (static_cast<std::size_t>(last - first) > N) {
1970 last = first + N;
1971 union {
1972 Float value;
1973 char buf[sizeof(Float)];
1974 };
1975 const char *t = first;
1976 char *e = buf;
1977 for (; t != last; ++t, ++e) {
1978 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
1979 : static_cast<unsigned>(*t - 'a' + 10);
1980 ++t;
1981 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
1982 : static_cast<unsigned>(*t - 'a' + 10);
1983 *e = static_cast<char>((d1 << 4) + d0);
1984 }
1985#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
1986 std::reverse(buf, e);
1987#endif
1988 char num[FloatData<Float>::max_demangled_size] = {0};
1989 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
1990 s += StringView(num, num + n);
1991 }
1992 }
1993};
1994
1995using FloatLiteral = FloatLiteralImpl<float>;
1996using DoubleLiteral = FloatLiteralImpl<double>;
1997using LongDoubleLiteral = FloatLiteralImpl<long double>;
1998
1999/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2000/// appropriate derived class.
2001template<typename Fn>
2002void Node::visit(Fn F) const {
2003 switch (K) {
2004#define CASE(X) case K ## X: return F(static_cast<const X*>(this));
2005 FOR_EACH_NODE_KIND(CASE)
2006#undef CASE
2007 }
2008 assert(0 && "unknown mangling node kind");
2009}
2010
2011/// Determine the kind of a node from its type.
2012template<typename NodeT> struct NodeKind;
2013#define SPECIALIZATION(X) \
2014 template<> struct NodeKind<X> { \
2015 static constexpr Node::Kind Kind = Node::K##X; \
2016 static constexpr const char *name() { return #X; } \
2017 };
2018FOR_EACH_NODE_KIND(SPECIALIZATION)
2019#undef SPECIALIZATION
2020
2021#undef FOR_EACH_NODE_KIND
2022
2023template <class T, size_t N>
2024class PODSmallVector {
2025 static_assert(std::is_pod<T>::value,
2026 "T is required to be a plain old data type");
2027
2028 T* First;
2029 T* Last;
2030 T* Cap;
2031 T Inline[N];
2032
2033 bool isInline() const { return First == Inline; }
2034
2035 void clearInline() {
2036 First = Inline;
2037 Last = Inline;
2038 Cap = Inline + N;
2039 }
2040
2041 void reserve(size_t NewCap) {
2042 size_t S = size();
2043 if (isInline()) {
2044 auto* Tmp = static_cast<T*>(std::malloc(NewCap * sizeof(T)));
2045 if (Tmp == nullptr)
2046 std::terminate();
2047 std::copy(First, Last, Tmp);
2048 First = Tmp;
2049 } else {
2050 First = static_cast<T*>(std::realloc(First, NewCap * sizeof(T)));
2051 if (First == nullptr)
2052 std::terminate();
2053 }
2054 Last = First + S;
2055 Cap = First + NewCap;
2056 }
2057
2058public:
2059 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
2060
2061 PODSmallVector(const PODSmallVector&) = delete;
2062 PODSmallVector& operator=(const PODSmallVector&) = delete;
2063
2064 PODSmallVector(PODSmallVector&& Other) : PODSmallVector() {
2065 if (Other.isInline()) {
2066 std::copy(Other.begin(), Other.end(), First);
2067 Last = First + Other.size();
2068 Other.clear();
2069 return;
2070 }
2071
2072 First = Other.First;
2073 Last = Other.Last;
2074 Cap = Other.Cap;
2075 Other.clearInline();
2076 }
2077
2078 PODSmallVector& operator=(PODSmallVector&& Other) {
2079 if (Other.isInline()) {
2080 if (!isInline()) {
2081 std::free(First);
2082 clearInline();
2083 }
2084 std::copy(Other.begin(), Other.end(), First);
2085 Last = First + Other.size();
2086 Other.clear();
2087 return *this;
2088 }
2089
2090 if (isInline()) {
2091 First = Other.First;
2092 Last = Other.Last;
2093 Cap = Other.Cap;
2094 Other.clearInline();
2095 return *this;
2096 }
2097
2098 std::swap(First, Other.First);
2099 std::swap(Last, Other.Last);
2100 std::swap(Cap, Other.Cap);
2101 Other.clear();
2102 return *this;
2103 }
2104
2105 void push_back(const T& Elem) {
2106 if (Last == Cap)
2107 reserve(size() * 2);
2108 *Last++ = Elem;
2109 }
2110
2111 void pop_back() {
2112 assert(Last != First && "Popping empty vector!");
2113 --Last;
2114 }
2115
2116 void dropBack(size_t Index) {
2117 assert(Index <= size() && "dropBack() can't expand!");
2118 Last = First + Index;
2119 }
2120
2121 T* begin() { return First; }
2122 T* end() { return Last; }
2123
2124 bool empty() const { return First == Last; }
2125 size_t size() const { return static_cast<size_t>(Last - First); }
2126 T& back() {
2127 assert(Last != First && "Calling back() on empty vector!");
2128 return *(Last - 1);
2129 }
2130 T& operator[](size_t Index) {
2131 assert(Index < size() && "Invalid access!");
2132 return *(begin() + Index);
2133 }
2134 void clear() { Last = First; }
2135
2136 ~PODSmallVector() {
2137 if (!isInline())
2138 std::free(First);
2139 }
2140};
2141
Pavel Labathba825192018-10-16 14:29:14 +00002142template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002143 const char *First;
2144 const char *Last;
2145
2146 // Name stack, this is used by the parser to hold temporary names that were
2147 // parsed. The parser collapses multiple names into new nodes to construct
2148 // the AST. Once the parser is finished, names.size() == 1.
2149 PODSmallVector<Node *, 32> Names;
2150
2151 // Substitution table. Itanium supports name substitutions as a means of
2152 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2153 // table.
2154 PODSmallVector<Node *, 32> Subs;
2155
2156 // Template parameter table. Like the above, but referenced like "T42_".
2157 // This has a smaller size compared to Subs and Names because it can be
2158 // stored on the stack.
2159 PODSmallVector<Node *, 8> TemplateParams;
2160
2161 // Set of unresolved forward <template-param> references. These can occur in a
2162 // conversion operator's type, and are resolved in the enclosing <encoding>.
2163 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2164
Richard Smithc20d1442018-08-20 20:14:49 +00002165 bool TryToParseTemplateArgs = true;
2166 bool PermitForwardTemplateReferences = false;
2167 bool ParsingLambdaParams = false;
2168
2169 Alloc ASTAllocator;
2170
Pavel Labathba825192018-10-16 14:29:14 +00002171 AbstractManglingParser(const char *First_, const char *Last_)
2172 : First(First_), Last(Last_) {}
2173
2174 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002175
2176 void reset(const char *First_, const char *Last_) {
2177 First = First_;
2178 Last = Last_;
2179 Names.clear();
2180 Subs.clear();
2181 TemplateParams.clear();
2182 ParsingLambdaParams = false;
2183 TryToParseTemplateArgs = true;
2184 PermitForwardTemplateReferences = false;
2185 ASTAllocator.reset();
2186 }
2187
Richard Smithb485b352018-08-24 23:30:26 +00002188 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002189 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2190 }
2191
2192 template <class It> NodeArray makeNodeArray(It begin, It end) {
2193 size_t sz = static_cast<size_t>(end - begin);
2194 void *mem = ASTAllocator.allocateNodeArray(sz);
2195 Node **data = new (mem) Node *[sz];
2196 std::copy(begin, end, data);
2197 return NodeArray(data, sz);
2198 }
2199
2200 NodeArray popTrailingNodeArray(size_t FromPosition) {
2201 assert(FromPosition <= Names.size());
2202 NodeArray res =
2203 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2204 Names.dropBack(FromPosition);
2205 return res;
2206 }
2207
2208 bool consumeIf(StringView S) {
2209 if (StringView(First, Last).startsWith(S)) {
2210 First += S.size();
2211 return true;
2212 }
2213 return false;
2214 }
2215
2216 bool consumeIf(char C) {
2217 if (First != Last && *First == C) {
2218 ++First;
2219 return true;
2220 }
2221 return false;
2222 }
2223
2224 char consume() { return First != Last ? *First++ : '\0'; }
2225
2226 char look(unsigned Lookahead = 0) {
2227 if (static_cast<size_t>(Last - First) <= Lookahead)
2228 return '\0';
2229 return First[Lookahead];
2230 }
2231
2232 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2233
2234 StringView parseNumber(bool AllowNegative = false);
2235 Qualifiers parseCVQualifiers();
2236 bool parsePositiveInteger(size_t *Out);
2237 StringView parseBareSourceName();
2238
2239 bool parseSeqId(size_t *Out);
2240 Node *parseSubstitution();
2241 Node *parseTemplateParam();
2242 Node *parseTemplateArgs(bool TagTemplates = false);
2243 Node *parseTemplateArg();
2244
2245 /// Parse the <expr> production.
2246 Node *parseExpr();
2247 Node *parsePrefixExpr(StringView Kind);
2248 Node *parseBinaryExpr(StringView Kind);
2249 Node *parseIntegerLiteral(StringView Lit);
2250 Node *parseExprPrimary();
2251 template <class Float> Node *parseFloatingLiteral();
2252 Node *parseFunctionParam();
2253 Node *parseNewExpr();
2254 Node *parseConversionExpr();
2255 Node *parseBracedExpr();
2256 Node *parseFoldExpr();
2257
2258 /// Parse the <type> production.
2259 Node *parseType();
2260 Node *parseFunctionType();
2261 Node *parseVectorType();
2262 Node *parseDecltype();
2263 Node *parseArrayType();
2264 Node *parsePointerToMemberType();
2265 Node *parseClassEnumType();
2266 Node *parseQualifiedType();
2267
2268 Node *parseEncoding();
2269 bool parseCallOffset();
2270 Node *parseSpecialName();
2271
2272 /// Holds some extra information about a <name> that is being parsed. This
2273 /// information is only pertinent if the <name> refers to an <encoding>.
2274 struct NameState {
2275 bool CtorDtorConversion = false;
2276 bool EndsWithTemplateArgs = false;
2277 Qualifiers CVQualifiers = QualNone;
2278 FunctionRefQual ReferenceQualifier = FrefQualNone;
2279 size_t ForwardTemplateRefsBegin;
2280
Pavel Labathba825192018-10-16 14:29:14 +00002281 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002282 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2283 };
2284
2285 bool resolveForwardTemplateRefs(NameState &State) {
2286 size_t I = State.ForwardTemplateRefsBegin;
2287 size_t E = ForwardTemplateRefs.size();
2288 for (; I < E; ++I) {
2289 size_t Idx = ForwardTemplateRefs[I]->Index;
2290 if (Idx >= TemplateParams.size())
2291 return true;
2292 ForwardTemplateRefs[I]->Ref = TemplateParams[Idx];
2293 }
2294 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2295 return false;
2296 }
2297
2298 /// Parse the <name> production>
2299 Node *parseName(NameState *State = nullptr);
2300 Node *parseLocalName(NameState *State);
2301 Node *parseOperatorName(NameState *State);
2302 Node *parseUnqualifiedName(NameState *State);
2303 Node *parseUnnamedTypeName(NameState *State);
2304 Node *parseSourceName(NameState *State);
2305 Node *parseUnscopedName(NameState *State);
2306 Node *parseNestedName(NameState *State);
2307 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2308
2309 Node *parseAbiTags(Node *N);
2310
2311 /// Parse the <unresolved-name> production.
2312 Node *parseUnresolvedName();
2313 Node *parseSimpleId();
2314 Node *parseBaseUnresolvedName();
2315 Node *parseUnresolvedType();
2316 Node *parseDestructorName();
2317
2318 /// Top-level entry point into the parser.
2319 Node *parse();
2320};
2321
2322const char* parse_discriminator(const char* first, const char* last);
2323
2324// <name> ::= <nested-name> // N
2325// ::= <local-name> # See Scope Encoding below // Z
2326// ::= <unscoped-template-name> <template-args>
2327// ::= <unscoped-name>
2328//
2329// <unscoped-template-name> ::= <unscoped-name>
2330// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002331template <typename Derived, typename Alloc>
2332Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002333 consumeIf('L'); // extension
2334
2335 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002336 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002337 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002338 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002339
2340 // ::= <unscoped-template-name> <template-args>
2341 if (look() == 'S' && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00002342 Node *S = getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00002343 if (S == nullptr)
2344 return nullptr;
2345 if (look() != 'I')
2346 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002347 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002348 if (TA == nullptr)
2349 return nullptr;
2350 if (State) State->EndsWithTemplateArgs = true;
2351 return make<NameWithTemplateArgs>(S, TA);
2352 }
2353
Pavel Labathba825192018-10-16 14:29:14 +00002354 Node *N = getDerived().parseUnscopedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002355 if (N == nullptr)
2356 return nullptr;
2357 // ::= <unscoped-template-name> <template-args>
2358 if (look() == 'I') {
2359 Subs.push_back(N);
Pavel Labathba825192018-10-16 14:29:14 +00002360 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002361 if (TA == nullptr)
2362 return nullptr;
2363 if (State) State->EndsWithTemplateArgs = true;
2364 return make<NameWithTemplateArgs>(N, TA);
2365 }
2366 // ::= <unscoped-name>
2367 return N;
2368}
2369
2370// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2371// := Z <function encoding> E s [<discriminator>]
2372// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002373template <typename Derived, typename Alloc>
2374Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002375 if (!consumeIf('Z'))
2376 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002377 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002378 if (Encoding == nullptr || !consumeIf('E'))
2379 return nullptr;
2380
2381 if (consumeIf('s')) {
2382 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002383 auto *StringLitName = make<NameType>("string literal");
2384 if (!StringLitName)
2385 return nullptr;
2386 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002387 }
2388
2389 if (consumeIf('d')) {
2390 parseNumber(true);
2391 if (!consumeIf('_'))
2392 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002393 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002394 if (N == nullptr)
2395 return nullptr;
2396 return make<LocalName>(Encoding, N);
2397 }
2398
Pavel Labathba825192018-10-16 14:29:14 +00002399 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002400 if (Entity == nullptr)
2401 return nullptr;
2402 First = parse_discriminator(First, Last);
2403 return make<LocalName>(Encoding, Entity);
2404}
2405
2406// <unscoped-name> ::= <unqualified-name>
2407// ::= St <unqualified-name> # ::std::
2408// extension ::= StL<unqualified-name>
Pavel Labathba825192018-10-16 14:29:14 +00002409template <typename Derived, typename Alloc>
2410Node *
2411AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {
2412 if (consumeIf("StL") || consumeIf("St")) {
2413 Node *R = getDerived().parseUnqualifiedName(State);
2414 if (R == nullptr)
2415 return nullptr;
2416 return make<StdQualifiedName>(R);
2417 }
2418 return getDerived().parseUnqualifiedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002419}
2420
2421// <unqualified-name> ::= <operator-name> [abi-tags]
2422// ::= <ctor-dtor-name>
2423// ::= <source-name>
2424// ::= <unnamed-type-name>
2425// ::= DC <source-name>+ E # structured binding declaration
Pavel Labathba825192018-10-16 14:29:14 +00002426template <typename Derived, typename Alloc>
2427Node *
2428AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002429 // <ctor-dtor-name>s are special-cased in parseNestedName().
2430 Node *Result;
2431 if (look() == 'U')
Pavel Labathba825192018-10-16 14:29:14 +00002432 Result = getDerived().parseUnnamedTypeName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002433 else if (look() >= '1' && look() <= '9')
Pavel Labathba825192018-10-16 14:29:14 +00002434 Result = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002435 else if (consumeIf("DC")) {
2436 size_t BindingsBegin = Names.size();
2437 do {
Pavel Labathba825192018-10-16 14:29:14 +00002438 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002439 if (Binding == nullptr)
2440 return nullptr;
2441 Names.push_back(Binding);
2442 } while (!consumeIf('E'));
2443 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
2444 } else
Pavel Labathba825192018-10-16 14:29:14 +00002445 Result = getDerived().parseOperatorName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002446 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002447 Result = getDerived().parseAbiTags(Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002448 return Result;
2449}
2450
2451// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2452// ::= <closure-type-name>
2453//
2454// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2455//
2456// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002457template <typename Derived, typename Alloc>
2458Node *
2459AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002460 if (consumeIf("Ut")) {
2461 StringView Count = parseNumber();
2462 if (!consumeIf('_'))
2463 return nullptr;
2464 return make<UnnamedTypeName>(Count);
2465 }
2466 if (consumeIf("Ul")) {
2467 NodeArray Params;
2468 SwapAndRestore<bool> SwapParams(ParsingLambdaParams, true);
2469 if (!consumeIf("vE")) {
2470 size_t ParamsBegin = Names.size();
2471 do {
Pavel Labathba825192018-10-16 14:29:14 +00002472 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002473 if (P == nullptr)
2474 return nullptr;
2475 Names.push_back(P);
2476 } while (!consumeIf('E'));
2477 Params = popTrailingNodeArray(ParamsBegin);
2478 }
2479 StringView Count = parseNumber();
2480 if (!consumeIf('_'))
2481 return nullptr;
2482 return make<ClosureTypeName>(Params, Count);
2483 }
2484 return nullptr;
2485}
2486
2487// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002488template <typename Derived, typename Alloc>
2489Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002490 size_t Length = 0;
2491 if (parsePositiveInteger(&Length))
2492 return nullptr;
2493 if (numLeft() < Length || Length == 0)
2494 return nullptr;
2495 StringView Name(First, First + Length);
2496 First += Length;
2497 if (Name.startsWith("_GLOBAL__N"))
2498 return make<NameType>("(anonymous namespace)");
2499 return make<NameType>(Name);
2500}
2501
2502// <operator-name> ::= aa # &&
2503// ::= ad # & (unary)
2504// ::= an # &
2505// ::= aN # &=
2506// ::= aS # =
2507// ::= cl # ()
2508// ::= cm # ,
2509// ::= co # ~
2510// ::= cv <type> # (cast)
2511// ::= da # delete[]
2512// ::= de # * (unary)
2513// ::= dl # delete
2514// ::= dv # /
2515// ::= dV # /=
2516// ::= eo # ^
2517// ::= eO # ^=
2518// ::= eq # ==
2519// ::= ge # >=
2520// ::= gt # >
2521// ::= ix # []
2522// ::= le # <=
2523// ::= li <source-name> # operator ""
2524// ::= ls # <<
2525// ::= lS # <<=
2526// ::= lt # <
2527// ::= mi # -
2528// ::= mI # -=
2529// ::= ml # *
2530// ::= mL # *=
2531// ::= mm # -- (postfix in <expression> context)
2532// ::= na # new[]
2533// ::= ne # !=
2534// ::= ng # - (unary)
2535// ::= nt # !
2536// ::= nw # new
2537// ::= oo # ||
2538// ::= or # |
2539// ::= oR # |=
2540// ::= pm # ->*
2541// ::= pl # +
2542// ::= pL # +=
2543// ::= pp # ++ (postfix in <expression> context)
2544// ::= ps # + (unary)
2545// ::= pt # ->
2546// ::= qu # ?
2547// ::= rm # %
2548// ::= rM # %=
2549// ::= rs # >>
2550// ::= rS # >>=
2551// ::= ss # <=> C++2a
2552// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00002553template <typename Derived, typename Alloc>
2554Node *
2555AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002556 switch (look()) {
2557 case 'a':
2558 switch (look(1)) {
2559 case 'a':
2560 First += 2;
2561 return make<NameType>("operator&&");
2562 case 'd':
2563 case 'n':
2564 First += 2;
2565 return make<NameType>("operator&");
2566 case 'N':
2567 First += 2;
2568 return make<NameType>("operator&=");
2569 case 'S':
2570 First += 2;
2571 return make<NameType>("operator=");
2572 }
2573 return nullptr;
2574 case 'c':
2575 switch (look(1)) {
2576 case 'l':
2577 First += 2;
2578 return make<NameType>("operator()");
2579 case 'm':
2580 First += 2;
2581 return make<NameType>("operator,");
2582 case 'o':
2583 First += 2;
2584 return make<NameType>("operator~");
2585 // ::= cv <type> # (cast)
2586 case 'v': {
2587 First += 2;
2588 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
2589 // If we're parsing an encoding, State != nullptr and the conversion
2590 // operators' <type> could have a <template-param> that refers to some
2591 // <template-arg>s further ahead in the mangled name.
2592 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
2593 PermitForwardTemplateReferences ||
2594 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00002595 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002596 if (Ty == nullptr)
2597 return nullptr;
2598 if (State) State->CtorDtorConversion = true;
2599 return make<ConversionOperatorType>(Ty);
2600 }
2601 }
2602 return nullptr;
2603 case 'd':
2604 switch (look(1)) {
2605 case 'a':
2606 First += 2;
2607 return make<NameType>("operator delete[]");
2608 case 'e':
2609 First += 2;
2610 return make<NameType>("operator*");
2611 case 'l':
2612 First += 2;
2613 return make<NameType>("operator delete");
2614 case 'v':
2615 First += 2;
2616 return make<NameType>("operator/");
2617 case 'V':
2618 First += 2;
2619 return make<NameType>("operator/=");
2620 }
2621 return nullptr;
2622 case 'e':
2623 switch (look(1)) {
2624 case 'o':
2625 First += 2;
2626 return make<NameType>("operator^");
2627 case 'O':
2628 First += 2;
2629 return make<NameType>("operator^=");
2630 case 'q':
2631 First += 2;
2632 return make<NameType>("operator==");
2633 }
2634 return nullptr;
2635 case 'g':
2636 switch (look(1)) {
2637 case 'e':
2638 First += 2;
2639 return make<NameType>("operator>=");
2640 case 't':
2641 First += 2;
2642 return make<NameType>("operator>");
2643 }
2644 return nullptr;
2645 case 'i':
2646 if (look(1) == 'x') {
2647 First += 2;
2648 return make<NameType>("operator[]");
2649 }
2650 return nullptr;
2651 case 'l':
2652 switch (look(1)) {
2653 case 'e':
2654 First += 2;
2655 return make<NameType>("operator<=");
2656 // ::= li <source-name> # operator ""
2657 case 'i': {
2658 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00002659 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002660 if (SN == nullptr)
2661 return nullptr;
2662 return make<LiteralOperator>(SN);
2663 }
2664 case 's':
2665 First += 2;
2666 return make<NameType>("operator<<");
2667 case 'S':
2668 First += 2;
2669 return make<NameType>("operator<<=");
2670 case 't':
2671 First += 2;
2672 return make<NameType>("operator<");
2673 }
2674 return nullptr;
2675 case 'm':
2676 switch (look(1)) {
2677 case 'i':
2678 First += 2;
2679 return make<NameType>("operator-");
2680 case 'I':
2681 First += 2;
2682 return make<NameType>("operator-=");
2683 case 'l':
2684 First += 2;
2685 return make<NameType>("operator*");
2686 case 'L':
2687 First += 2;
2688 return make<NameType>("operator*=");
2689 case 'm':
2690 First += 2;
2691 return make<NameType>("operator--");
2692 }
2693 return nullptr;
2694 case 'n':
2695 switch (look(1)) {
2696 case 'a':
2697 First += 2;
2698 return make<NameType>("operator new[]");
2699 case 'e':
2700 First += 2;
2701 return make<NameType>("operator!=");
2702 case 'g':
2703 First += 2;
2704 return make<NameType>("operator-");
2705 case 't':
2706 First += 2;
2707 return make<NameType>("operator!");
2708 case 'w':
2709 First += 2;
2710 return make<NameType>("operator new");
2711 }
2712 return nullptr;
2713 case 'o':
2714 switch (look(1)) {
2715 case 'o':
2716 First += 2;
2717 return make<NameType>("operator||");
2718 case 'r':
2719 First += 2;
2720 return make<NameType>("operator|");
2721 case 'R':
2722 First += 2;
2723 return make<NameType>("operator|=");
2724 }
2725 return nullptr;
2726 case 'p':
2727 switch (look(1)) {
2728 case 'm':
2729 First += 2;
2730 return make<NameType>("operator->*");
2731 case 'l':
2732 First += 2;
2733 return make<NameType>("operator+");
2734 case 'L':
2735 First += 2;
2736 return make<NameType>("operator+=");
2737 case 'p':
2738 First += 2;
2739 return make<NameType>("operator++");
2740 case 's':
2741 First += 2;
2742 return make<NameType>("operator+");
2743 case 't':
2744 First += 2;
2745 return make<NameType>("operator->");
2746 }
2747 return nullptr;
2748 case 'q':
2749 if (look(1) == 'u') {
2750 First += 2;
2751 return make<NameType>("operator?");
2752 }
2753 return nullptr;
2754 case 'r':
2755 switch (look(1)) {
2756 case 'm':
2757 First += 2;
2758 return make<NameType>("operator%");
2759 case 'M':
2760 First += 2;
2761 return make<NameType>("operator%=");
2762 case 's':
2763 First += 2;
2764 return make<NameType>("operator>>");
2765 case 'S':
2766 First += 2;
2767 return make<NameType>("operator>>=");
2768 }
2769 return nullptr;
2770 case 's':
2771 if (look(1) == 's') {
2772 First += 2;
2773 return make<NameType>("operator<=>");
2774 }
2775 return nullptr;
2776 // ::= v <digit> <source-name> # vendor extended operator
2777 case 'v':
2778 if (std::isdigit(look(1))) {
2779 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00002780 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002781 if (SN == nullptr)
2782 return nullptr;
2783 return make<ConversionOperatorType>(SN);
2784 }
2785 return nullptr;
2786 }
2787 return nullptr;
2788}
2789
2790// <ctor-dtor-name> ::= C1 # complete object constructor
2791// ::= C2 # base object constructor
2792// ::= C3 # complete object allocating constructor
2793// extension ::= C5 # ?
2794// ::= D0 # deleting destructor
2795// ::= D1 # complete object destructor
2796// ::= D2 # base object destructor
2797// extension ::= D5 # ?
Pavel Labathba825192018-10-16 14:29:14 +00002798template <typename Derived, typename Alloc>
2799Node *
2800AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
2801 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002802 if (SoFar->getKind() == Node::KSpecialSubstitution) {
2803 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
2804 switch (SSK) {
2805 case SpecialSubKind::string:
2806 case SpecialSubKind::istream:
2807 case SpecialSubKind::ostream:
2808 case SpecialSubKind::iostream:
2809 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00002810 if (!SoFar)
2811 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00002812 break;
Richard Smithc20d1442018-08-20 20:14:49 +00002813 default:
2814 break;
2815 }
2816 }
2817
2818 if (consumeIf('C')) {
2819 bool IsInherited = consumeIf('I');
2820 if (look() != '1' && look() != '2' && look() != '3' && look() != '5')
2821 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002822 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00002823 ++First;
2824 if (State) State->CtorDtorConversion = true;
2825 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00002826 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00002827 return nullptr;
2828 }
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002829 return make<CtorDtorName>(SoFar, false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00002830 }
2831
2832 if (look() == 'D' &&
2833 (look(1) == '0' || look(1) == '1' || look(1) == '2' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002834 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00002835 First += 2;
2836 if (State) State->CtorDtorConversion = true;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002837 return make<CtorDtorName>(SoFar, true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00002838 }
2839
2840 return nullptr;
2841}
2842
2843// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
2844// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
2845//
2846// <prefix> ::= <prefix> <unqualified-name>
2847// ::= <template-prefix> <template-args>
2848// ::= <template-param>
2849// ::= <decltype>
2850// ::= # empty
2851// ::= <substitution>
2852// ::= <prefix> <data-member-prefix>
2853// extension ::= L
2854//
2855// <data-member-prefix> := <member source-name> [<template-args>] M
2856//
2857// <template-prefix> ::= <prefix> <template unqualified-name>
2858// ::= <template-param>
2859// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002860template <typename Derived, typename Alloc>
2861Node *
2862AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002863 if (!consumeIf('N'))
2864 return nullptr;
2865
2866 Qualifiers CVTmp = parseCVQualifiers();
2867 if (State) State->CVQualifiers = CVTmp;
2868
2869 if (consumeIf('O')) {
2870 if (State) State->ReferenceQualifier = FrefQualRValue;
2871 } else if (consumeIf('R')) {
2872 if (State) State->ReferenceQualifier = FrefQualLValue;
2873 } else
2874 if (State) State->ReferenceQualifier = FrefQualNone;
2875
2876 Node *SoFar = nullptr;
2877 auto PushComponent = [&](Node *Comp) {
Richard Smithb485b352018-08-24 23:30:26 +00002878 if (!Comp) return false;
Richard Smithc20d1442018-08-20 20:14:49 +00002879 if (SoFar) SoFar = make<NestedName>(SoFar, Comp);
2880 else SoFar = Comp;
2881 if (State) State->EndsWithTemplateArgs = false;
Richard Smithb485b352018-08-24 23:30:26 +00002882 return SoFar != nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002883 };
2884
Richard Smithb485b352018-08-24 23:30:26 +00002885 if (consumeIf("St")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002886 SoFar = make<NameType>("std");
Richard Smithb485b352018-08-24 23:30:26 +00002887 if (!SoFar)
2888 return nullptr;
2889 }
Richard Smithc20d1442018-08-20 20:14:49 +00002890
2891 while (!consumeIf('E')) {
2892 consumeIf('L'); // extension
2893
2894 // <data-member-prefix> := <member source-name> [<template-args>] M
2895 if (consumeIf('M')) {
2896 if (SoFar == nullptr)
2897 return nullptr;
2898 continue;
2899 }
2900
2901 // ::= <template-param>
2902 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00002903 if (!PushComponent(getDerived().parseTemplateParam()))
Richard Smithc20d1442018-08-20 20:14:49 +00002904 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002905 Subs.push_back(SoFar);
2906 continue;
2907 }
2908
2909 // ::= <template-prefix> <template-args>
2910 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00002911 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002912 if (TA == nullptr || SoFar == nullptr)
2913 return nullptr;
2914 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00002915 if (!SoFar)
2916 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002917 if (State) State->EndsWithTemplateArgs = true;
2918 Subs.push_back(SoFar);
2919 continue;
2920 }
2921
2922 // ::= <decltype>
2923 if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
Pavel Labathba825192018-10-16 14:29:14 +00002924 if (!PushComponent(getDerived().parseDecltype()))
Richard Smithc20d1442018-08-20 20:14:49 +00002925 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002926 Subs.push_back(SoFar);
2927 continue;
2928 }
2929
2930 // ::= <substitution>
2931 if (look() == 'S' && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00002932 Node *S = getDerived().parseSubstitution();
Richard Smithb485b352018-08-24 23:30:26 +00002933 if (!PushComponent(S))
Richard Smithc20d1442018-08-20 20:14:49 +00002934 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002935 if (SoFar != S)
2936 Subs.push_back(S);
2937 continue;
2938 }
2939
2940 // Parse an <unqualified-name> thats actually a <ctor-dtor-name>.
2941 if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {
2942 if (SoFar == nullptr)
2943 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002944 if (!PushComponent(getDerived().parseCtorDtorName(SoFar, State)))
Richard Smithc20d1442018-08-20 20:14:49 +00002945 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002946 SoFar = getDerived().parseAbiTags(SoFar);
Richard Smithc20d1442018-08-20 20:14:49 +00002947 if (SoFar == nullptr)
2948 return nullptr;
2949 Subs.push_back(SoFar);
2950 continue;
2951 }
2952
2953 // ::= <prefix> <unqualified-name>
Pavel Labathba825192018-10-16 14:29:14 +00002954 if (!PushComponent(getDerived().parseUnqualifiedName(State)))
Richard Smithc20d1442018-08-20 20:14:49 +00002955 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002956 Subs.push_back(SoFar);
2957 }
2958
2959 if (SoFar == nullptr || Subs.empty())
2960 return nullptr;
2961
2962 Subs.pop_back();
2963 return SoFar;
2964}
2965
2966// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00002967template <typename Derived, typename Alloc>
2968Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
2969 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002970 if (SN == nullptr)
2971 return nullptr;
2972 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00002973 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00002974 if (TA == nullptr)
2975 return nullptr;
2976 return make<NameWithTemplateArgs>(SN, TA);
2977 }
2978 return SN;
2979}
2980
2981// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
2982// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00002983template <typename Derived, typename Alloc>
2984Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00002985 Node *Result;
2986 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00002987 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00002988 else
Pavel Labathba825192018-10-16 14:29:14 +00002989 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00002990 if (Result == nullptr)
2991 return nullptr;
2992 return make<DtorName>(Result);
2993}
2994
2995// <unresolved-type> ::= <template-param>
2996// ::= <decltype>
2997// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002998template <typename Derived, typename Alloc>
2999Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003000 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003001 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003002 if (TP == nullptr)
3003 return nullptr;
3004 Subs.push_back(TP);
3005 return TP;
3006 }
3007 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003008 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003009 if (DT == nullptr)
3010 return nullptr;
3011 Subs.push_back(DT);
3012 return DT;
3013 }
Pavel Labathba825192018-10-16 14:29:14 +00003014 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003015}
3016
3017// <base-unresolved-name> ::= <simple-id> # unresolved name
3018// extension ::= <operator-name> # unresolved operator-function-id
3019// extension ::= <operator-name> <template-args> # unresolved operator template-id
3020// ::= on <operator-name> # unresolved operator-function-id
3021// ::= on <operator-name> <template-args> # unresolved operator template-id
3022// ::= dn <destructor-name> # destructor or pseudo-destructor;
3023// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003024template <typename Derived, typename Alloc>
3025Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003026 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003027 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003028
3029 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003030 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003031
3032 consumeIf("on");
3033
Pavel Labathba825192018-10-16 14:29:14 +00003034 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003035 if (Oper == nullptr)
3036 return nullptr;
3037 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003038 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003039 if (TA == nullptr)
3040 return nullptr;
3041 return make<NameWithTemplateArgs>(Oper, TA);
3042 }
3043 return Oper;
3044}
3045
3046// <unresolved-name>
3047// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3048// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3049// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3050// # A::x, N::y, A<T>::z; "gs" means leading "::"
3051// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3052// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3053// # T::N::x /decltype(p)::N::x
3054// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3055//
3056// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003057template <typename Derived, typename Alloc>
3058Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003059 Node *SoFar = nullptr;
3060
3061 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3062 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3063 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003064 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003065 if (SoFar == nullptr)
3066 return nullptr;
3067
3068 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003069 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003070 if (TA == nullptr)
3071 return nullptr;
3072 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003073 if (!SoFar)
3074 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003075 }
3076
3077 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003078 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003079 if (Qual == nullptr)
3080 return nullptr;
3081 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003082 if (!SoFar)
3083 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003084 }
3085
Pavel Labathba825192018-10-16 14:29:14 +00003086 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003087 if (Base == nullptr)
3088 return nullptr;
3089 return make<QualifiedName>(SoFar, Base);
3090 }
3091
3092 bool Global = consumeIf("gs");
3093
3094 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3095 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003096 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003097 if (SoFar == nullptr)
3098 return nullptr;
3099 if (Global)
3100 SoFar = make<GlobalQualifiedName>(SoFar);
3101 return SoFar;
3102 }
3103
3104 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3105 if (std::isdigit(look())) {
3106 do {
Pavel Labathba825192018-10-16 14:29:14 +00003107 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003108 if (Qual == nullptr)
3109 return nullptr;
3110 if (SoFar)
3111 SoFar = make<QualifiedName>(SoFar, Qual);
3112 else if (Global)
3113 SoFar = make<GlobalQualifiedName>(Qual);
3114 else
3115 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003116 if (!SoFar)
3117 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003118 } while (!consumeIf('E'));
3119 }
3120 // sr <unresolved-type> <base-unresolved-name>
3121 // sr <unresolved-type> <template-args> <base-unresolved-name>
3122 else {
Pavel Labathba825192018-10-16 14:29:14 +00003123 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003124 if (SoFar == nullptr)
3125 return nullptr;
3126
3127 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003128 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003129 if (TA == nullptr)
3130 return nullptr;
3131 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003132 if (!SoFar)
3133 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003134 }
3135 }
3136
3137 assert(SoFar != nullptr);
3138
Pavel Labathba825192018-10-16 14:29:14 +00003139 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003140 if (Base == nullptr)
3141 return nullptr;
3142 return make<QualifiedName>(SoFar, Base);
3143}
3144
3145// <abi-tags> ::= <abi-tag> [<abi-tags>]
3146// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003147template <typename Derived, typename Alloc>
3148Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003149 while (consumeIf('B')) {
3150 StringView SN = parseBareSourceName();
3151 if (SN.empty())
3152 return nullptr;
3153 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003154 if (!N)
3155 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003156 }
3157 return N;
3158}
3159
3160// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003161template <typename Alloc, typename Derived>
3162StringView
3163AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003164 const char *Tmp = First;
3165 if (AllowNegative)
3166 consumeIf('n');
3167 if (numLeft() == 0 || !std::isdigit(*First))
3168 return StringView();
3169 while (numLeft() != 0 && std::isdigit(*First))
3170 ++First;
3171 return StringView(Tmp, First);
3172}
3173
3174// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003175template <typename Alloc, typename Derived>
3176bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003177 *Out = 0;
3178 if (look() < '0' || look() > '9')
3179 return true;
3180 while (look() >= '0' && look() <= '9') {
3181 *Out *= 10;
3182 *Out += static_cast<size_t>(consume() - '0');
3183 }
3184 return false;
3185}
3186
Pavel Labathba825192018-10-16 14:29:14 +00003187template <typename Alloc, typename Derived>
3188StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003189 size_t Int = 0;
3190 if (parsePositiveInteger(&Int) || numLeft() < Int)
3191 return StringView();
3192 StringView R(First, First + Int);
3193 First += Int;
3194 return R;
3195}
3196
3197// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3198//
3199// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3200// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3201// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3202//
3203// <ref-qualifier> ::= R # & ref-qualifier
3204// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003205template <typename Derived, typename Alloc>
3206Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003207 Qualifiers CVQuals = parseCVQualifiers();
3208
3209 Node *ExceptionSpec = nullptr;
3210 if (consumeIf("Do")) {
3211 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003212 if (!ExceptionSpec)
3213 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003214 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003215 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003216 if (E == nullptr || !consumeIf('E'))
3217 return nullptr;
3218 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003219 if (!ExceptionSpec)
3220 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003221 } else if (consumeIf("Dw")) {
3222 size_t SpecsBegin = Names.size();
3223 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003224 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003225 if (T == nullptr)
3226 return nullptr;
3227 Names.push_back(T);
3228 }
3229 ExceptionSpec =
3230 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003231 if (!ExceptionSpec)
3232 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003233 }
3234
3235 consumeIf("Dx"); // transaction safe
3236
3237 if (!consumeIf('F'))
3238 return nullptr;
3239 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003240 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003241 if (ReturnType == nullptr)
3242 return nullptr;
3243
3244 FunctionRefQual ReferenceQualifier = FrefQualNone;
3245 size_t ParamsBegin = Names.size();
3246 while (true) {
3247 if (consumeIf('E'))
3248 break;
3249 if (consumeIf('v'))
3250 continue;
3251 if (consumeIf("RE")) {
3252 ReferenceQualifier = FrefQualLValue;
3253 break;
3254 }
3255 if (consumeIf("OE")) {
3256 ReferenceQualifier = FrefQualRValue;
3257 break;
3258 }
Pavel Labathba825192018-10-16 14:29:14 +00003259 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003260 if (T == nullptr)
3261 return nullptr;
3262 Names.push_back(T);
3263 }
3264
3265 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3266 return make<FunctionType>(ReturnType, Params, CVQuals,
3267 ReferenceQualifier, ExceptionSpec);
3268}
3269
3270// extension:
3271// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3272// ::= Dv [<dimension expression>] _ <element type>
3273// <extended element type> ::= <element type>
3274// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003275template <typename Derived, typename Alloc>
3276Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003277 if (!consumeIf("Dv"))
3278 return nullptr;
3279 if (look() >= '1' && look() <= '9') {
3280 StringView DimensionNumber = parseNumber();
3281 if (!consumeIf('_'))
3282 return nullptr;
3283 if (consumeIf('p'))
3284 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003285 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003286 if (ElemType == nullptr)
3287 return nullptr;
3288 return make<VectorType>(ElemType, DimensionNumber);
3289 }
3290
3291 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003292 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003293 if (!DimExpr)
3294 return nullptr;
3295 if (!consumeIf('_'))
3296 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003297 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003298 if (!ElemType)
3299 return nullptr;
3300 return make<VectorType>(ElemType, DimExpr);
3301 }
Pavel Labathba825192018-10-16 14:29:14 +00003302 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003303 if (!ElemType)
3304 return nullptr;
3305 return make<VectorType>(ElemType, StringView());
3306}
3307
3308// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3309// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003310template <typename Derived, typename Alloc>
3311Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003312 if (!consumeIf('D'))
3313 return nullptr;
3314 if (!consumeIf('t') && !consumeIf('T'))
3315 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003316 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003317 if (E == nullptr)
3318 return nullptr;
3319 if (!consumeIf('E'))
3320 return nullptr;
3321 return make<EnclosingExpr>("decltype(", E, ")");
3322}
3323
3324// <array-type> ::= A <positive dimension number> _ <element type>
3325// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003326template <typename Derived, typename Alloc>
3327Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003328 if (!consumeIf('A'))
3329 return nullptr;
3330
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003331 NodeOrString Dimension;
3332
Richard Smithc20d1442018-08-20 20:14:49 +00003333 if (std::isdigit(look())) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003334 Dimension = parseNumber();
Richard Smithc20d1442018-08-20 20:14:49 +00003335 if (!consumeIf('_'))
3336 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003337 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003338 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003339 if (DimExpr == nullptr)
3340 return nullptr;
3341 if (!consumeIf('_'))
3342 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003343 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003344 }
3345
Pavel Labathba825192018-10-16 14:29:14 +00003346 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003347 if (Ty == nullptr)
3348 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003349 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003350}
3351
3352// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003353template <typename Derived, typename Alloc>
3354Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003355 if (!consumeIf('M'))
3356 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003357 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003358 if (ClassType == nullptr)
3359 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003360 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003361 if (MemberType == nullptr)
3362 return nullptr;
3363 return make<PointerToMemberType>(ClassType, MemberType);
3364}
3365
3366// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3367// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3368// ::= Tu <name> # dependent elaborated type specifier using 'union'
3369// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003370template <typename Derived, typename Alloc>
3371Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003372 StringView ElabSpef;
3373 if (consumeIf("Ts"))
3374 ElabSpef = "struct";
3375 else if (consumeIf("Tu"))
3376 ElabSpef = "union";
3377 else if (consumeIf("Te"))
3378 ElabSpef = "enum";
3379
Pavel Labathba825192018-10-16 14:29:14 +00003380 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003381 if (Name == nullptr)
3382 return nullptr;
3383
3384 if (!ElabSpef.empty())
3385 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3386
3387 return Name;
3388}
3389
3390// <qualified-type> ::= <qualifiers> <type>
3391// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3392// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003393template <typename Derived, typename Alloc>
3394Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003395 if (consumeIf('U')) {
3396 StringView Qual = parseBareSourceName();
3397 if (Qual.empty())
3398 return nullptr;
3399
3400 // FIXME parse the optional <template-args> here!
3401
3402 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3403 if (Qual.startsWith("objcproto")) {
3404 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3405 StringView Proto;
3406 {
3407 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3408 SaveLast(Last, ProtoSourceName.end());
3409 Proto = parseBareSourceName();
3410 }
3411 if (Proto.empty())
3412 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003413 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003414 if (Child == nullptr)
3415 return nullptr;
3416 return make<ObjCProtoName>(Child, Proto);
3417 }
3418
Pavel Labathba825192018-10-16 14:29:14 +00003419 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003420 if (Child == nullptr)
3421 return nullptr;
3422 return make<VendorExtQualType>(Child, Qual);
3423 }
3424
3425 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003426 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003427 if (Ty == nullptr)
3428 return nullptr;
3429 if (Quals != QualNone)
3430 Ty = make<QualType>(Ty, Quals);
3431 return Ty;
3432}
3433
3434// <type> ::= <builtin-type>
3435// ::= <qualified-type>
3436// ::= <function-type>
3437// ::= <class-enum-type>
3438// ::= <array-type>
3439// ::= <pointer-to-member-type>
3440// ::= <template-param>
3441// ::= <template-template-param> <template-args>
3442// ::= <decltype>
3443// ::= P <type> # pointer
3444// ::= R <type> # l-value reference
3445// ::= O <type> # r-value reference (C++11)
3446// ::= C <type> # complex pair (C99)
3447// ::= G <type> # imaginary (C99)
3448// ::= <substitution> # See Compression below
3449// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3450// extension ::= <vector-type> # <vector-type> starts with Dv
3451//
3452// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3453// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003454template <typename Derived, typename Alloc>
3455Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003456 Node *Result = nullptr;
3457
Richard Smithc20d1442018-08-20 20:14:49 +00003458 switch (look()) {
3459 // ::= <qualified-type>
3460 case 'r':
3461 case 'V':
3462 case 'K': {
3463 unsigned AfterQuals = 0;
3464 if (look(AfterQuals) == 'r') ++AfterQuals;
3465 if (look(AfterQuals) == 'V') ++AfterQuals;
3466 if (look(AfterQuals) == 'K') ++AfterQuals;
3467
3468 if (look(AfterQuals) == 'F' ||
3469 (look(AfterQuals) == 'D' &&
3470 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3471 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003472 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003473 break;
3474 }
3475 _LIBCPP_FALLTHROUGH();
3476 }
3477 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003478 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003479 break;
3480 }
3481 // <builtin-type> ::= v # void
3482 case 'v':
3483 ++First;
3484 return make<NameType>("void");
3485 // ::= w # wchar_t
3486 case 'w':
3487 ++First;
3488 return make<NameType>("wchar_t");
3489 // ::= b # bool
3490 case 'b':
3491 ++First;
3492 return make<NameType>("bool");
3493 // ::= c # char
3494 case 'c':
3495 ++First;
3496 return make<NameType>("char");
3497 // ::= a # signed char
3498 case 'a':
3499 ++First;
3500 return make<NameType>("signed char");
3501 // ::= h # unsigned char
3502 case 'h':
3503 ++First;
3504 return make<NameType>("unsigned char");
3505 // ::= s # short
3506 case 's':
3507 ++First;
3508 return make<NameType>("short");
3509 // ::= t # unsigned short
3510 case 't':
3511 ++First;
3512 return make<NameType>("unsigned short");
3513 // ::= i # int
3514 case 'i':
3515 ++First;
3516 return make<NameType>("int");
3517 // ::= j # unsigned int
3518 case 'j':
3519 ++First;
3520 return make<NameType>("unsigned int");
3521 // ::= l # long
3522 case 'l':
3523 ++First;
3524 return make<NameType>("long");
3525 // ::= m # unsigned long
3526 case 'm':
3527 ++First;
3528 return make<NameType>("unsigned long");
3529 // ::= x # long long, __int64
3530 case 'x':
3531 ++First;
3532 return make<NameType>("long long");
3533 // ::= y # unsigned long long, __int64
3534 case 'y':
3535 ++First;
3536 return make<NameType>("unsigned long long");
3537 // ::= n # __int128
3538 case 'n':
3539 ++First;
3540 return make<NameType>("__int128");
3541 // ::= o # unsigned __int128
3542 case 'o':
3543 ++First;
3544 return make<NameType>("unsigned __int128");
3545 // ::= f # float
3546 case 'f':
3547 ++First;
3548 return make<NameType>("float");
3549 // ::= d # double
3550 case 'd':
3551 ++First;
3552 return make<NameType>("double");
3553 // ::= e # long double, __float80
3554 case 'e':
3555 ++First;
3556 return make<NameType>("long double");
3557 // ::= g # __float128
3558 case 'g':
3559 ++First;
3560 return make<NameType>("__float128");
3561 // ::= z # ellipsis
3562 case 'z':
3563 ++First;
3564 return make<NameType>("...");
3565
3566 // <builtin-type> ::= u <source-name> # vendor extended type
3567 case 'u': {
3568 ++First;
3569 StringView Res = parseBareSourceName();
3570 if (Res.empty())
3571 return nullptr;
3572 return make<NameType>(Res);
3573 }
3574 case 'D':
3575 switch (look(1)) {
3576 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3577 case 'd':
3578 First += 2;
3579 return make<NameType>("decimal64");
3580 // ::= De # IEEE 754r decimal floating point (128 bits)
3581 case 'e':
3582 First += 2;
3583 return make<NameType>("decimal128");
3584 // ::= Df # IEEE 754r decimal floating point (32 bits)
3585 case 'f':
3586 First += 2;
3587 return make<NameType>("decimal32");
3588 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3589 case 'h':
3590 First += 2;
3591 return make<NameType>("decimal16");
3592 // ::= Di # char32_t
3593 case 'i':
3594 First += 2;
3595 return make<NameType>("char32_t");
3596 // ::= Ds # char16_t
3597 case 's':
3598 First += 2;
3599 return make<NameType>("char16_t");
3600 // ::= Da # auto (in dependent new-expressions)
3601 case 'a':
3602 First += 2;
3603 return make<NameType>("auto");
3604 // ::= Dc # decltype(auto)
3605 case 'c':
3606 First += 2;
3607 return make<NameType>("decltype(auto)");
3608 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3609 case 'n':
3610 First += 2;
3611 return make<NameType>("std::nullptr_t");
3612
3613 // ::= <decltype>
3614 case 't':
3615 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003616 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003617 break;
3618 }
3619 // extension ::= <vector-type> # <vector-type> starts with Dv
3620 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003621 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003622 break;
3623 }
3624 // ::= Dp <type> # pack expansion (C++0x)
3625 case 'p': {
3626 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003627 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003628 if (!Child)
3629 return nullptr;
3630 Result = make<ParameterPackExpansion>(Child);
3631 break;
3632 }
3633 // Exception specifier on a function type.
3634 case 'o':
3635 case 'O':
3636 case 'w':
3637 // Transaction safe function type.
3638 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003639 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003640 break;
3641 }
3642 break;
3643 // ::= <function-type>
3644 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003645 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003646 break;
3647 }
3648 // ::= <array-type>
3649 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003650 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003651 break;
3652 }
3653 // ::= <pointer-to-member-type>
3654 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003655 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003656 break;
3657 }
3658 // ::= <template-param>
3659 case 'T': {
3660 // This could be an elaborate type specifier on a <class-enum-type>.
3661 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00003662 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003663 break;
3664 }
3665
Pavel Labathba825192018-10-16 14:29:14 +00003666 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003667 if (Result == nullptr)
3668 return nullptr;
3669
3670 // Result could be either of:
3671 // <type> ::= <template-param>
3672 // <type> ::= <template-template-param> <template-args>
3673 //
3674 // <template-template-param> ::= <template-param>
3675 // ::= <substitution>
3676 //
3677 // If this is followed by some <template-args>, and we're permitted to
3678 // parse them, take the second production.
3679
3680 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003681 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003682 if (TA == nullptr)
3683 return nullptr;
3684 Result = make<NameWithTemplateArgs>(Result, TA);
3685 }
3686 break;
3687 }
3688 // ::= P <type> # pointer
3689 case 'P': {
3690 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003691 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003692 if (Ptr == nullptr)
3693 return nullptr;
3694 Result = make<PointerType>(Ptr);
3695 break;
3696 }
3697 // ::= R <type> # l-value reference
3698 case 'R': {
3699 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003700 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003701 if (Ref == nullptr)
3702 return nullptr;
3703 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
3704 break;
3705 }
3706 // ::= O <type> # r-value reference (C++11)
3707 case 'O': {
3708 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003709 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003710 if (Ref == nullptr)
3711 return nullptr;
3712 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
3713 break;
3714 }
3715 // ::= C <type> # complex pair (C99)
3716 case 'C': {
3717 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003718 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003719 if (P == nullptr)
3720 return nullptr;
3721 Result = make<PostfixQualifiedType>(P, " complex");
3722 break;
3723 }
3724 // ::= G <type> # imaginary (C99)
3725 case 'G': {
3726 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003727 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003728 if (P == nullptr)
3729 return P;
3730 Result = make<PostfixQualifiedType>(P, " imaginary");
3731 break;
3732 }
3733 // ::= <substitution> # See Compression below
3734 case 'S': {
3735 if (look(1) && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00003736 Node *Sub = getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003737 if (Sub == nullptr)
3738 return nullptr;
3739
3740 // Sub could be either of:
3741 // <type> ::= <substitution>
3742 // <type> ::= <template-template-param> <template-args>
3743 //
3744 // <template-template-param> ::= <template-param>
3745 // ::= <substitution>
3746 //
3747 // If this is followed by some <template-args>, and we're permitted to
3748 // parse them, take the second production.
3749
3750 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003751 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003752 if (TA == nullptr)
3753 return nullptr;
3754 Result = make<NameWithTemplateArgs>(Sub, TA);
3755 break;
3756 }
3757
3758 // If all we parsed was a substitution, don't re-insert into the
3759 // substitution table.
3760 return Sub;
3761 }
3762 _LIBCPP_FALLTHROUGH();
3763 }
3764 // ::= <class-enum-type>
3765 default: {
Pavel Labathba825192018-10-16 14:29:14 +00003766 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003767 break;
3768 }
3769 }
3770
3771 // If we parsed a type, insert it into the substitution table. Note that all
3772 // <builtin-type>s and <substitution>s have already bailed out, because they
3773 // don't get substitutions.
3774 if (Result != nullptr)
3775 Subs.push_back(Result);
3776 return Result;
3777}
3778
Pavel Labathba825192018-10-16 14:29:14 +00003779template <typename Derived, typename Alloc>
3780Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) {
3781 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003782 if (E == nullptr)
3783 return nullptr;
3784 return make<PrefixExpr>(Kind, E);
3785}
3786
Pavel Labathba825192018-10-16 14:29:14 +00003787template <typename Derived, typename Alloc>
3788Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) {
3789 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003790 if (LHS == nullptr)
3791 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003792 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003793 if (RHS == nullptr)
3794 return nullptr;
3795 return make<BinaryExpr>(LHS, Kind, RHS);
3796}
3797
Pavel Labathba825192018-10-16 14:29:14 +00003798template <typename Derived, typename Alloc>
3799Node *
3800AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00003801 StringView Tmp = parseNumber(true);
3802 if (!Tmp.empty() && consumeIf('E'))
3803 return make<IntegerLiteral>(Lit, Tmp);
3804 return nullptr;
3805}
3806
3807// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00003808template <typename Alloc, typename Derived>
3809Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00003810 Qualifiers CVR = QualNone;
3811 if (consumeIf('r'))
3812 CVR |= QualRestrict;
3813 if (consumeIf('V'))
3814 CVR |= QualVolatile;
3815 if (consumeIf('K'))
3816 CVR |= QualConst;
3817 return CVR;
3818}
3819
3820// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
3821// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
3822// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
3823// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
Pavel Labathba825192018-10-16 14:29:14 +00003824template <typename Derived, typename Alloc>
3825Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00003826 if (consumeIf("fp")) {
3827 parseCVQualifiers();
3828 StringView Num = parseNumber();
3829 if (!consumeIf('_'))
3830 return nullptr;
3831 return make<FunctionParam>(Num);
3832 }
3833 if (consumeIf("fL")) {
3834 if (parseNumber().empty())
3835 return nullptr;
3836 if (!consumeIf('p'))
3837 return nullptr;
3838 parseCVQualifiers();
3839 StringView Num = parseNumber();
3840 if (!consumeIf('_'))
3841 return nullptr;
3842 return make<FunctionParam>(Num);
3843 }
3844 return nullptr;
3845}
3846
3847// [gs] nw <expression>* _ <type> E # new (expr-list) type
3848// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
3849// [gs] na <expression>* _ <type> E # new[] (expr-list) type
3850// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
3851// <initializer> ::= pi <expression>* E # parenthesized initialization
Pavel Labathba825192018-10-16 14:29:14 +00003852template <typename Derived, typename Alloc>
3853Node *AbstractManglingParser<Derived, Alloc>::parseNewExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00003854 bool Global = consumeIf("gs");
3855 bool IsArray = look(1) == 'a';
3856 if (!consumeIf("nw") && !consumeIf("na"))
3857 return nullptr;
3858 size_t Exprs = Names.size();
3859 while (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003860 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003861 if (Ex == nullptr)
3862 return nullptr;
3863 Names.push_back(Ex);
3864 }
3865 NodeArray ExprList = popTrailingNodeArray(Exprs);
Pavel Labathba825192018-10-16 14:29:14 +00003866 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003867 if (Ty == nullptr)
3868 return Ty;
3869 if (consumeIf("pi")) {
3870 size_t InitsBegin = Names.size();
3871 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003872 Node *Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003873 if (Init == nullptr)
3874 return Init;
3875 Names.push_back(Init);
3876 }
3877 NodeArray Inits = popTrailingNodeArray(InitsBegin);
3878 return make<NewExpr>(ExprList, Ty, Inits, Global, IsArray);
3879 } else if (!consumeIf('E'))
3880 return nullptr;
3881 return make<NewExpr>(ExprList, Ty, NodeArray(), Global, IsArray);
3882}
3883
3884// cv <type> <expression> # conversion with one argument
3885// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00003886template <typename Derived, typename Alloc>
3887Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00003888 if (!consumeIf("cv"))
3889 return nullptr;
3890 Node *Ty;
3891 {
3892 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00003893 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003894 }
3895
3896 if (Ty == nullptr)
3897 return nullptr;
3898
3899 if (consumeIf('_')) {
3900 size_t ExprsBegin = Names.size();
3901 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003902 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003903 if (E == nullptr)
3904 return E;
3905 Names.push_back(E);
3906 }
3907 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
3908 return make<ConversionExpr>(Ty, Exprs);
3909 }
3910
Pavel Labathba825192018-10-16 14:29:14 +00003911 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00003912 if (E[0] == nullptr)
3913 return nullptr;
3914 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
3915}
3916
3917// <expr-primary> ::= L <type> <value number> E # integer literal
3918// ::= L <type> <value float> E # floating literal
3919// ::= L <string type> E # string literal
3920// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
3921// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
3922// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00003923template <typename Derived, typename Alloc>
3924Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00003925 if (!consumeIf('L'))
3926 return nullptr;
3927 switch (look()) {
3928 case 'w':
3929 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003930 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003931 case 'b':
3932 if (consumeIf("b0E"))
3933 return make<BoolExpr>(0);
3934 if (consumeIf("b1E"))
3935 return make<BoolExpr>(1);
3936 return nullptr;
3937 case 'c':
3938 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003939 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00003940 case 'a':
3941 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003942 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00003943 case 'h':
3944 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003945 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00003946 case 's':
3947 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003948 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00003949 case 't':
3950 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003951 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00003952 case 'i':
3953 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003954 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00003955 case 'j':
3956 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003957 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00003958 case 'l':
3959 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003960 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00003961 case 'm':
3962 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003963 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00003964 case 'x':
3965 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003966 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00003967 case 'y':
3968 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003969 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00003970 case 'n':
3971 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003972 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00003973 case 'o':
3974 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003975 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00003976 case 'f':
3977 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003978 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00003979 case 'd':
3980 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003981 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00003982 case 'e':
3983 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003984 return getDerived().template parseFloatingLiteral<long double>();
Richard Smithc20d1442018-08-20 20:14:49 +00003985 case '_':
3986 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00003987 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00003988 if (R != nullptr && consumeIf('E'))
3989 return R;
3990 }
3991 return nullptr;
3992 case 'T':
3993 // Invalid mangled name per
3994 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
3995 return nullptr;
3996 default: {
3997 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00003998 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003999 if (T == nullptr)
4000 return nullptr;
4001 StringView N = parseNumber();
4002 if (!N.empty()) {
4003 if (!consumeIf('E'))
4004 return nullptr;
4005 return make<IntegerCastExpr>(T, N);
4006 }
4007 if (consumeIf('E'))
4008 return T;
4009 return nullptr;
4010 }
4011 }
4012}
4013
4014// <braced-expression> ::= <expression>
4015// ::= di <field source-name> <braced-expression> # .name = expr
4016// ::= dx <index expression> <braced-expression> # [expr] = expr
4017// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004018template <typename Derived, typename Alloc>
4019Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004020 if (look() == 'd') {
4021 switch (look(1)) {
4022 case 'i': {
4023 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004024 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004025 if (Field == nullptr)
4026 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004027 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004028 if (Init == nullptr)
4029 return nullptr;
4030 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4031 }
4032 case 'x': {
4033 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004034 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004035 if (Index == nullptr)
4036 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004037 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004038 if (Init == nullptr)
4039 return nullptr;
4040 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4041 }
4042 case 'X': {
4043 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004044 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004045 if (RangeBegin == nullptr)
4046 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004047 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004048 if (RangeEnd == nullptr)
4049 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004050 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004051 if (Init == nullptr)
4052 return nullptr;
4053 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4054 }
4055 }
4056 }
Pavel Labathba825192018-10-16 14:29:14 +00004057 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004058}
4059
4060// (not yet in the spec)
4061// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4062// ::= fR <binary-operator-name> <expression> <expression>
4063// ::= fl <binary-operator-name> <expression>
4064// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004065template <typename Derived, typename Alloc>
4066Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004067 if (!consumeIf('f'))
4068 return nullptr;
4069
4070 char FoldKind = look();
4071 bool IsLeftFold, HasInitializer;
4072 HasInitializer = FoldKind == 'L' || FoldKind == 'R';
4073 if (FoldKind == 'l' || FoldKind == 'L')
4074 IsLeftFold = true;
4075 else if (FoldKind == 'r' || FoldKind == 'R')
4076 IsLeftFold = false;
4077 else
4078 return nullptr;
4079 ++First;
4080
4081 // FIXME: This map is duplicated in parseOperatorName and parseExpr.
4082 StringView OperatorName;
4083 if (consumeIf("aa")) OperatorName = "&&";
4084 else if (consumeIf("an")) OperatorName = "&";
4085 else if (consumeIf("aN")) OperatorName = "&=";
4086 else if (consumeIf("aS")) OperatorName = "=";
4087 else if (consumeIf("cm")) OperatorName = ",";
4088 else if (consumeIf("ds")) OperatorName = ".*";
4089 else if (consumeIf("dv")) OperatorName = "/";
4090 else if (consumeIf("dV")) OperatorName = "/=";
4091 else if (consumeIf("eo")) OperatorName = "^";
4092 else if (consumeIf("eO")) OperatorName = "^=";
4093 else if (consumeIf("eq")) OperatorName = "==";
4094 else if (consumeIf("ge")) OperatorName = ">=";
4095 else if (consumeIf("gt")) OperatorName = ">";
4096 else if (consumeIf("le")) OperatorName = "<=";
4097 else if (consumeIf("ls")) OperatorName = "<<";
4098 else if (consumeIf("lS")) OperatorName = "<<=";
4099 else if (consumeIf("lt")) OperatorName = "<";
4100 else if (consumeIf("mi")) OperatorName = "-";
4101 else if (consumeIf("mI")) OperatorName = "-=";
4102 else if (consumeIf("ml")) OperatorName = "*";
4103 else if (consumeIf("mL")) OperatorName = "*=";
4104 else if (consumeIf("ne")) OperatorName = "!=";
4105 else if (consumeIf("oo")) OperatorName = "||";
4106 else if (consumeIf("or")) OperatorName = "|";
4107 else if (consumeIf("oR")) OperatorName = "|=";
4108 else if (consumeIf("pl")) OperatorName = "+";
4109 else if (consumeIf("pL")) OperatorName = "+=";
4110 else if (consumeIf("rm")) OperatorName = "%";
4111 else if (consumeIf("rM")) OperatorName = "%=";
4112 else if (consumeIf("rs")) OperatorName = ">>";
4113 else if (consumeIf("rS")) OperatorName = ">>=";
4114 else return nullptr;
4115
Pavel Labathba825192018-10-16 14:29:14 +00004116 Node *Pack = getDerived().parseExpr(), *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004117 if (Pack == nullptr)
4118 return nullptr;
4119 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004120 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004121 if (Init == nullptr)
4122 return nullptr;
4123 }
4124
4125 if (IsLeftFold && Init)
4126 std::swap(Pack, Init);
4127
4128 return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
4129}
4130
4131// <expression> ::= <unary operator-name> <expression>
4132// ::= <binary operator-name> <expression> <expression>
4133// ::= <ternary operator-name> <expression> <expression> <expression>
4134// ::= cl <expression>+ E # call
4135// ::= cv <type> <expression> # conversion with one argument
4136// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4137// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4138// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4139// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4140// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4141// ::= [gs] dl <expression> # delete expression
4142// ::= [gs] da <expression> # delete[] expression
4143// ::= pp_ <expression> # prefix ++
4144// ::= mm_ <expression> # prefix --
4145// ::= ti <type> # typeid (type)
4146// ::= te <expression> # typeid (expression)
4147// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4148// ::= sc <type> <expression> # static_cast<type> (expression)
4149// ::= cc <type> <expression> # const_cast<type> (expression)
4150// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4151// ::= st <type> # sizeof (a type)
4152// ::= sz <expression> # sizeof (an expression)
4153// ::= at <type> # alignof (a type)
4154// ::= az <expression> # alignof (an expression)
4155// ::= nx <expression> # noexcept (expression)
4156// ::= <template-param>
4157// ::= <function-param>
4158// ::= dt <expression> <unresolved-name> # expr.name
4159// ::= pt <expression> <unresolved-name> # expr->name
4160// ::= ds <expression> <expression> # expr.*expr
4161// ::= sZ <template-param> # size of a parameter pack
4162// ::= sZ <function-param> # size of a function parameter pack
4163// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4164// ::= sp <expression> # pack expansion
4165// ::= tw <expression> # throw expression
4166// ::= tr # throw with no operand (rethrow)
4167// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4168// # freestanding dependent name (e.g., T::x),
4169// # objectless nonstatic member reference
4170// ::= fL <binary-operator-name> <expression> <expression>
4171// ::= fR <binary-operator-name> <expression> <expression>
4172// ::= fl <binary-operator-name> <expression>
4173// ::= fr <binary-operator-name> <expression>
4174// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004175template <typename Derived, typename Alloc>
4176Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004177 bool Global = consumeIf("gs");
4178 if (numLeft() < 2)
4179 return nullptr;
4180
4181 switch (*First) {
4182 case 'L':
Pavel Labathba825192018-10-16 14:29:14 +00004183 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00004184 case 'T':
Pavel Labathba825192018-10-16 14:29:14 +00004185 return getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004186 case 'f': {
4187 // Disambiguate a fold expression from a <function-param>.
4188 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
Pavel Labathba825192018-10-16 14:29:14 +00004189 return getDerived().parseFunctionParam();
4190 return getDerived().parseFoldExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004191 }
4192 case 'a':
4193 switch (First[1]) {
4194 case 'a':
4195 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004196 return getDerived().parseBinaryExpr("&&");
Richard Smithc20d1442018-08-20 20:14:49 +00004197 case 'd':
4198 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004199 return getDerived().parsePrefixExpr("&");
Richard Smithc20d1442018-08-20 20:14:49 +00004200 case 'n':
4201 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004202 return getDerived().parseBinaryExpr("&");
Richard Smithc20d1442018-08-20 20:14:49 +00004203 case 'N':
4204 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004205 return getDerived().parseBinaryExpr("&=");
Richard Smithc20d1442018-08-20 20:14:49 +00004206 case 'S':
4207 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004208 return getDerived().parseBinaryExpr("=");
Richard Smithc20d1442018-08-20 20:14:49 +00004209 case 't': {
4210 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004211 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004212 if (Ty == nullptr)
4213 return nullptr;
4214 return make<EnclosingExpr>("alignof (", Ty, ")");
4215 }
4216 case 'z': {
4217 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004218 Node *Ty = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004219 if (Ty == nullptr)
4220 return nullptr;
4221 return make<EnclosingExpr>("alignof (", Ty, ")");
4222 }
4223 }
4224 return nullptr;
4225 case 'c':
4226 switch (First[1]) {
4227 // cc <type> <expression> # const_cast<type>(expression)
4228 case 'c': {
4229 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004230 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004231 if (Ty == nullptr)
4232 return Ty;
Pavel Labathba825192018-10-16 14:29:14 +00004233 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004234 if (Ex == nullptr)
4235 return Ex;
4236 return make<CastExpr>("const_cast", Ty, Ex);
4237 }
4238 // cl <expression>+ E # call
4239 case 'l': {
4240 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004241 Node *Callee = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004242 if (Callee == nullptr)
4243 return Callee;
4244 size_t ExprsBegin = Names.size();
4245 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004246 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004247 if (E == nullptr)
4248 return E;
4249 Names.push_back(E);
4250 }
4251 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin));
4252 }
4253 case 'm':
4254 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004255 return getDerived().parseBinaryExpr(",");
Richard Smithc20d1442018-08-20 20:14:49 +00004256 case 'o':
4257 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004258 return getDerived().parsePrefixExpr("~");
Richard Smithc20d1442018-08-20 20:14:49 +00004259 case 'v':
Pavel Labathba825192018-10-16 14:29:14 +00004260 return getDerived().parseConversionExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004261 }
4262 return nullptr;
4263 case 'd':
4264 switch (First[1]) {
4265 case 'a': {
4266 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004267 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004268 if (Ex == nullptr)
4269 return Ex;
4270 return make<DeleteExpr>(Ex, Global, /*is_array=*/true);
4271 }
4272 case 'c': {
4273 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004274 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004275 if (T == nullptr)
4276 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004277 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004278 if (Ex == nullptr)
4279 return Ex;
4280 return make<CastExpr>("dynamic_cast", T, Ex);
4281 }
4282 case 'e':
4283 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004284 return getDerived().parsePrefixExpr("*");
Richard Smithc20d1442018-08-20 20:14:49 +00004285 case 'l': {
4286 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004287 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004288 if (E == nullptr)
4289 return E;
4290 return make<DeleteExpr>(E, Global, /*is_array=*/false);
4291 }
4292 case 'n':
Pavel Labathba825192018-10-16 14:29:14 +00004293 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004294 case 's': {
4295 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004296 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004297 if (LHS == nullptr)
4298 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004299 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004300 if (RHS == nullptr)
4301 return nullptr;
4302 return make<MemberExpr>(LHS, ".*", RHS);
4303 }
4304 case 't': {
4305 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004306 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004307 if (LHS == nullptr)
4308 return LHS;
Pavel Labathba825192018-10-16 14:29:14 +00004309 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004310 if (RHS == nullptr)
4311 return nullptr;
4312 return make<MemberExpr>(LHS, ".", RHS);
4313 }
4314 case 'v':
4315 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004316 return getDerived().parseBinaryExpr("/");
Richard Smithc20d1442018-08-20 20:14:49 +00004317 case 'V':
4318 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004319 return getDerived().parseBinaryExpr("/=");
Richard Smithc20d1442018-08-20 20:14:49 +00004320 }
4321 return nullptr;
4322 case 'e':
4323 switch (First[1]) {
4324 case 'o':
4325 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004326 return getDerived().parseBinaryExpr("^");
Richard Smithc20d1442018-08-20 20:14:49 +00004327 case 'O':
4328 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004329 return getDerived().parseBinaryExpr("^=");
Richard Smithc20d1442018-08-20 20:14:49 +00004330 case 'q':
4331 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004332 return getDerived().parseBinaryExpr("==");
Richard Smithc20d1442018-08-20 20:14:49 +00004333 }
4334 return nullptr;
4335 case 'g':
4336 switch (First[1]) {
4337 case 'e':
4338 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004339 return getDerived().parseBinaryExpr(">=");
Richard Smithc20d1442018-08-20 20:14:49 +00004340 case 't':
4341 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004342 return getDerived().parseBinaryExpr(">");
Richard Smithc20d1442018-08-20 20:14:49 +00004343 }
4344 return nullptr;
4345 case 'i':
4346 switch (First[1]) {
4347 case 'x': {
4348 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004349 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004350 if (Base == nullptr)
4351 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004352 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004353 if (Index == nullptr)
4354 return Index;
4355 return make<ArraySubscriptExpr>(Base, Index);
4356 }
4357 case 'l': {
4358 First += 2;
4359 size_t InitsBegin = Names.size();
4360 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004361 Node *E = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004362 if (E == nullptr)
4363 return nullptr;
4364 Names.push_back(E);
4365 }
4366 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4367 }
4368 }
4369 return nullptr;
4370 case 'l':
4371 switch (First[1]) {
4372 case 'e':
4373 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004374 return getDerived().parseBinaryExpr("<=");
Richard Smithc20d1442018-08-20 20:14:49 +00004375 case 's':
4376 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004377 return getDerived().parseBinaryExpr("<<");
Richard Smithc20d1442018-08-20 20:14:49 +00004378 case 'S':
4379 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004380 return getDerived().parseBinaryExpr("<<=");
Richard Smithc20d1442018-08-20 20:14:49 +00004381 case 't':
4382 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004383 return getDerived().parseBinaryExpr("<");
Richard Smithc20d1442018-08-20 20:14:49 +00004384 }
4385 return nullptr;
4386 case 'm':
4387 switch (First[1]) {
4388 case 'i':
4389 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004390 return getDerived().parseBinaryExpr("-");
Richard Smithc20d1442018-08-20 20:14:49 +00004391 case 'I':
4392 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004393 return getDerived().parseBinaryExpr("-=");
Richard Smithc20d1442018-08-20 20:14:49 +00004394 case 'l':
4395 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004396 return getDerived().parseBinaryExpr("*");
Richard Smithc20d1442018-08-20 20:14:49 +00004397 case 'L':
4398 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004399 return getDerived().parseBinaryExpr("*=");
Richard Smithc20d1442018-08-20 20:14:49 +00004400 case 'm':
4401 First += 2;
4402 if (consumeIf('_'))
Pavel Labathba825192018-10-16 14:29:14 +00004403 return getDerived().parsePrefixExpr("--");
4404 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004405 if (Ex == nullptr)
4406 return nullptr;
4407 return make<PostfixExpr>(Ex, "--");
4408 }
4409 return nullptr;
4410 case 'n':
4411 switch (First[1]) {
4412 case 'a':
4413 case 'w':
Pavel Labathba825192018-10-16 14:29:14 +00004414 return getDerived().parseNewExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004415 case 'e':
4416 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004417 return getDerived().parseBinaryExpr("!=");
Richard Smithc20d1442018-08-20 20:14:49 +00004418 case 'g':
4419 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004420 return getDerived().parsePrefixExpr("-");
Richard Smithc20d1442018-08-20 20:14:49 +00004421 case 't':
4422 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004423 return getDerived().parsePrefixExpr("!");
Richard Smithc20d1442018-08-20 20:14:49 +00004424 case 'x':
4425 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004426 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004427 if (Ex == nullptr)
4428 return Ex;
4429 return make<EnclosingExpr>("noexcept (", Ex, ")");
4430 }
4431 return nullptr;
4432 case 'o':
4433 switch (First[1]) {
4434 case 'n':
Pavel Labathba825192018-10-16 14:29:14 +00004435 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004436 case 'o':
4437 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004438 return getDerived().parseBinaryExpr("||");
Richard Smithc20d1442018-08-20 20:14:49 +00004439 case 'r':
4440 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004441 return getDerived().parseBinaryExpr("|");
Richard Smithc20d1442018-08-20 20:14:49 +00004442 case 'R':
4443 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004444 return getDerived().parseBinaryExpr("|=");
Richard Smithc20d1442018-08-20 20:14:49 +00004445 }
4446 return nullptr;
4447 case 'p':
4448 switch (First[1]) {
4449 case 'm':
4450 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004451 return getDerived().parseBinaryExpr("->*");
Richard Smithc20d1442018-08-20 20:14:49 +00004452 case 'l':
4453 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004454 return getDerived().parseBinaryExpr("+");
Richard Smithc20d1442018-08-20 20:14:49 +00004455 case 'L':
4456 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004457 return getDerived().parseBinaryExpr("+=");
Richard Smithc20d1442018-08-20 20:14:49 +00004458 case 'p': {
4459 First += 2;
4460 if (consumeIf('_'))
Pavel Labathba825192018-10-16 14:29:14 +00004461 return getDerived().parsePrefixExpr("++");
4462 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004463 if (Ex == nullptr)
4464 return Ex;
4465 return make<PostfixExpr>(Ex, "++");
4466 }
4467 case 's':
4468 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004469 return getDerived().parsePrefixExpr("+");
Richard Smithc20d1442018-08-20 20:14:49 +00004470 case 't': {
4471 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004472 Node *L = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004473 if (L == nullptr)
4474 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004475 Node *R = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004476 if (R == nullptr)
4477 return nullptr;
4478 return make<MemberExpr>(L, "->", R);
4479 }
4480 }
4481 return nullptr;
4482 case 'q':
4483 if (First[1] == 'u') {
4484 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004485 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004486 if (Cond == nullptr)
4487 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004488 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004489 if (LHS == nullptr)
4490 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004491 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004492 if (RHS == nullptr)
4493 return nullptr;
4494 return make<ConditionalExpr>(Cond, LHS, RHS);
4495 }
4496 return nullptr;
4497 case 'r':
4498 switch (First[1]) {
4499 case 'c': {
4500 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004501 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004502 if (T == nullptr)
4503 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004504 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004505 if (Ex == nullptr)
4506 return Ex;
4507 return make<CastExpr>("reinterpret_cast", T, Ex);
4508 }
4509 case 'm':
4510 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004511 return getDerived().parseBinaryExpr("%");
Richard Smithc20d1442018-08-20 20:14:49 +00004512 case 'M':
4513 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004514 return getDerived().parseBinaryExpr("%=");
Richard Smithc20d1442018-08-20 20:14:49 +00004515 case 's':
4516 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004517 return getDerived().parseBinaryExpr(">>");
Richard Smithc20d1442018-08-20 20:14:49 +00004518 case 'S':
4519 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004520 return getDerived().parseBinaryExpr(">>=");
Richard Smithc20d1442018-08-20 20:14:49 +00004521 }
4522 return nullptr;
4523 case 's':
4524 switch (First[1]) {
4525 case 'c': {
4526 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004527 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004528 if (T == nullptr)
4529 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004530 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004531 if (Ex == nullptr)
4532 return Ex;
4533 return make<CastExpr>("static_cast", T, Ex);
4534 }
4535 case 'p': {
4536 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004537 Node *Child = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004538 if (Child == nullptr)
4539 return nullptr;
4540 return make<ParameterPackExpansion>(Child);
4541 }
4542 case 'r':
Pavel Labathba825192018-10-16 14:29:14 +00004543 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004544 case 't': {
4545 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004546 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004547 if (Ty == nullptr)
4548 return Ty;
4549 return make<EnclosingExpr>("sizeof (", Ty, ")");
4550 }
4551 case 'z': {
4552 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004553 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004554 if (Ex == nullptr)
4555 return Ex;
4556 return make<EnclosingExpr>("sizeof (", Ex, ")");
4557 }
4558 case 'Z':
4559 First += 2;
4560 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00004561 Node *R = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004562 if (R == nullptr)
4563 return nullptr;
4564 return make<SizeofParamPackExpr>(R);
4565 } else if (look() == 'f') {
Pavel Labathba825192018-10-16 14:29:14 +00004566 Node *FP = getDerived().parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004567 if (FP == nullptr)
4568 return nullptr;
4569 return make<EnclosingExpr>("sizeof... (", FP, ")");
4570 }
4571 return nullptr;
4572 case 'P': {
4573 First += 2;
4574 size_t ArgsBegin = Names.size();
4575 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004576 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00004577 if (Arg == nullptr)
4578 return nullptr;
4579 Names.push_back(Arg);
4580 }
Richard Smithb485b352018-08-24 23:30:26 +00004581 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4582 if (!Pack)
4583 return nullptr;
4584 return make<EnclosingExpr>("sizeof... (", Pack, ")");
Richard Smithc20d1442018-08-20 20:14:49 +00004585 }
4586 }
4587 return nullptr;
4588 case 't':
4589 switch (First[1]) {
4590 case 'e': {
4591 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004592 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004593 if (Ex == nullptr)
4594 return Ex;
4595 return make<EnclosingExpr>("typeid (", Ex, ")");
4596 }
4597 case 'i': {
4598 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004599 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004600 if (Ty == nullptr)
4601 return Ty;
4602 return make<EnclosingExpr>("typeid (", Ty, ")");
4603 }
4604 case 'l': {
4605 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004606 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004607 if (Ty == nullptr)
4608 return nullptr;
4609 size_t InitsBegin = Names.size();
4610 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004611 Node *E = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004612 if (E == nullptr)
4613 return nullptr;
4614 Names.push_back(E);
4615 }
4616 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4617 }
4618 case 'r':
4619 First += 2;
4620 return make<NameType>("throw");
4621 case 'w': {
4622 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004623 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004624 if (Ex == nullptr)
4625 return nullptr;
4626 return make<ThrowExpr>(Ex);
4627 }
4628 }
4629 return nullptr;
4630 case '1':
4631 case '2':
4632 case '3':
4633 case '4':
4634 case '5':
4635 case '6':
4636 case '7':
4637 case '8':
4638 case '9':
Pavel Labathba825192018-10-16 14:29:14 +00004639 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004640 }
4641 return nullptr;
4642}
4643
4644// <call-offset> ::= h <nv-offset> _
4645// ::= v <v-offset> _
4646//
4647// <nv-offset> ::= <offset number>
4648// # non-virtual base override
4649//
4650// <v-offset> ::= <offset number> _ <virtual offset number>
4651// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004652template <typename Alloc, typename Derived>
4653bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004654 // Just scan through the call offset, we never add this information into the
4655 // output.
4656 if (consumeIf('h'))
4657 return parseNumber(true).empty() || !consumeIf('_');
4658 if (consumeIf('v'))
4659 return parseNumber(true).empty() || !consumeIf('_') ||
4660 parseNumber(true).empty() || !consumeIf('_');
4661 return true;
4662}
4663
4664// <special-name> ::= TV <type> # virtual table
4665// ::= TT <type> # VTT structure (construction vtable index)
4666// ::= TI <type> # typeinfo structure
4667// ::= TS <type> # typeinfo name (null-terminated byte string)
4668// ::= Tc <call-offset> <call-offset> <base encoding>
4669// # base is the nominal target function of thunk
4670// # first call-offset is 'this' adjustment
4671// # second call-offset is result adjustment
4672// ::= T <call-offset> <base encoding>
4673// # base is the nominal target function of thunk
4674// ::= GV <object name> # Guard variable for one-time initialization
4675// # No <type>
4676// ::= TW <object name> # Thread-local wrapper
4677// ::= TH <object name> # Thread-local initialization
4678// ::= GR <object name> _ # First temporary
4679// ::= GR <object name> <seq-id> _ # Subsequent temporaries
4680// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4681// extension ::= GR <object name> # reference temporary for object
Pavel Labathba825192018-10-16 14:29:14 +00004682template <typename Derived, typename Alloc>
4683Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004684 switch (look()) {
4685 case 'T':
4686 switch (look(1)) {
4687 // TV <type> # virtual table
4688 case 'V': {
4689 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004690 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004691 if (Ty == nullptr)
4692 return nullptr;
4693 return make<SpecialName>("vtable for ", Ty);
4694 }
4695 // TT <type> # VTT structure (construction vtable index)
4696 case 'T': {
4697 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004698 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004699 if (Ty == nullptr)
4700 return nullptr;
4701 return make<SpecialName>("VTT for ", Ty);
4702 }
4703 // TI <type> # typeinfo structure
4704 case 'I': {
4705 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004706 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004707 if (Ty == nullptr)
4708 return nullptr;
4709 return make<SpecialName>("typeinfo for ", Ty);
4710 }
4711 // TS <type> # typeinfo name (null-terminated byte string)
4712 case 'S': {
4713 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004714 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004715 if (Ty == nullptr)
4716 return nullptr;
4717 return make<SpecialName>("typeinfo name for ", Ty);
4718 }
4719 // Tc <call-offset> <call-offset> <base encoding>
4720 case 'c': {
4721 First += 2;
4722 if (parseCallOffset() || parseCallOffset())
4723 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004724 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004725 if (Encoding == nullptr)
4726 return nullptr;
4727 return make<SpecialName>("covariant return thunk to ", Encoding);
4728 }
4729 // extension ::= TC <first type> <number> _ <second type>
4730 // # construction vtable for second-in-first
4731 case 'C': {
4732 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004733 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004734 if (FirstType == nullptr)
4735 return nullptr;
4736 if (parseNumber(true).empty() || !consumeIf('_'))
4737 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004738 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004739 if (SecondType == nullptr)
4740 return nullptr;
4741 return make<CtorVtableSpecialName>(SecondType, FirstType);
4742 }
4743 // TW <object name> # Thread-local wrapper
4744 case 'W': {
4745 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004746 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004747 if (Name == nullptr)
4748 return nullptr;
4749 return make<SpecialName>("thread-local wrapper routine for ", Name);
4750 }
4751 // TH <object name> # Thread-local initialization
4752 case 'H': {
4753 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004754 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004755 if (Name == nullptr)
4756 return nullptr;
4757 return make<SpecialName>("thread-local initialization routine for ", Name);
4758 }
4759 // T <call-offset> <base encoding>
4760 default: {
4761 ++First;
4762 bool IsVirt = look() == 'v';
4763 if (parseCallOffset())
4764 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004765 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004766 if (BaseEncoding == nullptr)
4767 return nullptr;
4768 if (IsVirt)
4769 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4770 else
4771 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4772 }
4773 }
4774 case 'G':
4775 switch (look(1)) {
4776 // GV <object name> # Guard variable for one-time initialization
4777 case 'V': {
4778 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004779 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004780 if (Name == nullptr)
4781 return nullptr;
4782 return make<SpecialName>("guard variable for ", Name);
4783 }
4784 // GR <object name> # reference temporary for object
4785 // GR <object name> _ # First temporary
4786 // GR <object name> <seq-id> _ # Subsequent temporaries
4787 case 'R': {
4788 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004789 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004790 if (Name == nullptr)
4791 return nullptr;
4792 size_t Count;
4793 bool ParsedSeqId = !parseSeqId(&Count);
4794 if (!consumeIf('_') && ParsedSeqId)
4795 return nullptr;
4796 return make<SpecialName>("reference temporary for ", Name);
4797 }
4798 }
4799 }
4800 return nullptr;
4801}
4802
4803// <encoding> ::= <function name> <bare-function-type>
4804// ::= <data name>
4805// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00004806template <typename Derived, typename Alloc>
4807Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithc20d1442018-08-20 20:14:49 +00004808 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00004809 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00004810
4811 auto IsEndOfEncoding = [&] {
4812 // The set of chars that can potentially follow an <encoding> (none of which
4813 // can start a <type>). Enumerating these allows us to avoid speculative
4814 // parsing.
4815 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
4816 };
4817
4818 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00004819 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00004820 if (Name == nullptr)
4821 return nullptr;
4822
4823 if (resolveForwardTemplateRefs(NameInfo))
4824 return nullptr;
4825
4826 if (IsEndOfEncoding())
4827 return Name;
4828
4829 Node *Attrs = nullptr;
4830 if (consumeIf("Ua9enable_ifI")) {
4831 size_t BeforeArgs = Names.size();
4832 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004833 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00004834 if (Arg == nullptr)
4835 return nullptr;
4836 Names.push_back(Arg);
4837 }
4838 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00004839 if (!Attrs)
4840 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004841 }
4842
4843 Node *ReturnType = nullptr;
4844 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00004845 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004846 if (ReturnType == nullptr)
4847 return nullptr;
4848 }
4849
4850 if (consumeIf('v'))
4851 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
4852 Attrs, NameInfo.CVQualifiers,
4853 NameInfo.ReferenceQualifier);
4854
4855 size_t ParamsBegin = Names.size();
4856 do {
Pavel Labathba825192018-10-16 14:29:14 +00004857 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004858 if (Ty == nullptr)
4859 return nullptr;
4860 Names.push_back(Ty);
4861 } while (!IsEndOfEncoding());
4862
4863 return make<FunctionEncoding>(ReturnType, Name,
4864 popTrailingNodeArray(ParamsBegin),
4865 Attrs, NameInfo.CVQualifiers,
4866 NameInfo.ReferenceQualifier);
4867}
4868
4869template <class Float>
4870struct FloatData;
4871
4872template <>
4873struct FloatData<float>
4874{
4875 static const size_t mangled_size = 8;
4876 static const size_t max_demangled_size = 24;
4877 static constexpr const char* spec = "%af";
4878};
4879
4880template <>
4881struct FloatData<double>
4882{
4883 static const size_t mangled_size = 16;
4884 static const size_t max_demangled_size = 32;
4885 static constexpr const char* spec = "%a";
4886};
4887
4888template <>
4889struct FloatData<long double>
4890{
4891#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
4892 defined(__wasm__)
4893 static const size_t mangled_size = 32;
4894#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
4895 static const size_t mangled_size = 16;
4896#else
4897 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
4898#endif
4899 static const size_t max_demangled_size = 40;
4900 static constexpr const char *spec = "%LaL";
4901};
4902
Pavel Labathba825192018-10-16 14:29:14 +00004903template <typename Alloc, typename Derived>
4904template <class Float>
4905Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00004906 const size_t N = FloatData<Float>::mangled_size;
4907 if (numLeft() <= N)
4908 return nullptr;
4909 StringView Data(First, First + N);
4910 for (char C : Data)
4911 if (!std::isxdigit(C))
4912 return nullptr;
4913 First += N;
4914 if (!consumeIf('E'))
4915 return nullptr;
4916 return make<FloatLiteralImpl<Float>>(Data);
4917}
4918
4919// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00004920template <typename Alloc, typename Derived>
4921bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00004922 if (!(look() >= '0' && look() <= '9') &&
4923 !(look() >= 'A' && look() <= 'Z'))
4924 return true;
4925
4926 size_t Id = 0;
4927 while (true) {
4928 if (look() >= '0' && look() <= '9') {
4929 Id *= 36;
4930 Id += static_cast<size_t>(look() - '0');
4931 } else if (look() >= 'A' && look() <= 'Z') {
4932 Id *= 36;
4933 Id += static_cast<size_t>(look() - 'A') + 10;
4934 } else {
4935 *Out = Id;
4936 return false;
4937 }
4938 ++First;
4939 }
4940}
4941
4942// <substitution> ::= S <seq-id> _
4943// ::= S_
4944// <substitution> ::= Sa # ::std::allocator
4945// <substitution> ::= Sb # ::std::basic_string
4946// <substitution> ::= Ss # ::std::basic_string < char,
4947// ::std::char_traits<char>,
4948// ::std::allocator<char> >
4949// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
4950// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
4951// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Pavel Labathba825192018-10-16 14:29:14 +00004952template <typename Derived, typename Alloc>
4953Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00004954 if (!consumeIf('S'))
4955 return nullptr;
4956
4957 if (std::islower(look())) {
4958 Node *SpecialSub;
4959 switch (look()) {
4960 case 'a':
4961 ++First;
4962 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::allocator);
4963 break;
4964 case 'b':
4965 ++First;
4966 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::basic_string);
4967 break;
4968 case 's':
4969 ++First;
4970 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::string);
4971 break;
4972 case 'i':
4973 ++First;
4974 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::istream);
4975 break;
4976 case 'o':
4977 ++First;
4978 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::ostream);
4979 break;
4980 case 'd':
4981 ++First;
4982 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::iostream);
4983 break;
4984 default:
4985 return nullptr;
4986 }
Richard Smithb485b352018-08-24 23:30:26 +00004987 if (!SpecialSub)
4988 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004989 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
4990 // has ABI tags, the tags are appended to the substitution; the result is a
4991 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00004992 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00004993 if (WithTags != SpecialSub) {
4994 Subs.push_back(WithTags);
4995 SpecialSub = WithTags;
4996 }
4997 return SpecialSub;
4998 }
4999
5000 // ::= S_
5001 if (consumeIf('_')) {
5002 if (Subs.empty())
5003 return nullptr;
5004 return Subs[0];
5005 }
5006
5007 // ::= S <seq-id> _
5008 size_t Index = 0;
5009 if (parseSeqId(&Index))
5010 return nullptr;
5011 ++Index;
5012 if (!consumeIf('_') || Index >= Subs.size())
5013 return nullptr;
5014 return Subs[Index];
5015}
5016
5017// <template-param> ::= T_ # first template parameter
5018// ::= T <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005019template <typename Derived, typename Alloc>
5020Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005021 if (!consumeIf('T'))
5022 return nullptr;
5023
5024 size_t Index = 0;
5025 if (!consumeIf('_')) {
5026 if (parsePositiveInteger(&Index))
5027 return nullptr;
5028 ++Index;
5029 if (!consumeIf('_'))
5030 return nullptr;
5031 }
5032
5033 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter list
5034 // are mangled as the corresponding artificial template type parameter.
5035 if (ParsingLambdaParams)
5036 return make<NameType>("auto");
5037
5038 // If we're in a context where this <template-param> refers to a
5039 // <template-arg> further ahead in the mangled name (currently just conversion
5040 // operator types), then we should only look it up in the right context.
5041 if (PermitForwardTemplateReferences) {
Richard Smithb485b352018-08-24 23:30:26 +00005042 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5043 if (!ForwardRef)
5044 return nullptr;
5045 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5046 ForwardTemplateRefs.push_back(
5047 static_cast<ForwardTemplateReference *>(ForwardRef));
5048 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005049 }
5050
5051 if (Index >= TemplateParams.size())
5052 return nullptr;
5053 return TemplateParams[Index];
5054}
5055
5056// <template-arg> ::= <type> # type or template
5057// ::= X <expression> E # expression
5058// ::= <expr-primary> # simple expressions
5059// ::= J <template-arg>* E # argument pack
5060// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005061template <typename Derived, typename Alloc>
5062Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005063 switch (look()) {
5064 case 'X': {
5065 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005066 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005067 if (Arg == nullptr || !consumeIf('E'))
5068 return nullptr;
5069 return Arg;
5070 }
5071 case 'J': {
5072 ++First;
5073 size_t ArgsBegin = Names.size();
5074 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005075 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005076 if (Arg == nullptr)
5077 return nullptr;
5078 Names.push_back(Arg);
5079 }
5080 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5081 return make<TemplateArgumentPack>(Args);
5082 }
5083 case 'L': {
5084 // ::= LZ <encoding> E # extension
5085 if (look(1) == 'Z') {
5086 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005087 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005088 if (Arg == nullptr || !consumeIf('E'))
5089 return nullptr;
5090 return Arg;
5091 }
5092 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005093 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005094 }
5095 default:
Pavel Labathba825192018-10-16 14:29:14 +00005096 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005097 }
5098}
5099
5100// <template-args> ::= I <template-arg>* E
5101// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005102template <typename Derived, typename Alloc>
5103Node *
5104AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005105 if (!consumeIf('I'))
5106 return nullptr;
5107
5108 // <template-params> refer to the innermost <template-args>. Clear out any
5109 // outer args that we may have inserted into TemplateParams.
5110 if (TagTemplates)
5111 TemplateParams.clear();
5112
5113 size_t ArgsBegin = Names.size();
5114 while (!consumeIf('E')) {
5115 if (TagTemplates) {
5116 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005117 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005118 TemplateParams = std::move(OldParams);
5119 if (Arg == nullptr)
5120 return nullptr;
5121 Names.push_back(Arg);
5122 Node *TableEntry = Arg;
5123 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5124 TableEntry = make<ParameterPack>(
5125 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005126 if (!TableEntry)
5127 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005128 }
5129 TemplateParams.push_back(TableEntry);
5130 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005131 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005132 if (Arg == nullptr)
5133 return nullptr;
5134 Names.push_back(Arg);
5135 }
5136 }
5137 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5138}
5139
5140// <mangled-name> ::= _Z <encoding>
5141// ::= <type>
5142// extension ::= ___Z <encoding> _block_invoke
5143// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5144// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005145template <typename Derived, typename Alloc>
5146Node *AbstractManglingParser<Derived, Alloc>::parse() {
Richard Smithc20d1442018-08-20 20:14:49 +00005147 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005148 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005149 if (Encoding == nullptr)
5150 return nullptr;
5151 if (look() == '.') {
5152 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5153 First = Last;
5154 }
5155 if (numLeft() != 0)
5156 return nullptr;
5157 return Encoding;
5158 }
5159
5160 if (consumeIf("___Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005161 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005162 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5163 return nullptr;
5164 bool RequireNumber = consumeIf('_');
5165 if (parseNumber().empty() && RequireNumber)
5166 return nullptr;
5167 if (look() == '.')
5168 First = Last;
5169 if (numLeft() != 0)
5170 return nullptr;
5171 return make<SpecialName>("invocation function for block in ", Encoding);
5172 }
5173
Pavel Labathba825192018-10-16 14:29:14 +00005174 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005175 if (numLeft() != 0)
5176 return nullptr;
5177 return Ty;
5178}
5179
Pavel Labathba825192018-10-16 14:29:14 +00005180template <typename Alloc>
5181struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5182 using AbstractManglingParser<ManglingParser<Alloc>,
5183 Alloc>::AbstractManglingParser;
5184};
5185
Richard Smithc20d1442018-08-20 20:14:49 +00005186} // namespace itanium_demangle
5187} // namespace
5188
5189#endif // LIBCXX_DEMANGLE_ITANIUMDEMANGLE_H