blob: 9a54ff5d80d59505f072df5e9deee4954bdb2dca [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//
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000010// Generic itanium demangler library. This file has two byte-per-byte identical
11// copies in the source tree, one in libcxxabi, and the other in llvm.
Richard Smithc20d1442018-08-20 20:14:49 +000012//
13//===----------------------------------------------------------------------===//
14
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000015#ifndef DEMANGLE_ITANIUMDEMANGLE_H
16#define DEMANGLE_ITANIUMDEMANGLE_H
Richard Smithc20d1442018-08-20 20:14:49 +000017
18// FIXME: (possibly) incomplete list of features that clang mangles that this
19// file does not yet support:
20// - C++ modules TS
21
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000022#include "DemangleConfig.h"
Richard Smithc20d1442018-08-20 20:14:49 +000023#include "StringView.h"
24#include "Utility.h"
Richard Smithc20d1442018-08-20 20:14:49 +000025#include <cassert>
26#include <cctype>
27#include <cstdio>
28#include <cstdlib>
29#include <cstring>
30#include <numeric>
31#include <utility>
32
33#define FOR_EACH_NODE_KIND(X) \
34 X(NodeArrayNode) \
35 X(DotSuffix) \
36 X(VendorExtQualType) \
37 X(QualType) \
38 X(ConversionOperatorType) \
39 X(PostfixQualifiedType) \
40 X(ElaboratedTypeSpefType) \
41 X(NameType) \
42 X(AbiTagAttr) \
43 X(EnableIfAttr) \
44 X(ObjCProtoName) \
45 X(PointerType) \
46 X(ReferenceType) \
47 X(PointerToMemberType) \
48 X(ArrayType) \
49 X(FunctionType) \
50 X(NoexceptSpec) \
51 X(DynamicExceptionSpec) \
52 X(FunctionEncoding) \
53 X(LiteralOperator) \
54 X(SpecialName) \
55 X(CtorVtableSpecialName) \
56 X(QualifiedName) \
57 X(NestedName) \
58 X(LocalName) \
59 X(VectorType) \
60 X(PixelVectorType) \
61 X(ParameterPack) \
62 X(TemplateArgumentPack) \
63 X(ParameterPackExpansion) \
64 X(TemplateArgs) \
65 X(ForwardTemplateReference) \
66 X(NameWithTemplateArgs) \
67 X(GlobalQualifiedName) \
68 X(StdQualifiedName) \
69 X(ExpandedSpecialSubstitution) \
70 X(SpecialSubstitution) \
71 X(CtorDtorName) \
72 X(DtorName) \
73 X(UnnamedTypeName) \
74 X(ClosureTypeName) \
75 X(StructuredBindingName) \
76 X(BinaryExpr) \
77 X(ArraySubscriptExpr) \
78 X(PostfixExpr) \
79 X(ConditionalExpr) \
80 X(MemberExpr) \
81 X(EnclosingExpr) \
82 X(CastExpr) \
83 X(SizeofParamPackExpr) \
84 X(CallExpr) \
85 X(NewExpr) \
86 X(DeleteExpr) \
87 X(PrefixExpr) \
88 X(FunctionParam) \
89 X(ConversionExpr) \
90 X(InitListExpr) \
91 X(FoldExpr) \
92 X(ThrowExpr) \
93 X(BoolExpr) \
94 X(IntegerCastExpr) \
95 X(IntegerLiteral) \
96 X(FloatLiteral) \
97 X(DoubleLiteral) \
98 X(LongDoubleLiteral) \
99 X(BracedExpr) \
100 X(BracedRangeExpr)
101
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000102DEMANGLE_NAMESPACE_BEGIN
103
Richard Smithc20d1442018-08-20 20:14:49 +0000104// Base class of all AST nodes. The AST is built by the parser, then is
105// traversed by the printLeft/Right functions to produce a demangled string.
106class Node {
107public:
108 enum Kind : unsigned char {
109#define ENUMERATOR(NodeKind) K ## NodeKind,
110 FOR_EACH_NODE_KIND(ENUMERATOR)
111#undef ENUMERATOR
112 };
113
114 /// Three-way bool to track a cached value. Unknown is possible if this node
115 /// has an unexpanded parameter pack below it that may affect this cache.
116 enum class Cache : unsigned char { Yes, No, Unknown, };
117
118private:
119 Kind K;
120
121 // FIXME: Make these protected.
122public:
123 /// Tracks if this node has a component on its right side, in which case we
124 /// need to call printRight.
125 Cache RHSComponentCache;
126
127 /// Track if this node is a (possibly qualified) array type. This can affect
128 /// how we format the output string.
129 Cache ArrayCache;
130
131 /// Track if this node is a (possibly qualified) function type. This can
132 /// affect how we format the output string.
133 Cache FunctionCache;
134
135public:
136 Node(Kind K_, Cache RHSComponentCache_ = Cache::No,
137 Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No)
138 : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),
139 FunctionCache(FunctionCache_) {}
140
141 /// Visit the most-derived object corresponding to this object.
142 template<typename Fn> void visit(Fn F) const;
143
144 // The following function is provided by all derived classes:
145 //
146 // Call F with arguments that, when passed to the constructor of this node,
147 // would construct an equivalent node.
148 //template<typename Fn> void match(Fn F) const;
149
150 bool hasRHSComponent(OutputStream &S) const {
151 if (RHSComponentCache != Cache::Unknown)
152 return RHSComponentCache == Cache::Yes;
153 return hasRHSComponentSlow(S);
154 }
155
156 bool hasArray(OutputStream &S) const {
157 if (ArrayCache != Cache::Unknown)
158 return ArrayCache == Cache::Yes;
159 return hasArraySlow(S);
160 }
161
162 bool hasFunction(OutputStream &S) const {
163 if (FunctionCache != Cache::Unknown)
164 return FunctionCache == Cache::Yes;
165 return hasFunctionSlow(S);
166 }
167
168 Kind getKind() const { return K; }
169
170 virtual bool hasRHSComponentSlow(OutputStream &) const { return false; }
171 virtual bool hasArraySlow(OutputStream &) const { return false; }
172 virtual bool hasFunctionSlow(OutputStream &) const { return false; }
173
174 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
175 // get at a node that actually represents some concrete syntax.
176 virtual const Node *getSyntaxNode(OutputStream &) const {
177 return this;
178 }
179
180 void print(OutputStream &S) const {
181 printLeft(S);
182 if (RHSComponentCache != Cache::No)
183 printRight(S);
184 }
185
186 // Print the "left" side of this Node into OutputStream.
187 virtual void printLeft(OutputStream &) const = 0;
188
189 // Print the "right". This distinction is necessary to represent C++ types
190 // that appear on the RHS of their subtype, such as arrays or functions.
191 // Since most types don't have such a component, provide a default
192 // implementation.
193 virtual void printRight(OutputStream &) const {}
194
195 virtual StringView getBaseName() const { return StringView(); }
196
197 // Silence compiler warnings, this dtor will never be called.
198 virtual ~Node() = default;
199
200#ifndef NDEBUG
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000201 DEMANGLE_DUMP_METHOD void dump() const;
Richard Smithc20d1442018-08-20 20:14:49 +0000202#endif
203};
204
205class NodeArray {
206 Node **Elements;
207 size_t NumElements;
208
209public:
210 NodeArray() : Elements(nullptr), NumElements(0) {}
211 NodeArray(Node **Elements_, size_t NumElements_)
212 : Elements(Elements_), NumElements(NumElements_) {}
213
214 bool empty() const { return NumElements == 0; }
215 size_t size() const { return NumElements; }
216
217 Node **begin() const { return Elements; }
218 Node **end() const { return Elements + NumElements; }
219
220 Node *operator[](size_t Idx) const { return Elements[Idx]; }
221
222 void printWithComma(OutputStream &S) const {
223 bool FirstElement = true;
224 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
225 size_t BeforeComma = S.getCurrentPosition();
226 if (!FirstElement)
227 S += ", ";
228 size_t AfterComma = S.getCurrentPosition();
229 Elements[Idx]->print(S);
230
231 // Elements[Idx] is an empty parameter pack expansion, we should erase the
232 // comma we just printed.
233 if (AfterComma == S.getCurrentPosition()) {
234 S.setCurrentPosition(BeforeComma);
235 continue;
236 }
237
238 FirstElement = false;
239 }
240 }
241};
242
243struct NodeArrayNode : Node {
244 NodeArray Array;
245 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
246
247 template<typename Fn> void match(Fn F) const { F(Array); }
248
249 void printLeft(OutputStream &S) const override {
250 Array.printWithComma(S);
251 }
252};
253
254class DotSuffix final : public Node {
255 const Node *Prefix;
256 const StringView Suffix;
257
258public:
259 DotSuffix(const Node *Prefix_, StringView Suffix_)
260 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
261
262 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
263
264 void printLeft(OutputStream &s) const override {
265 Prefix->print(s);
266 s += " (";
267 s += Suffix;
268 s += ")";
269 }
270};
271
272class VendorExtQualType final : public Node {
273 const Node *Ty;
274 StringView Ext;
275
276public:
277 VendorExtQualType(const Node *Ty_, StringView Ext_)
278 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {}
279
280 template<typename Fn> void match(Fn F) const { F(Ty, Ext); }
281
282 void printLeft(OutputStream &S) const override {
283 Ty->print(S);
284 S += " ";
285 S += Ext;
286 }
287};
288
289enum FunctionRefQual : unsigned char {
290 FrefQualNone,
291 FrefQualLValue,
292 FrefQualRValue,
293};
294
295enum Qualifiers {
296 QualNone = 0,
297 QualConst = 0x1,
298 QualVolatile = 0x2,
299 QualRestrict = 0x4,
300};
301
302inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
303 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
304}
305
306class QualType : public Node {
307protected:
308 const Qualifiers Quals;
309 const Node *Child;
310
311 void printQuals(OutputStream &S) const {
312 if (Quals & QualConst)
313 S += " const";
314 if (Quals & QualVolatile)
315 S += " volatile";
316 if (Quals & QualRestrict)
317 S += " restrict";
318 }
319
320public:
321 QualType(const Node *Child_, Qualifiers Quals_)
322 : Node(KQualType, Child_->RHSComponentCache,
323 Child_->ArrayCache, Child_->FunctionCache),
324 Quals(Quals_), Child(Child_) {}
325
326 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
327
328 bool hasRHSComponentSlow(OutputStream &S) const override {
329 return Child->hasRHSComponent(S);
330 }
331 bool hasArraySlow(OutputStream &S) const override {
332 return Child->hasArray(S);
333 }
334 bool hasFunctionSlow(OutputStream &S) const override {
335 return Child->hasFunction(S);
336 }
337
338 void printLeft(OutputStream &S) const override {
339 Child->printLeft(S);
340 printQuals(S);
341 }
342
343 void printRight(OutputStream &S) const override { Child->printRight(S); }
344};
345
346class ConversionOperatorType final : public Node {
347 const Node *Ty;
348
349public:
350 ConversionOperatorType(const Node *Ty_)
351 : Node(KConversionOperatorType), Ty(Ty_) {}
352
353 template<typename Fn> void match(Fn F) const { F(Ty); }
354
355 void printLeft(OutputStream &S) const override {
356 S += "operator ";
357 Ty->print(S);
358 }
359};
360
361class PostfixQualifiedType final : public Node {
362 const Node *Ty;
363 const StringView Postfix;
364
365public:
366 PostfixQualifiedType(Node *Ty_, StringView Postfix_)
367 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
368
369 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
370
371 void printLeft(OutputStream &s) const override {
372 Ty->printLeft(s);
373 s += Postfix;
374 }
375};
376
377class NameType final : public Node {
378 const StringView Name;
379
380public:
381 NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
382
383 template<typename Fn> void match(Fn F) const { F(Name); }
384
385 StringView getName() const { return Name; }
386 StringView getBaseName() const override { return Name; }
387
388 void printLeft(OutputStream &s) const override { s += Name; }
389};
390
391class ElaboratedTypeSpefType : public Node {
392 StringView Kind;
393 Node *Child;
394public:
395 ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
396 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
397
398 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
399
400 void printLeft(OutputStream &S) const override {
401 S += Kind;
402 S += ' ';
403 Child->print(S);
404 }
405};
406
407struct AbiTagAttr : Node {
408 Node *Base;
409 StringView Tag;
410
411 AbiTagAttr(Node* Base_, StringView Tag_)
412 : Node(KAbiTagAttr, Base_->RHSComponentCache,
413 Base_->ArrayCache, Base_->FunctionCache),
414 Base(Base_), Tag(Tag_) {}
415
416 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
417
418 void printLeft(OutputStream &S) const override {
419 Base->printLeft(S);
420 S += "[abi:";
421 S += Tag;
422 S += "]";
423 }
424};
425
426class EnableIfAttr : public Node {
427 NodeArray Conditions;
428public:
429 EnableIfAttr(NodeArray Conditions_)
430 : Node(KEnableIfAttr), Conditions(Conditions_) {}
431
432 template<typename Fn> void match(Fn F) const { F(Conditions); }
433
434 void printLeft(OutputStream &S) const override {
435 S += " [enable_if:";
436 Conditions.printWithComma(S);
437 S += ']';
438 }
439};
440
441class ObjCProtoName : public Node {
442 const Node *Ty;
443 StringView Protocol;
444
445 friend class PointerType;
446
447public:
448 ObjCProtoName(const Node *Ty_, StringView Protocol_)
449 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
450
451 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
452
453 bool isObjCObject() const {
454 return Ty->getKind() == KNameType &&
455 static_cast<const NameType *>(Ty)->getName() == "objc_object";
456 }
457
458 void printLeft(OutputStream &S) const override {
459 Ty->print(S);
460 S += "<";
461 S += Protocol;
462 S += ">";
463 }
464};
465
466class PointerType final : public Node {
467 const Node *Pointee;
468
469public:
470 PointerType(const Node *Pointee_)
471 : Node(KPointerType, Pointee_->RHSComponentCache),
472 Pointee(Pointee_) {}
473
474 template<typename Fn> void match(Fn F) const { F(Pointee); }
475
476 bool hasRHSComponentSlow(OutputStream &S) const override {
477 return Pointee->hasRHSComponent(S);
478 }
479
480 void printLeft(OutputStream &s) const override {
481 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
482 if (Pointee->getKind() != KObjCProtoName ||
483 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
484 Pointee->printLeft(s);
485 if (Pointee->hasArray(s))
486 s += " ";
487 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
488 s += "(";
489 s += "*";
490 } else {
491 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
492 s += "id<";
493 s += objcProto->Protocol;
494 s += ">";
495 }
496 }
497
498 void printRight(OutputStream &s) const override {
499 if (Pointee->getKind() != KObjCProtoName ||
500 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
501 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
502 s += ")";
503 Pointee->printRight(s);
504 }
505 }
506};
507
508enum class ReferenceKind {
509 LValue,
510 RValue,
511};
512
513// Represents either a LValue or an RValue reference type.
514class ReferenceType : public Node {
515 const Node *Pointee;
516 ReferenceKind RK;
517
518 mutable bool Printing = false;
519
520 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
521 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
522 // other combination collapses to a lvalue ref.
523 std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const {
524 auto SoFar = std::make_pair(RK, Pointee);
525 for (;;) {
526 const Node *SN = SoFar.second->getSyntaxNode(S);
527 if (SN->getKind() != KReferenceType)
528 break;
529 auto *RT = static_cast<const ReferenceType *>(SN);
530 SoFar.second = RT->Pointee;
531 SoFar.first = std::min(SoFar.first, RT->RK);
532 }
533 return SoFar;
534 }
535
536public:
537 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
538 : Node(KReferenceType, Pointee_->RHSComponentCache),
539 Pointee(Pointee_), RK(RK_) {}
540
541 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
542
543 bool hasRHSComponentSlow(OutputStream &S) const override {
544 return Pointee->hasRHSComponent(S);
545 }
546
547 void printLeft(OutputStream &s) const override {
548 if (Printing)
549 return;
550 SwapAndRestore<bool> SavePrinting(Printing, true);
551 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
552 Collapsed.second->printLeft(s);
553 if (Collapsed.second->hasArray(s))
554 s += " ";
555 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
556 s += "(";
557
558 s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
559 }
560 void printRight(OutputStream &s) const override {
561 if (Printing)
562 return;
563 SwapAndRestore<bool> SavePrinting(Printing, true);
564 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
565 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
566 s += ")";
567 Collapsed.second->printRight(s);
568 }
569};
570
571class PointerToMemberType final : public Node {
572 const Node *ClassType;
573 const Node *MemberType;
574
575public:
576 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
577 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
578 ClassType(ClassType_), MemberType(MemberType_) {}
579
580 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
581
582 bool hasRHSComponentSlow(OutputStream &S) const override {
583 return MemberType->hasRHSComponent(S);
584 }
585
586 void printLeft(OutputStream &s) const override {
587 MemberType->printLeft(s);
588 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
589 s += "(";
590 else
591 s += " ";
592 ClassType->print(s);
593 s += "::*";
594 }
595
596 void printRight(OutputStream &s) const override {
597 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
598 s += ")";
599 MemberType->printRight(s);
600 }
601};
602
603class NodeOrString {
604 const void *First;
605 const void *Second;
606
607public:
608 /* implicit */ NodeOrString(StringView Str) {
609 const char *FirstChar = Str.begin();
610 const char *SecondChar = Str.end();
611 if (SecondChar == nullptr) {
612 assert(FirstChar == SecondChar);
613 ++FirstChar, ++SecondChar;
614 }
615 First = static_cast<const void *>(FirstChar);
616 Second = static_cast<const void *>(SecondChar);
617 }
618
619 /* implicit */ NodeOrString(Node *N)
620 : First(static_cast<const void *>(N)), Second(nullptr) {}
621 NodeOrString() : First(nullptr), Second(nullptr) {}
622
623 bool isString() const { return Second && First; }
624 bool isNode() const { return First && !Second; }
625 bool isEmpty() const { return !First && !Second; }
626
627 StringView asString() const {
628 assert(isString());
629 return StringView(static_cast<const char *>(First),
630 static_cast<const char *>(Second));
631 }
632
633 const Node *asNode() const {
634 assert(isNode());
635 return static_cast<const Node *>(First);
636 }
637};
638
639class ArrayType final : public Node {
640 const Node *Base;
641 NodeOrString Dimension;
642
643public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +0000644 ArrayType(const Node *Base_, NodeOrString Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000645 : Node(KArrayType,
646 /*RHSComponentCache=*/Cache::Yes,
647 /*ArrayCache=*/Cache::Yes),
648 Base(Base_), Dimension(Dimension_) {}
649
650 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
651
652 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
653 bool hasArraySlow(OutputStream &) const override { return true; }
654
655 void printLeft(OutputStream &S) const override { Base->printLeft(S); }
656
657 void printRight(OutputStream &S) const override {
658 if (S.back() != ']')
659 S += " ";
660 S += "[";
661 if (Dimension.isString())
662 S += Dimension.asString();
663 else if (Dimension.isNode())
664 Dimension.asNode()->print(S);
665 S += "]";
666 Base->printRight(S);
667 }
668};
669
670class FunctionType final : public Node {
671 const Node *Ret;
672 NodeArray Params;
673 Qualifiers CVQuals;
674 FunctionRefQual RefQual;
675 const Node *ExceptionSpec;
676
677public:
678 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
679 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
680 : Node(KFunctionType,
681 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
682 /*FunctionCache=*/Cache::Yes),
683 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
684 ExceptionSpec(ExceptionSpec_) {}
685
686 template<typename Fn> void match(Fn F) const {
687 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
688 }
689
690 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
691 bool hasFunctionSlow(OutputStream &) const override { return true; }
692
693 // Handle C++'s ... quirky decl grammar by using the left & right
694 // distinction. Consider:
695 // int (*f(float))(char) {}
696 // f is a function that takes a float and returns a pointer to a function
697 // that takes a char and returns an int. If we're trying to print f, start
698 // by printing out the return types's left, then print our parameters, then
699 // finally print right of the return type.
700 void printLeft(OutputStream &S) const override {
701 Ret->printLeft(S);
702 S += " ";
703 }
704
705 void printRight(OutputStream &S) const override {
706 S += "(";
707 Params.printWithComma(S);
708 S += ")";
709 Ret->printRight(S);
710
711 if (CVQuals & QualConst)
712 S += " const";
713 if (CVQuals & QualVolatile)
714 S += " volatile";
715 if (CVQuals & QualRestrict)
716 S += " restrict";
717
718 if (RefQual == FrefQualLValue)
719 S += " &";
720 else if (RefQual == FrefQualRValue)
721 S += " &&";
722
723 if (ExceptionSpec != nullptr) {
724 S += ' ';
725 ExceptionSpec->print(S);
726 }
727 }
728};
729
730class NoexceptSpec : public Node {
731 const Node *E;
732public:
733 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
734
735 template<typename Fn> void match(Fn F) const { F(E); }
736
737 void printLeft(OutputStream &S) const override {
738 S += "noexcept(";
739 E->print(S);
740 S += ")";
741 }
742};
743
744class DynamicExceptionSpec : public Node {
745 NodeArray Types;
746public:
747 DynamicExceptionSpec(NodeArray Types_)
748 : Node(KDynamicExceptionSpec), Types(Types_) {}
749
750 template<typename Fn> void match(Fn F) const { F(Types); }
751
752 void printLeft(OutputStream &S) const override {
753 S += "throw(";
754 Types.printWithComma(S);
755 S += ')';
756 }
757};
758
759class FunctionEncoding final : public Node {
760 const Node *Ret;
761 const Node *Name;
762 NodeArray Params;
763 const Node *Attrs;
764 Qualifiers CVQuals;
765 FunctionRefQual RefQual;
766
767public:
768 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
769 const Node *Attrs_, Qualifiers CVQuals_,
770 FunctionRefQual RefQual_)
771 : Node(KFunctionEncoding,
772 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
773 /*FunctionCache=*/Cache::Yes),
774 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
775 CVQuals(CVQuals_), RefQual(RefQual_) {}
776
777 template<typename Fn> void match(Fn F) const {
778 F(Ret, Name, Params, Attrs, CVQuals, RefQual);
779 }
780
781 Qualifiers getCVQuals() const { return CVQuals; }
782 FunctionRefQual getRefQual() const { return RefQual; }
783 NodeArray getParams() const { return Params; }
784 const Node *getReturnType() const { return Ret; }
785
786 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
787 bool hasFunctionSlow(OutputStream &) const override { return true; }
788
789 const Node *getName() const { return Name; }
790
791 void printLeft(OutputStream &S) const override {
792 if (Ret) {
793 Ret->printLeft(S);
794 if (!Ret->hasRHSComponent(S))
795 S += " ";
796 }
797 Name->print(S);
798 }
799
800 void printRight(OutputStream &S) const override {
801 S += "(";
802 Params.printWithComma(S);
803 S += ")";
804 if (Ret)
805 Ret->printRight(S);
806
807 if (CVQuals & QualConst)
808 S += " const";
809 if (CVQuals & QualVolatile)
810 S += " volatile";
811 if (CVQuals & QualRestrict)
812 S += " restrict";
813
814 if (RefQual == FrefQualLValue)
815 S += " &";
816 else if (RefQual == FrefQualRValue)
817 S += " &&";
818
819 if (Attrs != nullptr)
820 Attrs->print(S);
821 }
822};
823
824class LiteralOperator : public Node {
825 const Node *OpName;
826
827public:
828 LiteralOperator(const Node *OpName_)
829 : Node(KLiteralOperator), OpName(OpName_) {}
830
831 template<typename Fn> void match(Fn F) const { F(OpName); }
832
833 void printLeft(OutputStream &S) const override {
834 S += "operator\"\" ";
835 OpName->print(S);
836 }
837};
838
839class SpecialName final : public Node {
840 const StringView Special;
841 const Node *Child;
842
843public:
844 SpecialName(StringView Special_, const Node *Child_)
845 : Node(KSpecialName), Special(Special_), Child(Child_) {}
846
847 template<typename Fn> void match(Fn F) const { F(Special, Child); }
848
849 void printLeft(OutputStream &S) const override {
850 S += Special;
851 Child->print(S);
852 }
853};
854
855class CtorVtableSpecialName final : public Node {
856 const Node *FirstType;
857 const Node *SecondType;
858
859public:
860 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
861 : Node(KCtorVtableSpecialName),
862 FirstType(FirstType_), SecondType(SecondType_) {}
863
864 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
865
866 void printLeft(OutputStream &S) const override {
867 S += "construction vtable for ";
868 FirstType->print(S);
869 S += "-in-";
870 SecondType->print(S);
871 }
872};
873
874struct NestedName : Node {
875 Node *Qual;
876 Node *Name;
877
878 NestedName(Node *Qual_, Node *Name_)
879 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
880
881 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
882
883 StringView getBaseName() const override { return Name->getBaseName(); }
884
885 void printLeft(OutputStream &S) const override {
886 Qual->print(S);
887 S += "::";
888 Name->print(S);
889 }
890};
891
892struct LocalName : Node {
893 Node *Encoding;
894 Node *Entity;
895
896 LocalName(Node *Encoding_, Node *Entity_)
897 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
898
899 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
900
901 void printLeft(OutputStream &S) const override {
902 Encoding->print(S);
903 S += "::";
904 Entity->print(S);
905 }
906};
907
908class QualifiedName final : public Node {
909 // qualifier::name
910 const Node *Qualifier;
911 const Node *Name;
912
913public:
914 QualifiedName(const Node *Qualifier_, const Node *Name_)
915 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
916
917 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
918
919 StringView getBaseName() const override { return Name->getBaseName(); }
920
921 void printLeft(OutputStream &S) const override {
922 Qualifier->print(S);
923 S += "::";
924 Name->print(S);
925 }
926};
927
928class VectorType final : public Node {
929 const Node *BaseType;
930 const NodeOrString Dimension;
931
932public:
933 VectorType(const Node *BaseType_, NodeOrString Dimension_)
934 : Node(KVectorType), BaseType(BaseType_),
935 Dimension(Dimension_) {}
936
937 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
938
939 void printLeft(OutputStream &S) const override {
940 BaseType->print(S);
941 S += " vector[";
942 if (Dimension.isNode())
943 Dimension.asNode()->print(S);
944 else if (Dimension.isString())
945 S += Dimension.asString();
946 S += "]";
947 }
948};
949
950class PixelVectorType final : public Node {
951 const NodeOrString Dimension;
952
953public:
954 PixelVectorType(NodeOrString Dimension_)
955 : Node(KPixelVectorType), Dimension(Dimension_) {}
956
957 template<typename Fn> void match(Fn F) const { F(Dimension); }
958
959 void printLeft(OutputStream &S) const override {
960 // FIXME: This should demangle as "vector pixel".
961 S += "pixel vector[";
962 S += Dimension.asString();
963 S += "]";
964 }
965};
966
967/// An unexpanded parameter pack (either in the expression or type context). If
968/// this AST is correct, this node will have a ParameterPackExpansion node above
969/// it.
970///
971/// This node is created when some <template-args> are found that apply to an
972/// <encoding>, and is stored in the TemplateParams table. In order for this to
973/// appear in the final AST, it has to referenced via a <template-param> (ie,
974/// T_).
975class ParameterPack final : public Node {
976 NodeArray Data;
977
978 // Setup OutputStream for a pack expansion unless we're already expanding one.
979 void initializePackExpansion(OutputStream &S) const {
980 if (S.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
981 S.CurrentPackMax = static_cast<unsigned>(Data.size());
982 S.CurrentPackIndex = 0;
983 }
984 }
985
986public:
987 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
988 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
989 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
990 return P->ArrayCache == Cache::No;
991 }))
992 ArrayCache = Cache::No;
993 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
994 return P->FunctionCache == Cache::No;
995 }))
996 FunctionCache = Cache::No;
997 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
998 return P->RHSComponentCache == Cache::No;
999 }))
1000 RHSComponentCache = Cache::No;
1001 }
1002
1003 template<typename Fn> void match(Fn F) const { F(Data); }
1004
1005 bool hasRHSComponentSlow(OutputStream &S) const override {
1006 initializePackExpansion(S);
1007 size_t Idx = S.CurrentPackIndex;
1008 return Idx < Data.size() && Data[Idx]->hasRHSComponent(S);
1009 }
1010 bool hasArraySlow(OutputStream &S) const override {
1011 initializePackExpansion(S);
1012 size_t Idx = S.CurrentPackIndex;
1013 return Idx < Data.size() && Data[Idx]->hasArray(S);
1014 }
1015 bool hasFunctionSlow(OutputStream &S) const override {
1016 initializePackExpansion(S);
1017 size_t Idx = S.CurrentPackIndex;
1018 return Idx < Data.size() && Data[Idx]->hasFunction(S);
1019 }
1020 const Node *getSyntaxNode(OutputStream &S) const override {
1021 initializePackExpansion(S);
1022 size_t Idx = S.CurrentPackIndex;
1023 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this;
1024 }
1025
1026 void printLeft(OutputStream &S) const override {
1027 initializePackExpansion(S);
1028 size_t Idx = S.CurrentPackIndex;
1029 if (Idx < Data.size())
1030 Data[Idx]->printLeft(S);
1031 }
1032 void printRight(OutputStream &S) const override {
1033 initializePackExpansion(S);
1034 size_t Idx = S.CurrentPackIndex;
1035 if (Idx < Data.size())
1036 Data[Idx]->printRight(S);
1037 }
1038};
1039
1040/// A variadic template argument. This node represents an occurrence of
1041/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1042/// one of it's Elements is. The parser inserts a ParameterPack into the
1043/// TemplateParams table if the <template-args> this pack belongs to apply to an
1044/// <encoding>.
1045class TemplateArgumentPack final : public Node {
1046 NodeArray Elements;
1047public:
1048 TemplateArgumentPack(NodeArray Elements_)
1049 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1050
1051 template<typename Fn> void match(Fn F) const { F(Elements); }
1052
1053 NodeArray getElements() const { return Elements; }
1054
1055 void printLeft(OutputStream &S) const override {
1056 Elements.printWithComma(S);
1057 }
1058};
1059
1060/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1061/// which each have Child->ParameterPackSize elements.
1062class ParameterPackExpansion final : public Node {
1063 const Node *Child;
1064
1065public:
1066 ParameterPackExpansion(const Node *Child_)
1067 : Node(KParameterPackExpansion), Child(Child_) {}
1068
1069 template<typename Fn> void match(Fn F) const { F(Child); }
1070
1071 const Node *getChild() const { return Child; }
1072
1073 void printLeft(OutputStream &S) const override {
1074 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
1075 SwapAndRestore<unsigned> SavePackIdx(S.CurrentPackIndex, Max);
1076 SwapAndRestore<unsigned> SavePackMax(S.CurrentPackMax, Max);
1077 size_t StreamPos = S.getCurrentPosition();
1078
1079 // Print the first element in the pack. If Child contains a ParameterPack,
1080 // it will set up S.CurrentPackMax and print the first element.
1081 Child->print(S);
1082
1083 // No ParameterPack was found in Child. This can occur if we've found a pack
1084 // expansion on a <function-param>.
1085 if (S.CurrentPackMax == Max) {
1086 S += "...";
1087 return;
1088 }
1089
1090 // We found a ParameterPack, but it has no elements. Erase whatever we may
1091 // of printed.
1092 if (S.CurrentPackMax == 0) {
1093 S.setCurrentPosition(StreamPos);
1094 return;
1095 }
1096
1097 // Else, iterate through the rest of the elements in the pack.
1098 for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) {
1099 S += ", ";
1100 S.CurrentPackIndex = I;
1101 Child->print(S);
1102 }
1103 }
1104};
1105
1106class TemplateArgs final : public Node {
1107 NodeArray Params;
1108
1109public:
1110 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1111
1112 template<typename Fn> void match(Fn F) const { F(Params); }
1113
1114 NodeArray getParams() { return Params; }
1115
1116 void printLeft(OutputStream &S) const override {
1117 S += "<";
1118 Params.printWithComma(S);
1119 if (S.back() == '>')
1120 S += " ";
1121 S += ">";
1122 }
1123};
1124
Richard Smithb485b352018-08-24 23:30:26 +00001125/// A forward-reference to a template argument that was not known at the point
1126/// where the template parameter name was parsed in a mangling.
1127///
1128/// This is created when demangling the name of a specialization of a
1129/// conversion function template:
1130///
1131/// \code
1132/// struct A {
1133/// template<typename T> operator T*();
1134/// };
1135/// \endcode
1136///
1137/// When demangling a specialization of the conversion function template, we
1138/// encounter the name of the template (including the \c T) before we reach
1139/// the template argument list, so we cannot substitute the parameter name
1140/// for the corresponding argument while parsing. Instead, we create a
1141/// \c ForwardTemplateReference node that is resolved after we parse the
1142/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001143struct ForwardTemplateReference : Node {
1144 size_t Index;
1145 Node *Ref = nullptr;
1146
1147 // If we're currently printing this node. It is possible (though invalid) for
1148 // a forward template reference to refer to itself via a substitution. This
1149 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1150 // out if more than one print* function is active.
1151 mutable bool Printing = false;
1152
1153 ForwardTemplateReference(size_t Index_)
1154 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1155 Cache::Unknown),
1156 Index(Index_) {}
1157
1158 // We don't provide a matcher for these, because the value of the node is
1159 // not determined by its construction parameters, and it generally needs
1160 // special handling.
1161 template<typename Fn> void match(Fn F) const = delete;
1162
1163 bool hasRHSComponentSlow(OutputStream &S) const override {
1164 if (Printing)
1165 return false;
1166 SwapAndRestore<bool> SavePrinting(Printing, true);
1167 return Ref->hasRHSComponent(S);
1168 }
1169 bool hasArraySlow(OutputStream &S) const override {
1170 if (Printing)
1171 return false;
1172 SwapAndRestore<bool> SavePrinting(Printing, true);
1173 return Ref->hasArray(S);
1174 }
1175 bool hasFunctionSlow(OutputStream &S) const override {
1176 if (Printing)
1177 return false;
1178 SwapAndRestore<bool> SavePrinting(Printing, true);
1179 return Ref->hasFunction(S);
1180 }
1181 const Node *getSyntaxNode(OutputStream &S) const override {
1182 if (Printing)
1183 return this;
1184 SwapAndRestore<bool> SavePrinting(Printing, true);
1185 return Ref->getSyntaxNode(S);
1186 }
1187
1188 void printLeft(OutputStream &S) const override {
1189 if (Printing)
1190 return;
1191 SwapAndRestore<bool> SavePrinting(Printing, true);
1192 Ref->printLeft(S);
1193 }
1194 void printRight(OutputStream &S) const override {
1195 if (Printing)
1196 return;
1197 SwapAndRestore<bool> SavePrinting(Printing, true);
1198 Ref->printRight(S);
1199 }
1200};
1201
1202struct NameWithTemplateArgs : Node {
1203 // name<template_args>
1204 Node *Name;
1205 Node *TemplateArgs;
1206
1207 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1208 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1209
1210 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1211
1212 StringView getBaseName() const override { return Name->getBaseName(); }
1213
1214 void printLeft(OutputStream &S) const override {
1215 Name->print(S);
1216 TemplateArgs->print(S);
1217 }
1218};
1219
1220class GlobalQualifiedName final : public Node {
1221 Node *Child;
1222
1223public:
1224 GlobalQualifiedName(Node* Child_)
1225 : Node(KGlobalQualifiedName), Child(Child_) {}
1226
1227 template<typename Fn> void match(Fn F) const { F(Child); }
1228
1229 StringView getBaseName() const override { return Child->getBaseName(); }
1230
1231 void printLeft(OutputStream &S) const override {
1232 S += "::";
1233 Child->print(S);
1234 }
1235};
1236
1237struct StdQualifiedName : Node {
1238 Node *Child;
1239
1240 StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {}
1241
1242 template<typename Fn> void match(Fn F) const { F(Child); }
1243
1244 StringView getBaseName() const override { return Child->getBaseName(); }
1245
1246 void printLeft(OutputStream &S) const override {
1247 S += "std::";
1248 Child->print(S);
1249 }
1250};
1251
1252enum class SpecialSubKind {
1253 allocator,
1254 basic_string,
1255 string,
1256 istream,
1257 ostream,
1258 iostream,
1259};
1260
1261class ExpandedSpecialSubstitution final : public Node {
1262 SpecialSubKind SSK;
1263
1264public:
1265 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1266 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1267
1268 template<typename Fn> void match(Fn F) const { F(SSK); }
1269
1270 StringView getBaseName() const override {
1271 switch (SSK) {
1272 case SpecialSubKind::allocator:
1273 return StringView("allocator");
1274 case SpecialSubKind::basic_string:
1275 return StringView("basic_string");
1276 case SpecialSubKind::string:
1277 return StringView("basic_string");
1278 case SpecialSubKind::istream:
1279 return StringView("basic_istream");
1280 case SpecialSubKind::ostream:
1281 return StringView("basic_ostream");
1282 case SpecialSubKind::iostream:
1283 return StringView("basic_iostream");
1284 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001285 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001286 }
1287
1288 void printLeft(OutputStream &S) const override {
1289 switch (SSK) {
1290 case SpecialSubKind::allocator:
Richard Smithb485b352018-08-24 23:30:26 +00001291 S += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001292 break;
1293 case SpecialSubKind::basic_string:
Richard Smithb485b352018-08-24 23:30:26 +00001294 S += "std::basic_string";
1295 break;
Richard Smithc20d1442018-08-20 20:14:49 +00001296 case SpecialSubKind::string:
1297 S += "std::basic_string<char, std::char_traits<char>, "
1298 "std::allocator<char> >";
1299 break;
1300 case SpecialSubKind::istream:
1301 S += "std::basic_istream<char, std::char_traits<char> >";
1302 break;
1303 case SpecialSubKind::ostream:
1304 S += "std::basic_ostream<char, std::char_traits<char> >";
1305 break;
1306 case SpecialSubKind::iostream:
1307 S += "std::basic_iostream<char, std::char_traits<char> >";
1308 break;
1309 }
1310 }
1311};
1312
1313class SpecialSubstitution final : public Node {
1314public:
1315 SpecialSubKind SSK;
1316
1317 SpecialSubstitution(SpecialSubKind SSK_)
1318 : Node(KSpecialSubstitution), SSK(SSK_) {}
1319
1320 template<typename Fn> void match(Fn F) const { F(SSK); }
1321
1322 StringView getBaseName() const override {
1323 switch (SSK) {
1324 case SpecialSubKind::allocator:
1325 return StringView("allocator");
1326 case SpecialSubKind::basic_string:
1327 return StringView("basic_string");
1328 case SpecialSubKind::string:
1329 return StringView("string");
1330 case SpecialSubKind::istream:
1331 return StringView("istream");
1332 case SpecialSubKind::ostream:
1333 return StringView("ostream");
1334 case SpecialSubKind::iostream:
1335 return StringView("iostream");
1336 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001337 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001338 }
1339
1340 void printLeft(OutputStream &S) const override {
1341 switch (SSK) {
1342 case SpecialSubKind::allocator:
1343 S += "std::allocator";
1344 break;
1345 case SpecialSubKind::basic_string:
1346 S += "std::basic_string";
1347 break;
1348 case SpecialSubKind::string:
1349 S += "std::string";
1350 break;
1351 case SpecialSubKind::istream:
1352 S += "std::istream";
1353 break;
1354 case SpecialSubKind::ostream:
1355 S += "std::ostream";
1356 break;
1357 case SpecialSubKind::iostream:
1358 S += "std::iostream";
1359 break;
1360 }
1361 }
1362};
1363
1364class CtorDtorName final : public Node {
1365 const Node *Basename;
1366 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001367 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001368
1369public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001370 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1371 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1372 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001373
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001374 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001375
1376 void printLeft(OutputStream &S) const override {
1377 if (IsDtor)
1378 S += "~";
1379 S += Basename->getBaseName();
1380 }
1381};
1382
1383class DtorName : public Node {
1384 const Node *Base;
1385
1386public:
1387 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1388
1389 template<typename Fn> void match(Fn F) const { F(Base); }
1390
1391 void printLeft(OutputStream &S) const override {
1392 S += "~";
1393 Base->printLeft(S);
1394 }
1395};
1396
1397class UnnamedTypeName : public Node {
1398 const StringView Count;
1399
1400public:
1401 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1402
1403 template<typename Fn> void match(Fn F) const { F(Count); }
1404
1405 void printLeft(OutputStream &S) const override {
1406 S += "'unnamed";
1407 S += Count;
1408 S += "\'";
1409 }
1410};
1411
1412class ClosureTypeName : public Node {
1413 NodeArray Params;
1414 StringView Count;
1415
1416public:
1417 ClosureTypeName(NodeArray Params_, StringView Count_)
1418 : Node(KClosureTypeName), Params(Params_), Count(Count_) {}
1419
1420 template<typename Fn> void match(Fn F) const { F(Params, Count); }
1421
1422 void printLeft(OutputStream &S) const override {
1423 S += "\'lambda";
1424 S += Count;
1425 S += "\'(";
1426 Params.printWithComma(S);
1427 S += ")";
1428 }
1429};
1430
1431class StructuredBindingName : public Node {
1432 NodeArray Bindings;
1433public:
1434 StructuredBindingName(NodeArray Bindings_)
1435 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1436
1437 template<typename Fn> void match(Fn F) const { F(Bindings); }
1438
1439 void printLeft(OutputStream &S) const override {
1440 S += '[';
1441 Bindings.printWithComma(S);
1442 S += ']';
1443 }
1444};
1445
1446// -- Expression Nodes --
1447
1448class BinaryExpr : public Node {
1449 const Node *LHS;
1450 const StringView InfixOperator;
1451 const Node *RHS;
1452
1453public:
1454 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_)
1455 : Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {
1456 }
1457
1458 template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }
1459
1460 void printLeft(OutputStream &S) const override {
1461 // might be a template argument expression, then we need to disambiguate
1462 // with parens.
1463 if (InfixOperator == ">")
1464 S += "(";
1465
1466 S += "(";
1467 LHS->print(S);
1468 S += ") ";
1469 S += InfixOperator;
1470 S += " (";
1471 RHS->print(S);
1472 S += ")";
1473
1474 if (InfixOperator == ">")
1475 S += ")";
1476 }
1477};
1478
1479class ArraySubscriptExpr : public Node {
1480 const Node *Op1;
1481 const Node *Op2;
1482
1483public:
1484 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_)
1485 : Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {}
1486
1487 template<typename Fn> void match(Fn F) const { F(Op1, Op2); }
1488
1489 void printLeft(OutputStream &S) const override {
1490 S += "(";
1491 Op1->print(S);
1492 S += ")[";
1493 Op2->print(S);
1494 S += "]";
1495 }
1496};
1497
1498class PostfixExpr : public Node {
1499 const Node *Child;
1500 const StringView Operator;
1501
1502public:
1503 PostfixExpr(const Node *Child_, StringView Operator_)
1504 : Node(KPostfixExpr), Child(Child_), Operator(Operator_) {}
1505
1506 template<typename Fn> void match(Fn F) const { F(Child, Operator); }
1507
1508 void printLeft(OutputStream &S) const override {
1509 S += "(";
1510 Child->print(S);
1511 S += ")";
1512 S += Operator;
1513 }
1514};
1515
1516class ConditionalExpr : public Node {
1517 const Node *Cond;
1518 const Node *Then;
1519 const Node *Else;
1520
1521public:
1522 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_)
1523 : Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {}
1524
1525 template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }
1526
1527 void printLeft(OutputStream &S) const override {
1528 S += "(";
1529 Cond->print(S);
1530 S += ") ? (";
1531 Then->print(S);
1532 S += ") : (";
1533 Else->print(S);
1534 S += ")";
1535 }
1536};
1537
1538class MemberExpr : public Node {
1539 const Node *LHS;
1540 const StringView Kind;
1541 const Node *RHS;
1542
1543public:
1544 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_)
1545 : Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
1546
1547 template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }
1548
1549 void printLeft(OutputStream &S) const override {
1550 LHS->print(S);
1551 S += Kind;
1552 RHS->print(S);
1553 }
1554};
1555
1556class EnclosingExpr : public Node {
1557 const StringView Prefix;
1558 const Node *Infix;
1559 const StringView Postfix;
1560
1561public:
1562 EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_)
1563 : Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_),
1564 Postfix(Postfix_) {}
1565
1566 template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); }
1567
1568 void printLeft(OutputStream &S) const override {
1569 S += Prefix;
1570 Infix->print(S);
1571 S += Postfix;
1572 }
1573};
1574
1575class CastExpr : public Node {
1576 // cast_kind<to>(from)
1577 const StringView CastKind;
1578 const Node *To;
1579 const Node *From;
1580
1581public:
1582 CastExpr(StringView CastKind_, const Node *To_, const Node *From_)
1583 : Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {}
1584
1585 template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }
1586
1587 void printLeft(OutputStream &S) const override {
1588 S += CastKind;
1589 S += "<";
1590 To->printLeft(S);
1591 S += ">(";
1592 From->printLeft(S);
1593 S += ")";
1594 }
1595};
1596
1597class SizeofParamPackExpr : public Node {
1598 const Node *Pack;
1599
1600public:
1601 SizeofParamPackExpr(const Node *Pack_)
1602 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1603
1604 template<typename Fn> void match(Fn F) const { F(Pack); }
1605
1606 void printLeft(OutputStream &S) const override {
1607 S += "sizeof...(";
1608 ParameterPackExpansion PPE(Pack);
1609 PPE.printLeft(S);
1610 S += ")";
1611 }
1612};
1613
1614class CallExpr : public Node {
1615 const Node *Callee;
1616 NodeArray Args;
1617
1618public:
1619 CallExpr(const Node *Callee_, NodeArray Args_)
1620 : Node(KCallExpr), Callee(Callee_), Args(Args_) {}
1621
1622 template<typename Fn> void match(Fn F) const { F(Callee, Args); }
1623
1624 void printLeft(OutputStream &S) const override {
1625 Callee->print(S);
1626 S += "(";
1627 Args.printWithComma(S);
1628 S += ")";
1629 }
1630};
1631
1632class NewExpr : public Node {
1633 // new (expr_list) type(init_list)
1634 NodeArray ExprList;
1635 Node *Type;
1636 NodeArray InitList;
1637 bool IsGlobal; // ::operator new ?
1638 bool IsArray; // new[] ?
1639public:
1640 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
1641 bool IsArray_)
1642 : Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_),
1643 IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1644
1645 template<typename Fn> void match(Fn F) const {
1646 F(ExprList, Type, InitList, IsGlobal, IsArray);
1647 }
1648
1649 void printLeft(OutputStream &S) const override {
1650 if (IsGlobal)
1651 S += "::operator ";
1652 S += "new";
1653 if (IsArray)
1654 S += "[]";
1655 S += ' ';
1656 if (!ExprList.empty()) {
1657 S += "(";
1658 ExprList.printWithComma(S);
1659 S += ")";
1660 }
1661 Type->print(S);
1662 if (!InitList.empty()) {
1663 S += "(";
1664 InitList.printWithComma(S);
1665 S += ")";
1666 }
1667
1668 }
1669};
1670
1671class DeleteExpr : public Node {
1672 Node *Op;
1673 bool IsGlobal;
1674 bool IsArray;
1675
1676public:
1677 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_)
1678 : Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1679
1680 template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }
1681
1682 void printLeft(OutputStream &S) const override {
1683 if (IsGlobal)
1684 S += "::";
1685 S += "delete";
1686 if (IsArray)
1687 S += "[] ";
1688 Op->print(S);
1689 }
1690};
1691
1692class PrefixExpr : public Node {
1693 StringView Prefix;
1694 Node *Child;
1695
1696public:
1697 PrefixExpr(StringView Prefix_, Node *Child_)
1698 : Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {}
1699
1700 template<typename Fn> void match(Fn F) const { F(Prefix, Child); }
1701
1702 void printLeft(OutputStream &S) const override {
1703 S += Prefix;
1704 S += "(";
1705 Child->print(S);
1706 S += ")";
1707 }
1708};
1709
1710class FunctionParam : public Node {
1711 StringView Number;
1712
1713public:
1714 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
1715
1716 template<typename Fn> void match(Fn F) const { F(Number); }
1717
1718 void printLeft(OutputStream &S) const override {
1719 S += "fp";
1720 S += Number;
1721 }
1722};
1723
1724class ConversionExpr : public Node {
1725 const Node *Type;
1726 NodeArray Expressions;
1727
1728public:
1729 ConversionExpr(const Node *Type_, NodeArray Expressions_)
1730 : Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {}
1731
1732 template<typename Fn> void match(Fn F) const { F(Type, Expressions); }
1733
1734 void printLeft(OutputStream &S) const override {
1735 S += "(";
1736 Type->print(S);
1737 S += ")(";
1738 Expressions.printWithComma(S);
1739 S += ")";
1740 }
1741};
1742
1743class InitListExpr : public Node {
1744 const Node *Ty;
1745 NodeArray Inits;
1746public:
1747 InitListExpr(const Node *Ty_, NodeArray Inits_)
1748 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
1749
1750 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
1751
1752 void printLeft(OutputStream &S) const override {
1753 if (Ty)
1754 Ty->print(S);
1755 S += '{';
1756 Inits.printWithComma(S);
1757 S += '}';
1758 }
1759};
1760
1761class BracedExpr : public Node {
1762 const Node *Elem;
1763 const Node *Init;
1764 bool IsArray;
1765public:
1766 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
1767 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
1768
1769 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
1770
1771 void printLeft(OutputStream &S) const override {
1772 if (IsArray) {
1773 S += '[';
1774 Elem->print(S);
1775 S += ']';
1776 } else {
1777 S += '.';
1778 Elem->print(S);
1779 }
1780 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1781 S += " = ";
1782 Init->print(S);
1783 }
1784};
1785
1786class BracedRangeExpr : public Node {
1787 const Node *First;
1788 const Node *Last;
1789 const Node *Init;
1790public:
1791 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
1792 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
1793
1794 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
1795
1796 void printLeft(OutputStream &S) const override {
1797 S += '[';
1798 First->print(S);
1799 S += " ... ";
1800 Last->print(S);
1801 S += ']';
1802 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1803 S += " = ";
1804 Init->print(S);
1805 }
1806};
1807
1808class FoldExpr : public Node {
1809 const Node *Pack, *Init;
1810 StringView OperatorName;
1811 bool IsLeftFold;
1812
1813public:
1814 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
1815 const Node *Init_)
1816 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
1817 IsLeftFold(IsLeftFold_) {}
1818
1819 template<typename Fn> void match(Fn F) const {
1820 F(IsLeftFold, OperatorName, Pack, Init);
1821 }
1822
1823 void printLeft(OutputStream &S) const override {
1824 auto PrintPack = [&] {
1825 S += '(';
1826 ParameterPackExpansion(Pack).print(S);
1827 S += ')';
1828 };
1829
1830 S += '(';
1831
1832 if (IsLeftFold) {
1833 // init op ... op pack
1834 if (Init != nullptr) {
1835 Init->print(S);
1836 S += ' ';
1837 S += OperatorName;
1838 S += ' ';
1839 }
1840 // ... op pack
1841 S += "... ";
1842 S += OperatorName;
1843 S += ' ';
1844 PrintPack();
1845 } else { // !IsLeftFold
1846 // pack op ...
1847 PrintPack();
1848 S += ' ';
1849 S += OperatorName;
1850 S += " ...";
1851 // pack op ... op init
1852 if (Init != nullptr) {
1853 S += ' ';
1854 S += OperatorName;
1855 S += ' ';
1856 Init->print(S);
1857 }
1858 }
1859 S += ')';
1860 }
1861};
1862
1863class ThrowExpr : public Node {
1864 const Node *Op;
1865
1866public:
1867 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
1868
1869 template<typename Fn> void match(Fn F) const { F(Op); }
1870
1871 void printLeft(OutputStream &S) const override {
1872 S += "throw ";
1873 Op->print(S);
1874 }
1875};
1876
1877class BoolExpr : public Node {
1878 bool Value;
1879
1880public:
1881 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
1882
1883 template<typename Fn> void match(Fn F) const { F(Value); }
1884
1885 void printLeft(OutputStream &S) const override {
1886 S += Value ? StringView("true") : StringView("false");
1887 }
1888};
1889
1890class IntegerCastExpr : public Node {
1891 // ty(integer)
1892 const Node *Ty;
1893 StringView Integer;
1894
1895public:
1896 IntegerCastExpr(const Node *Ty_, StringView Integer_)
1897 : Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {}
1898
1899 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
1900
1901 void printLeft(OutputStream &S) const override {
1902 S += "(";
1903 Ty->print(S);
1904 S += ")";
1905 S += Integer;
1906 }
1907};
1908
1909class IntegerLiteral : public Node {
1910 StringView Type;
1911 StringView Value;
1912
1913public:
1914 IntegerLiteral(StringView Type_, StringView Value_)
1915 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
1916
1917 template<typename Fn> void match(Fn F) const { F(Type, Value); }
1918
1919 void printLeft(OutputStream &S) const override {
1920 if (Type.size() > 3) {
1921 S += "(";
1922 S += Type;
1923 S += ")";
1924 }
1925
1926 if (Value[0] == 'n') {
1927 S += "-";
1928 S += Value.dropFront(1);
1929 } else
1930 S += Value;
1931
1932 if (Type.size() <= 3)
1933 S += Type;
1934 }
1935};
1936
1937template <class Float> struct FloatData;
1938
1939namespace float_literal_impl {
1940constexpr Node::Kind getFloatLiteralKind(float *) {
1941 return Node::KFloatLiteral;
1942}
1943constexpr Node::Kind getFloatLiteralKind(double *) {
1944 return Node::KDoubleLiteral;
1945}
1946constexpr Node::Kind getFloatLiteralKind(long double *) {
1947 return Node::KLongDoubleLiteral;
1948}
1949}
1950
1951template <class Float> class FloatLiteralImpl : public Node {
1952 const StringView Contents;
1953
1954 static constexpr Kind KindForClass =
1955 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
1956
1957public:
1958 FloatLiteralImpl(StringView Contents_)
1959 : Node(KindForClass), Contents(Contents_) {}
1960
1961 template<typename Fn> void match(Fn F) const { F(Contents); }
1962
1963 void printLeft(OutputStream &s) const override {
1964 const char *first = Contents.begin();
1965 const char *last = Contents.end() + 1;
1966
1967 const size_t N = FloatData<Float>::mangled_size;
1968 if (static_cast<std::size_t>(last - first) > N) {
1969 last = first + N;
1970 union {
1971 Float value;
1972 char buf[sizeof(Float)];
1973 };
1974 const char *t = first;
1975 char *e = buf;
1976 for (; t != last; ++t, ++e) {
1977 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
1978 : static_cast<unsigned>(*t - 'a' + 10);
1979 ++t;
1980 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
1981 : static_cast<unsigned>(*t - 'a' + 10);
1982 *e = static_cast<char>((d1 << 4) + d0);
1983 }
1984#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
1985 std::reverse(buf, e);
1986#endif
1987 char num[FloatData<Float>::max_demangled_size] = {0};
1988 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
1989 s += StringView(num, num + n);
1990 }
1991 }
1992};
1993
1994using FloatLiteral = FloatLiteralImpl<float>;
1995using DoubleLiteral = FloatLiteralImpl<double>;
1996using LongDoubleLiteral = FloatLiteralImpl<long double>;
1997
1998/// Visit the node. Calls \c F(P), where \c P is the node cast to the
1999/// appropriate derived class.
2000template<typename Fn>
2001void Node::visit(Fn F) const {
2002 switch (K) {
2003#define CASE(X) case K ## X: return F(static_cast<const X*>(this));
2004 FOR_EACH_NODE_KIND(CASE)
2005#undef CASE
2006 }
2007 assert(0 && "unknown mangling node kind");
2008}
2009
2010/// Determine the kind of a node from its type.
2011template<typename NodeT> struct NodeKind;
2012#define SPECIALIZATION(X) \
2013 template<> struct NodeKind<X> { \
2014 static constexpr Node::Kind Kind = Node::K##X; \
2015 static constexpr const char *name() { return #X; } \
2016 };
2017FOR_EACH_NODE_KIND(SPECIALIZATION)
2018#undef SPECIALIZATION
2019
2020#undef FOR_EACH_NODE_KIND
2021
2022template <class T, size_t N>
2023class PODSmallVector {
2024 static_assert(std::is_pod<T>::value,
2025 "T is required to be a plain old data type");
2026
2027 T* First;
2028 T* Last;
2029 T* Cap;
2030 T Inline[N];
2031
2032 bool isInline() const { return First == Inline; }
2033
2034 void clearInline() {
2035 First = Inline;
2036 Last = Inline;
2037 Cap = Inline + N;
2038 }
2039
2040 void reserve(size_t NewCap) {
2041 size_t S = size();
2042 if (isInline()) {
2043 auto* Tmp = static_cast<T*>(std::malloc(NewCap * sizeof(T)));
2044 if (Tmp == nullptr)
2045 std::terminate();
2046 std::copy(First, Last, Tmp);
2047 First = Tmp;
2048 } else {
2049 First = static_cast<T*>(std::realloc(First, NewCap * sizeof(T)));
2050 if (First == nullptr)
2051 std::terminate();
2052 }
2053 Last = First + S;
2054 Cap = First + NewCap;
2055 }
2056
2057public:
2058 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
2059
2060 PODSmallVector(const PODSmallVector&) = delete;
2061 PODSmallVector& operator=(const PODSmallVector&) = delete;
2062
2063 PODSmallVector(PODSmallVector&& Other) : PODSmallVector() {
2064 if (Other.isInline()) {
2065 std::copy(Other.begin(), Other.end(), First);
2066 Last = First + Other.size();
2067 Other.clear();
2068 return;
2069 }
2070
2071 First = Other.First;
2072 Last = Other.Last;
2073 Cap = Other.Cap;
2074 Other.clearInline();
2075 }
2076
2077 PODSmallVector& operator=(PODSmallVector&& Other) {
2078 if (Other.isInline()) {
2079 if (!isInline()) {
2080 std::free(First);
2081 clearInline();
2082 }
2083 std::copy(Other.begin(), Other.end(), First);
2084 Last = First + Other.size();
2085 Other.clear();
2086 return *this;
2087 }
2088
2089 if (isInline()) {
2090 First = Other.First;
2091 Last = Other.Last;
2092 Cap = Other.Cap;
2093 Other.clearInline();
2094 return *this;
2095 }
2096
2097 std::swap(First, Other.First);
2098 std::swap(Last, Other.Last);
2099 std::swap(Cap, Other.Cap);
2100 Other.clear();
2101 return *this;
2102 }
2103
2104 void push_back(const T& Elem) {
2105 if (Last == Cap)
2106 reserve(size() * 2);
2107 *Last++ = Elem;
2108 }
2109
2110 void pop_back() {
2111 assert(Last != First && "Popping empty vector!");
2112 --Last;
2113 }
2114
2115 void dropBack(size_t Index) {
2116 assert(Index <= size() && "dropBack() can't expand!");
2117 Last = First + Index;
2118 }
2119
2120 T* begin() { return First; }
2121 T* end() { return Last; }
2122
2123 bool empty() const { return First == Last; }
2124 size_t size() const { return static_cast<size_t>(Last - First); }
2125 T& back() {
2126 assert(Last != First && "Calling back() on empty vector!");
2127 return *(Last - 1);
2128 }
2129 T& operator[](size_t Index) {
2130 assert(Index < size() && "Invalid access!");
2131 return *(begin() + Index);
2132 }
2133 void clear() { Last = First; }
2134
2135 ~PODSmallVector() {
2136 if (!isInline())
2137 std::free(First);
2138 }
2139};
2140
Pavel Labathba825192018-10-16 14:29:14 +00002141template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002142 const char *First;
2143 const char *Last;
2144
2145 // Name stack, this is used by the parser to hold temporary names that were
2146 // parsed. The parser collapses multiple names into new nodes to construct
2147 // the AST. Once the parser is finished, names.size() == 1.
2148 PODSmallVector<Node *, 32> Names;
2149
2150 // Substitution table. Itanium supports name substitutions as a means of
2151 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2152 // table.
2153 PODSmallVector<Node *, 32> Subs;
2154
2155 // Template parameter table. Like the above, but referenced like "T42_".
2156 // This has a smaller size compared to Subs and Names because it can be
2157 // stored on the stack.
2158 PODSmallVector<Node *, 8> TemplateParams;
2159
2160 // Set of unresolved forward <template-param> references. These can occur in a
2161 // conversion operator's type, and are resolved in the enclosing <encoding>.
2162 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2163
Richard Smithc20d1442018-08-20 20:14:49 +00002164 bool TryToParseTemplateArgs = true;
2165 bool PermitForwardTemplateReferences = false;
2166 bool ParsingLambdaParams = false;
2167
2168 Alloc ASTAllocator;
2169
Pavel Labathba825192018-10-16 14:29:14 +00002170 AbstractManglingParser(const char *First_, const char *Last_)
2171 : First(First_), Last(Last_) {}
2172
2173 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002174
2175 void reset(const char *First_, const char *Last_) {
2176 First = First_;
2177 Last = Last_;
2178 Names.clear();
2179 Subs.clear();
2180 TemplateParams.clear();
2181 ParsingLambdaParams = false;
2182 TryToParseTemplateArgs = true;
2183 PermitForwardTemplateReferences = false;
2184 ASTAllocator.reset();
2185 }
2186
Richard Smithb485b352018-08-24 23:30:26 +00002187 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002188 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2189 }
2190
2191 template <class It> NodeArray makeNodeArray(It begin, It end) {
2192 size_t sz = static_cast<size_t>(end - begin);
2193 void *mem = ASTAllocator.allocateNodeArray(sz);
2194 Node **data = new (mem) Node *[sz];
2195 std::copy(begin, end, data);
2196 return NodeArray(data, sz);
2197 }
2198
2199 NodeArray popTrailingNodeArray(size_t FromPosition) {
2200 assert(FromPosition <= Names.size());
2201 NodeArray res =
2202 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2203 Names.dropBack(FromPosition);
2204 return res;
2205 }
2206
2207 bool consumeIf(StringView S) {
2208 if (StringView(First, Last).startsWith(S)) {
2209 First += S.size();
2210 return true;
2211 }
2212 return false;
2213 }
2214
2215 bool consumeIf(char C) {
2216 if (First != Last && *First == C) {
2217 ++First;
2218 return true;
2219 }
2220 return false;
2221 }
2222
2223 char consume() { return First != Last ? *First++ : '\0'; }
2224
2225 char look(unsigned Lookahead = 0) {
2226 if (static_cast<size_t>(Last - First) <= Lookahead)
2227 return '\0';
2228 return First[Lookahead];
2229 }
2230
2231 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2232
2233 StringView parseNumber(bool AllowNegative = false);
2234 Qualifiers parseCVQualifiers();
2235 bool parsePositiveInteger(size_t *Out);
2236 StringView parseBareSourceName();
2237
2238 bool parseSeqId(size_t *Out);
2239 Node *parseSubstitution();
2240 Node *parseTemplateParam();
2241 Node *parseTemplateArgs(bool TagTemplates = false);
2242 Node *parseTemplateArg();
2243
2244 /// Parse the <expr> production.
2245 Node *parseExpr();
2246 Node *parsePrefixExpr(StringView Kind);
2247 Node *parseBinaryExpr(StringView Kind);
2248 Node *parseIntegerLiteral(StringView Lit);
2249 Node *parseExprPrimary();
2250 template <class Float> Node *parseFloatingLiteral();
2251 Node *parseFunctionParam();
2252 Node *parseNewExpr();
2253 Node *parseConversionExpr();
2254 Node *parseBracedExpr();
2255 Node *parseFoldExpr();
2256
2257 /// Parse the <type> production.
2258 Node *parseType();
2259 Node *parseFunctionType();
2260 Node *parseVectorType();
2261 Node *parseDecltype();
2262 Node *parseArrayType();
2263 Node *parsePointerToMemberType();
2264 Node *parseClassEnumType();
2265 Node *parseQualifiedType();
2266
2267 Node *parseEncoding();
2268 bool parseCallOffset();
2269 Node *parseSpecialName();
2270
2271 /// Holds some extra information about a <name> that is being parsed. This
2272 /// information is only pertinent if the <name> refers to an <encoding>.
2273 struct NameState {
2274 bool CtorDtorConversion = false;
2275 bool EndsWithTemplateArgs = false;
2276 Qualifiers CVQualifiers = QualNone;
2277 FunctionRefQual ReferenceQualifier = FrefQualNone;
2278 size_t ForwardTemplateRefsBegin;
2279
Pavel Labathba825192018-10-16 14:29:14 +00002280 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002281 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2282 };
2283
2284 bool resolveForwardTemplateRefs(NameState &State) {
2285 size_t I = State.ForwardTemplateRefsBegin;
2286 size_t E = ForwardTemplateRefs.size();
2287 for (; I < E; ++I) {
2288 size_t Idx = ForwardTemplateRefs[I]->Index;
2289 if (Idx >= TemplateParams.size())
2290 return true;
2291 ForwardTemplateRefs[I]->Ref = TemplateParams[Idx];
2292 }
2293 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2294 return false;
2295 }
2296
2297 /// Parse the <name> production>
2298 Node *parseName(NameState *State = nullptr);
2299 Node *parseLocalName(NameState *State);
2300 Node *parseOperatorName(NameState *State);
2301 Node *parseUnqualifiedName(NameState *State);
2302 Node *parseUnnamedTypeName(NameState *State);
2303 Node *parseSourceName(NameState *State);
2304 Node *parseUnscopedName(NameState *State);
2305 Node *parseNestedName(NameState *State);
2306 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2307
2308 Node *parseAbiTags(Node *N);
2309
2310 /// Parse the <unresolved-name> production.
2311 Node *parseUnresolvedName();
2312 Node *parseSimpleId();
2313 Node *parseBaseUnresolvedName();
2314 Node *parseUnresolvedType();
2315 Node *parseDestructorName();
2316
2317 /// Top-level entry point into the parser.
2318 Node *parse();
2319};
2320
2321const char* parse_discriminator(const char* first, const char* last);
2322
2323// <name> ::= <nested-name> // N
2324// ::= <local-name> # See Scope Encoding below // Z
2325// ::= <unscoped-template-name> <template-args>
2326// ::= <unscoped-name>
2327//
2328// <unscoped-template-name> ::= <unscoped-name>
2329// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002330template <typename Derived, typename Alloc>
2331Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002332 consumeIf('L'); // extension
2333
2334 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002335 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002336 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002337 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002338
2339 // ::= <unscoped-template-name> <template-args>
2340 if (look() == 'S' && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00002341 Node *S = getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00002342 if (S == nullptr)
2343 return nullptr;
2344 if (look() != 'I')
2345 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002346 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002347 if (TA == nullptr)
2348 return nullptr;
2349 if (State) State->EndsWithTemplateArgs = true;
2350 return make<NameWithTemplateArgs>(S, TA);
2351 }
2352
Pavel Labathba825192018-10-16 14:29:14 +00002353 Node *N = getDerived().parseUnscopedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002354 if (N == nullptr)
2355 return nullptr;
2356 // ::= <unscoped-template-name> <template-args>
2357 if (look() == 'I') {
2358 Subs.push_back(N);
Pavel Labathba825192018-10-16 14:29:14 +00002359 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002360 if (TA == nullptr)
2361 return nullptr;
2362 if (State) State->EndsWithTemplateArgs = true;
2363 return make<NameWithTemplateArgs>(N, TA);
2364 }
2365 // ::= <unscoped-name>
2366 return N;
2367}
2368
2369// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2370// := Z <function encoding> E s [<discriminator>]
2371// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002372template <typename Derived, typename Alloc>
2373Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002374 if (!consumeIf('Z'))
2375 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002376 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002377 if (Encoding == nullptr || !consumeIf('E'))
2378 return nullptr;
2379
2380 if (consumeIf('s')) {
2381 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002382 auto *StringLitName = make<NameType>("string literal");
2383 if (!StringLitName)
2384 return nullptr;
2385 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002386 }
2387
2388 if (consumeIf('d')) {
2389 parseNumber(true);
2390 if (!consumeIf('_'))
2391 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002392 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002393 if (N == nullptr)
2394 return nullptr;
2395 return make<LocalName>(Encoding, N);
2396 }
2397
Pavel Labathba825192018-10-16 14:29:14 +00002398 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002399 if (Entity == nullptr)
2400 return nullptr;
2401 First = parse_discriminator(First, Last);
2402 return make<LocalName>(Encoding, Entity);
2403}
2404
2405// <unscoped-name> ::= <unqualified-name>
2406// ::= St <unqualified-name> # ::std::
2407// extension ::= StL<unqualified-name>
Pavel Labathba825192018-10-16 14:29:14 +00002408template <typename Derived, typename Alloc>
2409Node *
2410AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {
2411 if (consumeIf("StL") || consumeIf("St")) {
2412 Node *R = getDerived().parseUnqualifiedName(State);
2413 if (R == nullptr)
2414 return nullptr;
2415 return make<StdQualifiedName>(R);
2416 }
2417 return getDerived().parseUnqualifiedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002418}
2419
2420// <unqualified-name> ::= <operator-name> [abi-tags]
2421// ::= <ctor-dtor-name>
2422// ::= <source-name>
2423// ::= <unnamed-type-name>
2424// ::= DC <source-name>+ E # structured binding declaration
Pavel Labathba825192018-10-16 14:29:14 +00002425template <typename Derived, typename Alloc>
2426Node *
2427AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002428 // <ctor-dtor-name>s are special-cased in parseNestedName().
2429 Node *Result;
2430 if (look() == 'U')
Pavel Labathba825192018-10-16 14:29:14 +00002431 Result = getDerived().parseUnnamedTypeName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002432 else if (look() >= '1' && look() <= '9')
Pavel Labathba825192018-10-16 14:29:14 +00002433 Result = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002434 else if (consumeIf("DC")) {
2435 size_t BindingsBegin = Names.size();
2436 do {
Pavel Labathba825192018-10-16 14:29:14 +00002437 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002438 if (Binding == nullptr)
2439 return nullptr;
2440 Names.push_back(Binding);
2441 } while (!consumeIf('E'));
2442 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
2443 } else
Pavel Labathba825192018-10-16 14:29:14 +00002444 Result = getDerived().parseOperatorName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002445 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002446 Result = getDerived().parseAbiTags(Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002447 return Result;
2448}
2449
2450// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2451// ::= <closure-type-name>
2452//
2453// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2454//
2455// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002456template <typename Derived, typename Alloc>
2457Node *
2458AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002459 if (consumeIf("Ut")) {
2460 StringView Count = parseNumber();
2461 if (!consumeIf('_'))
2462 return nullptr;
2463 return make<UnnamedTypeName>(Count);
2464 }
2465 if (consumeIf("Ul")) {
2466 NodeArray Params;
2467 SwapAndRestore<bool> SwapParams(ParsingLambdaParams, true);
2468 if (!consumeIf("vE")) {
2469 size_t ParamsBegin = Names.size();
2470 do {
Pavel Labathba825192018-10-16 14:29:14 +00002471 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002472 if (P == nullptr)
2473 return nullptr;
2474 Names.push_back(P);
2475 } while (!consumeIf('E'));
2476 Params = popTrailingNodeArray(ParamsBegin);
2477 }
2478 StringView Count = parseNumber();
2479 if (!consumeIf('_'))
2480 return nullptr;
2481 return make<ClosureTypeName>(Params, Count);
2482 }
2483 return nullptr;
2484}
2485
2486// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002487template <typename Derived, typename Alloc>
2488Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002489 size_t Length = 0;
2490 if (parsePositiveInteger(&Length))
2491 return nullptr;
2492 if (numLeft() < Length || Length == 0)
2493 return nullptr;
2494 StringView Name(First, First + Length);
2495 First += Length;
2496 if (Name.startsWith("_GLOBAL__N"))
2497 return make<NameType>("(anonymous namespace)");
2498 return make<NameType>(Name);
2499}
2500
2501// <operator-name> ::= aa # &&
2502// ::= ad # & (unary)
2503// ::= an # &
2504// ::= aN # &=
2505// ::= aS # =
2506// ::= cl # ()
2507// ::= cm # ,
2508// ::= co # ~
2509// ::= cv <type> # (cast)
2510// ::= da # delete[]
2511// ::= de # * (unary)
2512// ::= dl # delete
2513// ::= dv # /
2514// ::= dV # /=
2515// ::= eo # ^
2516// ::= eO # ^=
2517// ::= eq # ==
2518// ::= ge # >=
2519// ::= gt # >
2520// ::= ix # []
2521// ::= le # <=
2522// ::= li <source-name> # operator ""
2523// ::= ls # <<
2524// ::= lS # <<=
2525// ::= lt # <
2526// ::= mi # -
2527// ::= mI # -=
2528// ::= ml # *
2529// ::= mL # *=
2530// ::= mm # -- (postfix in <expression> context)
2531// ::= na # new[]
2532// ::= ne # !=
2533// ::= ng # - (unary)
2534// ::= nt # !
2535// ::= nw # new
2536// ::= oo # ||
2537// ::= or # |
2538// ::= oR # |=
2539// ::= pm # ->*
2540// ::= pl # +
2541// ::= pL # +=
2542// ::= pp # ++ (postfix in <expression> context)
2543// ::= ps # + (unary)
2544// ::= pt # ->
2545// ::= qu # ?
2546// ::= rm # %
2547// ::= rM # %=
2548// ::= rs # >>
2549// ::= rS # >>=
2550// ::= ss # <=> C++2a
2551// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00002552template <typename Derived, typename Alloc>
2553Node *
2554AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002555 switch (look()) {
2556 case 'a':
2557 switch (look(1)) {
2558 case 'a':
2559 First += 2;
2560 return make<NameType>("operator&&");
2561 case 'd':
2562 case 'n':
2563 First += 2;
2564 return make<NameType>("operator&");
2565 case 'N':
2566 First += 2;
2567 return make<NameType>("operator&=");
2568 case 'S':
2569 First += 2;
2570 return make<NameType>("operator=");
2571 }
2572 return nullptr;
2573 case 'c':
2574 switch (look(1)) {
2575 case 'l':
2576 First += 2;
2577 return make<NameType>("operator()");
2578 case 'm':
2579 First += 2;
2580 return make<NameType>("operator,");
2581 case 'o':
2582 First += 2;
2583 return make<NameType>("operator~");
2584 // ::= cv <type> # (cast)
2585 case 'v': {
2586 First += 2;
2587 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
2588 // If we're parsing an encoding, State != nullptr and the conversion
2589 // operators' <type> could have a <template-param> that refers to some
2590 // <template-arg>s further ahead in the mangled name.
2591 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
2592 PermitForwardTemplateReferences ||
2593 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00002594 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002595 if (Ty == nullptr)
2596 return nullptr;
2597 if (State) State->CtorDtorConversion = true;
2598 return make<ConversionOperatorType>(Ty);
2599 }
2600 }
2601 return nullptr;
2602 case 'd':
2603 switch (look(1)) {
2604 case 'a':
2605 First += 2;
2606 return make<NameType>("operator delete[]");
2607 case 'e':
2608 First += 2;
2609 return make<NameType>("operator*");
2610 case 'l':
2611 First += 2;
2612 return make<NameType>("operator delete");
2613 case 'v':
2614 First += 2;
2615 return make<NameType>("operator/");
2616 case 'V':
2617 First += 2;
2618 return make<NameType>("operator/=");
2619 }
2620 return nullptr;
2621 case 'e':
2622 switch (look(1)) {
2623 case 'o':
2624 First += 2;
2625 return make<NameType>("operator^");
2626 case 'O':
2627 First += 2;
2628 return make<NameType>("operator^=");
2629 case 'q':
2630 First += 2;
2631 return make<NameType>("operator==");
2632 }
2633 return nullptr;
2634 case 'g':
2635 switch (look(1)) {
2636 case 'e':
2637 First += 2;
2638 return make<NameType>("operator>=");
2639 case 't':
2640 First += 2;
2641 return make<NameType>("operator>");
2642 }
2643 return nullptr;
2644 case 'i':
2645 if (look(1) == 'x') {
2646 First += 2;
2647 return make<NameType>("operator[]");
2648 }
2649 return nullptr;
2650 case 'l':
2651 switch (look(1)) {
2652 case 'e':
2653 First += 2;
2654 return make<NameType>("operator<=");
2655 // ::= li <source-name> # operator ""
2656 case 'i': {
2657 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00002658 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002659 if (SN == nullptr)
2660 return nullptr;
2661 return make<LiteralOperator>(SN);
2662 }
2663 case 's':
2664 First += 2;
2665 return make<NameType>("operator<<");
2666 case 'S':
2667 First += 2;
2668 return make<NameType>("operator<<=");
2669 case 't':
2670 First += 2;
2671 return make<NameType>("operator<");
2672 }
2673 return nullptr;
2674 case 'm':
2675 switch (look(1)) {
2676 case 'i':
2677 First += 2;
2678 return make<NameType>("operator-");
2679 case 'I':
2680 First += 2;
2681 return make<NameType>("operator-=");
2682 case 'l':
2683 First += 2;
2684 return make<NameType>("operator*");
2685 case 'L':
2686 First += 2;
2687 return make<NameType>("operator*=");
2688 case 'm':
2689 First += 2;
2690 return make<NameType>("operator--");
2691 }
2692 return nullptr;
2693 case 'n':
2694 switch (look(1)) {
2695 case 'a':
2696 First += 2;
2697 return make<NameType>("operator new[]");
2698 case 'e':
2699 First += 2;
2700 return make<NameType>("operator!=");
2701 case 'g':
2702 First += 2;
2703 return make<NameType>("operator-");
2704 case 't':
2705 First += 2;
2706 return make<NameType>("operator!");
2707 case 'w':
2708 First += 2;
2709 return make<NameType>("operator new");
2710 }
2711 return nullptr;
2712 case 'o':
2713 switch (look(1)) {
2714 case 'o':
2715 First += 2;
2716 return make<NameType>("operator||");
2717 case 'r':
2718 First += 2;
2719 return make<NameType>("operator|");
2720 case 'R':
2721 First += 2;
2722 return make<NameType>("operator|=");
2723 }
2724 return nullptr;
2725 case 'p':
2726 switch (look(1)) {
2727 case 'm':
2728 First += 2;
2729 return make<NameType>("operator->*");
2730 case 'l':
2731 First += 2;
2732 return make<NameType>("operator+");
2733 case 'L':
2734 First += 2;
2735 return make<NameType>("operator+=");
2736 case 'p':
2737 First += 2;
2738 return make<NameType>("operator++");
2739 case 's':
2740 First += 2;
2741 return make<NameType>("operator+");
2742 case 't':
2743 First += 2;
2744 return make<NameType>("operator->");
2745 }
2746 return nullptr;
2747 case 'q':
2748 if (look(1) == 'u') {
2749 First += 2;
2750 return make<NameType>("operator?");
2751 }
2752 return nullptr;
2753 case 'r':
2754 switch (look(1)) {
2755 case 'm':
2756 First += 2;
2757 return make<NameType>("operator%");
2758 case 'M':
2759 First += 2;
2760 return make<NameType>("operator%=");
2761 case 's':
2762 First += 2;
2763 return make<NameType>("operator>>");
2764 case 'S':
2765 First += 2;
2766 return make<NameType>("operator>>=");
2767 }
2768 return nullptr;
2769 case 's':
2770 if (look(1) == 's') {
2771 First += 2;
2772 return make<NameType>("operator<=>");
2773 }
2774 return nullptr;
2775 // ::= v <digit> <source-name> # vendor extended operator
2776 case 'v':
2777 if (std::isdigit(look(1))) {
2778 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00002779 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002780 if (SN == nullptr)
2781 return nullptr;
2782 return make<ConversionOperatorType>(SN);
2783 }
2784 return nullptr;
2785 }
2786 return nullptr;
2787}
2788
2789// <ctor-dtor-name> ::= C1 # complete object constructor
2790// ::= C2 # base object constructor
2791// ::= C3 # complete object allocating constructor
2792// extension ::= C5 # ?
2793// ::= D0 # deleting destructor
2794// ::= D1 # complete object destructor
2795// ::= D2 # base object destructor
2796// extension ::= D5 # ?
Pavel Labathba825192018-10-16 14:29:14 +00002797template <typename Derived, typename Alloc>
2798Node *
2799AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
2800 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002801 if (SoFar->getKind() == Node::KSpecialSubstitution) {
2802 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
2803 switch (SSK) {
2804 case SpecialSubKind::string:
2805 case SpecialSubKind::istream:
2806 case SpecialSubKind::ostream:
2807 case SpecialSubKind::iostream:
2808 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00002809 if (!SoFar)
2810 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00002811 break;
Richard Smithc20d1442018-08-20 20:14:49 +00002812 default:
2813 break;
2814 }
2815 }
2816
2817 if (consumeIf('C')) {
2818 bool IsInherited = consumeIf('I');
2819 if (look() != '1' && look() != '2' && look() != '3' && look() != '5')
2820 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002821 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00002822 ++First;
2823 if (State) State->CtorDtorConversion = true;
2824 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00002825 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00002826 return nullptr;
2827 }
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002828 return make<CtorDtorName>(SoFar, false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00002829 }
2830
2831 if (look() == 'D' &&
2832 (look(1) == '0' || look(1) == '1' || look(1) == '2' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002833 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00002834 First += 2;
2835 if (State) State->CtorDtorConversion = true;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002836 return make<CtorDtorName>(SoFar, true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00002837 }
2838
2839 return nullptr;
2840}
2841
2842// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
2843// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
2844//
2845// <prefix> ::= <prefix> <unqualified-name>
2846// ::= <template-prefix> <template-args>
2847// ::= <template-param>
2848// ::= <decltype>
2849// ::= # empty
2850// ::= <substitution>
2851// ::= <prefix> <data-member-prefix>
2852// extension ::= L
2853//
2854// <data-member-prefix> := <member source-name> [<template-args>] M
2855//
2856// <template-prefix> ::= <prefix> <template unqualified-name>
2857// ::= <template-param>
2858// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002859template <typename Derived, typename Alloc>
2860Node *
2861AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002862 if (!consumeIf('N'))
2863 return nullptr;
2864
2865 Qualifiers CVTmp = parseCVQualifiers();
2866 if (State) State->CVQualifiers = CVTmp;
2867
2868 if (consumeIf('O')) {
2869 if (State) State->ReferenceQualifier = FrefQualRValue;
2870 } else if (consumeIf('R')) {
2871 if (State) State->ReferenceQualifier = FrefQualLValue;
2872 } else
2873 if (State) State->ReferenceQualifier = FrefQualNone;
2874
2875 Node *SoFar = nullptr;
2876 auto PushComponent = [&](Node *Comp) {
Richard Smithb485b352018-08-24 23:30:26 +00002877 if (!Comp) return false;
Richard Smithc20d1442018-08-20 20:14:49 +00002878 if (SoFar) SoFar = make<NestedName>(SoFar, Comp);
2879 else SoFar = Comp;
2880 if (State) State->EndsWithTemplateArgs = false;
Richard Smithb485b352018-08-24 23:30:26 +00002881 return SoFar != nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002882 };
2883
Richard Smithb485b352018-08-24 23:30:26 +00002884 if (consumeIf("St")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002885 SoFar = make<NameType>("std");
Richard Smithb485b352018-08-24 23:30:26 +00002886 if (!SoFar)
2887 return nullptr;
2888 }
Richard Smithc20d1442018-08-20 20:14:49 +00002889
2890 while (!consumeIf('E')) {
2891 consumeIf('L'); // extension
2892
2893 // <data-member-prefix> := <member source-name> [<template-args>] M
2894 if (consumeIf('M')) {
2895 if (SoFar == nullptr)
2896 return nullptr;
2897 continue;
2898 }
2899
2900 // ::= <template-param>
2901 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00002902 if (!PushComponent(getDerived().parseTemplateParam()))
Richard Smithc20d1442018-08-20 20:14:49 +00002903 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002904 Subs.push_back(SoFar);
2905 continue;
2906 }
2907
2908 // ::= <template-prefix> <template-args>
2909 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00002910 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002911 if (TA == nullptr || SoFar == nullptr)
2912 return nullptr;
2913 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00002914 if (!SoFar)
2915 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002916 if (State) State->EndsWithTemplateArgs = true;
2917 Subs.push_back(SoFar);
2918 continue;
2919 }
2920
2921 // ::= <decltype>
2922 if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
Pavel Labathba825192018-10-16 14:29:14 +00002923 if (!PushComponent(getDerived().parseDecltype()))
Richard Smithc20d1442018-08-20 20:14:49 +00002924 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002925 Subs.push_back(SoFar);
2926 continue;
2927 }
2928
2929 // ::= <substitution>
2930 if (look() == 'S' && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00002931 Node *S = getDerived().parseSubstitution();
Richard Smithb485b352018-08-24 23:30:26 +00002932 if (!PushComponent(S))
Richard Smithc20d1442018-08-20 20:14:49 +00002933 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002934 if (SoFar != S)
2935 Subs.push_back(S);
2936 continue;
2937 }
2938
2939 // Parse an <unqualified-name> thats actually a <ctor-dtor-name>.
2940 if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {
2941 if (SoFar == nullptr)
2942 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002943 if (!PushComponent(getDerived().parseCtorDtorName(SoFar, State)))
Richard Smithc20d1442018-08-20 20:14:49 +00002944 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002945 SoFar = getDerived().parseAbiTags(SoFar);
Richard Smithc20d1442018-08-20 20:14:49 +00002946 if (SoFar == nullptr)
2947 return nullptr;
2948 Subs.push_back(SoFar);
2949 continue;
2950 }
2951
2952 // ::= <prefix> <unqualified-name>
Pavel Labathba825192018-10-16 14:29:14 +00002953 if (!PushComponent(getDerived().parseUnqualifiedName(State)))
Richard Smithc20d1442018-08-20 20:14:49 +00002954 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002955 Subs.push_back(SoFar);
2956 }
2957
2958 if (SoFar == nullptr || Subs.empty())
2959 return nullptr;
2960
2961 Subs.pop_back();
2962 return SoFar;
2963}
2964
2965// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00002966template <typename Derived, typename Alloc>
2967Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
2968 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002969 if (SN == nullptr)
2970 return nullptr;
2971 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00002972 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00002973 if (TA == nullptr)
2974 return nullptr;
2975 return make<NameWithTemplateArgs>(SN, TA);
2976 }
2977 return SN;
2978}
2979
2980// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
2981// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00002982template <typename Derived, typename Alloc>
2983Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00002984 Node *Result;
2985 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00002986 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00002987 else
Pavel Labathba825192018-10-16 14:29:14 +00002988 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00002989 if (Result == nullptr)
2990 return nullptr;
2991 return make<DtorName>(Result);
2992}
2993
2994// <unresolved-type> ::= <template-param>
2995// ::= <decltype>
2996// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002997template <typename Derived, typename Alloc>
2998Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00002999 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003000 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003001 if (TP == nullptr)
3002 return nullptr;
3003 Subs.push_back(TP);
3004 return TP;
3005 }
3006 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003007 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003008 if (DT == nullptr)
3009 return nullptr;
3010 Subs.push_back(DT);
3011 return DT;
3012 }
Pavel Labathba825192018-10-16 14:29:14 +00003013 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003014}
3015
3016// <base-unresolved-name> ::= <simple-id> # unresolved name
3017// extension ::= <operator-name> # unresolved operator-function-id
3018// extension ::= <operator-name> <template-args> # unresolved operator template-id
3019// ::= on <operator-name> # unresolved operator-function-id
3020// ::= on <operator-name> <template-args> # unresolved operator template-id
3021// ::= dn <destructor-name> # destructor or pseudo-destructor;
3022// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003023template <typename Derived, typename Alloc>
3024Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003025 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003026 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003027
3028 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003029 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003030
3031 consumeIf("on");
3032
Pavel Labathba825192018-10-16 14:29:14 +00003033 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003034 if (Oper == nullptr)
3035 return nullptr;
3036 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003037 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003038 if (TA == nullptr)
3039 return nullptr;
3040 return make<NameWithTemplateArgs>(Oper, TA);
3041 }
3042 return Oper;
3043}
3044
3045// <unresolved-name>
3046// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3047// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3048// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3049// # A::x, N::y, A<T>::z; "gs" means leading "::"
3050// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3051// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3052// # T::N::x /decltype(p)::N::x
3053// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3054//
3055// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003056template <typename Derived, typename Alloc>
3057Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003058 Node *SoFar = nullptr;
3059
3060 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3061 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3062 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003063 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003064 if (SoFar == nullptr)
3065 return nullptr;
3066
3067 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003068 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003069 if (TA == nullptr)
3070 return nullptr;
3071 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003072 if (!SoFar)
3073 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003074 }
3075
3076 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003077 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003078 if (Qual == nullptr)
3079 return nullptr;
3080 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003081 if (!SoFar)
3082 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003083 }
3084
Pavel Labathba825192018-10-16 14:29:14 +00003085 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003086 if (Base == nullptr)
3087 return nullptr;
3088 return make<QualifiedName>(SoFar, Base);
3089 }
3090
3091 bool Global = consumeIf("gs");
3092
3093 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3094 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003095 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003096 if (SoFar == nullptr)
3097 return nullptr;
3098 if (Global)
3099 SoFar = make<GlobalQualifiedName>(SoFar);
3100 return SoFar;
3101 }
3102
3103 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3104 if (std::isdigit(look())) {
3105 do {
Pavel Labathba825192018-10-16 14:29:14 +00003106 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003107 if (Qual == nullptr)
3108 return nullptr;
3109 if (SoFar)
3110 SoFar = make<QualifiedName>(SoFar, Qual);
3111 else if (Global)
3112 SoFar = make<GlobalQualifiedName>(Qual);
3113 else
3114 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003115 if (!SoFar)
3116 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003117 } while (!consumeIf('E'));
3118 }
3119 // sr <unresolved-type> <base-unresolved-name>
3120 // sr <unresolved-type> <template-args> <base-unresolved-name>
3121 else {
Pavel Labathba825192018-10-16 14:29:14 +00003122 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003123 if (SoFar == nullptr)
3124 return nullptr;
3125
3126 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003127 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003128 if (TA == nullptr)
3129 return nullptr;
3130 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003131 if (!SoFar)
3132 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003133 }
3134 }
3135
3136 assert(SoFar != nullptr);
3137
Pavel Labathba825192018-10-16 14:29:14 +00003138 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003139 if (Base == nullptr)
3140 return nullptr;
3141 return make<QualifiedName>(SoFar, Base);
3142}
3143
3144// <abi-tags> ::= <abi-tag> [<abi-tags>]
3145// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003146template <typename Derived, typename Alloc>
3147Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003148 while (consumeIf('B')) {
3149 StringView SN = parseBareSourceName();
3150 if (SN.empty())
3151 return nullptr;
3152 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003153 if (!N)
3154 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003155 }
3156 return N;
3157}
3158
3159// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003160template <typename Alloc, typename Derived>
3161StringView
3162AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003163 const char *Tmp = First;
3164 if (AllowNegative)
3165 consumeIf('n');
3166 if (numLeft() == 0 || !std::isdigit(*First))
3167 return StringView();
3168 while (numLeft() != 0 && std::isdigit(*First))
3169 ++First;
3170 return StringView(Tmp, First);
3171}
3172
3173// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003174template <typename Alloc, typename Derived>
3175bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003176 *Out = 0;
3177 if (look() < '0' || look() > '9')
3178 return true;
3179 while (look() >= '0' && look() <= '9') {
3180 *Out *= 10;
3181 *Out += static_cast<size_t>(consume() - '0');
3182 }
3183 return false;
3184}
3185
Pavel Labathba825192018-10-16 14:29:14 +00003186template <typename Alloc, typename Derived>
3187StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003188 size_t Int = 0;
3189 if (parsePositiveInteger(&Int) || numLeft() < Int)
3190 return StringView();
3191 StringView R(First, First + Int);
3192 First += Int;
3193 return R;
3194}
3195
3196// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3197//
3198// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3199// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3200// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3201//
3202// <ref-qualifier> ::= R # & ref-qualifier
3203// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003204template <typename Derived, typename Alloc>
3205Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003206 Qualifiers CVQuals = parseCVQualifiers();
3207
3208 Node *ExceptionSpec = nullptr;
3209 if (consumeIf("Do")) {
3210 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003211 if (!ExceptionSpec)
3212 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003213 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003214 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003215 if (E == nullptr || !consumeIf('E'))
3216 return nullptr;
3217 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003218 if (!ExceptionSpec)
3219 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003220 } else if (consumeIf("Dw")) {
3221 size_t SpecsBegin = Names.size();
3222 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003223 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003224 if (T == nullptr)
3225 return nullptr;
3226 Names.push_back(T);
3227 }
3228 ExceptionSpec =
3229 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003230 if (!ExceptionSpec)
3231 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003232 }
3233
3234 consumeIf("Dx"); // transaction safe
3235
3236 if (!consumeIf('F'))
3237 return nullptr;
3238 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003239 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003240 if (ReturnType == nullptr)
3241 return nullptr;
3242
3243 FunctionRefQual ReferenceQualifier = FrefQualNone;
3244 size_t ParamsBegin = Names.size();
3245 while (true) {
3246 if (consumeIf('E'))
3247 break;
3248 if (consumeIf('v'))
3249 continue;
3250 if (consumeIf("RE")) {
3251 ReferenceQualifier = FrefQualLValue;
3252 break;
3253 }
3254 if (consumeIf("OE")) {
3255 ReferenceQualifier = FrefQualRValue;
3256 break;
3257 }
Pavel Labathba825192018-10-16 14:29:14 +00003258 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003259 if (T == nullptr)
3260 return nullptr;
3261 Names.push_back(T);
3262 }
3263
3264 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3265 return make<FunctionType>(ReturnType, Params, CVQuals,
3266 ReferenceQualifier, ExceptionSpec);
3267}
3268
3269// extension:
3270// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3271// ::= Dv [<dimension expression>] _ <element type>
3272// <extended element type> ::= <element type>
3273// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003274template <typename Derived, typename Alloc>
3275Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003276 if (!consumeIf("Dv"))
3277 return nullptr;
3278 if (look() >= '1' && look() <= '9') {
3279 StringView DimensionNumber = parseNumber();
3280 if (!consumeIf('_'))
3281 return nullptr;
3282 if (consumeIf('p'))
3283 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003284 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003285 if (ElemType == nullptr)
3286 return nullptr;
3287 return make<VectorType>(ElemType, DimensionNumber);
3288 }
3289
3290 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003291 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003292 if (!DimExpr)
3293 return nullptr;
3294 if (!consumeIf('_'))
3295 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003296 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003297 if (!ElemType)
3298 return nullptr;
3299 return make<VectorType>(ElemType, DimExpr);
3300 }
Pavel Labathba825192018-10-16 14:29:14 +00003301 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003302 if (!ElemType)
3303 return nullptr;
3304 return make<VectorType>(ElemType, StringView());
3305}
3306
3307// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3308// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003309template <typename Derived, typename Alloc>
3310Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003311 if (!consumeIf('D'))
3312 return nullptr;
3313 if (!consumeIf('t') && !consumeIf('T'))
3314 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003315 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003316 if (E == nullptr)
3317 return nullptr;
3318 if (!consumeIf('E'))
3319 return nullptr;
3320 return make<EnclosingExpr>("decltype(", E, ")");
3321}
3322
3323// <array-type> ::= A <positive dimension number> _ <element type>
3324// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003325template <typename Derived, typename Alloc>
3326Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003327 if (!consumeIf('A'))
3328 return nullptr;
3329
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003330 NodeOrString Dimension;
3331
Richard Smithc20d1442018-08-20 20:14:49 +00003332 if (std::isdigit(look())) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003333 Dimension = parseNumber();
Richard Smithc20d1442018-08-20 20:14:49 +00003334 if (!consumeIf('_'))
3335 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003336 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003337 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003338 if (DimExpr == nullptr)
3339 return nullptr;
3340 if (!consumeIf('_'))
3341 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003342 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003343 }
3344
Pavel Labathba825192018-10-16 14:29:14 +00003345 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003346 if (Ty == nullptr)
3347 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003348 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003349}
3350
3351// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003352template <typename Derived, typename Alloc>
3353Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003354 if (!consumeIf('M'))
3355 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003356 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003357 if (ClassType == nullptr)
3358 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003359 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003360 if (MemberType == nullptr)
3361 return nullptr;
3362 return make<PointerToMemberType>(ClassType, MemberType);
3363}
3364
3365// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3366// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3367// ::= Tu <name> # dependent elaborated type specifier using 'union'
3368// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003369template <typename Derived, typename Alloc>
3370Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003371 StringView ElabSpef;
3372 if (consumeIf("Ts"))
3373 ElabSpef = "struct";
3374 else if (consumeIf("Tu"))
3375 ElabSpef = "union";
3376 else if (consumeIf("Te"))
3377 ElabSpef = "enum";
3378
Pavel Labathba825192018-10-16 14:29:14 +00003379 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003380 if (Name == nullptr)
3381 return nullptr;
3382
3383 if (!ElabSpef.empty())
3384 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3385
3386 return Name;
3387}
3388
3389// <qualified-type> ::= <qualifiers> <type>
3390// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3391// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003392template <typename Derived, typename Alloc>
3393Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003394 if (consumeIf('U')) {
3395 StringView Qual = parseBareSourceName();
3396 if (Qual.empty())
3397 return nullptr;
3398
3399 // FIXME parse the optional <template-args> here!
3400
3401 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3402 if (Qual.startsWith("objcproto")) {
3403 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3404 StringView Proto;
3405 {
3406 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3407 SaveLast(Last, ProtoSourceName.end());
3408 Proto = parseBareSourceName();
3409 }
3410 if (Proto.empty())
3411 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003412 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003413 if (Child == nullptr)
3414 return nullptr;
3415 return make<ObjCProtoName>(Child, Proto);
3416 }
3417
Pavel Labathba825192018-10-16 14:29:14 +00003418 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003419 if (Child == nullptr)
3420 return nullptr;
3421 return make<VendorExtQualType>(Child, Qual);
3422 }
3423
3424 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003425 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003426 if (Ty == nullptr)
3427 return nullptr;
3428 if (Quals != QualNone)
3429 Ty = make<QualType>(Ty, Quals);
3430 return Ty;
3431}
3432
3433// <type> ::= <builtin-type>
3434// ::= <qualified-type>
3435// ::= <function-type>
3436// ::= <class-enum-type>
3437// ::= <array-type>
3438// ::= <pointer-to-member-type>
3439// ::= <template-param>
3440// ::= <template-template-param> <template-args>
3441// ::= <decltype>
3442// ::= P <type> # pointer
3443// ::= R <type> # l-value reference
3444// ::= O <type> # r-value reference (C++11)
3445// ::= C <type> # complex pair (C99)
3446// ::= G <type> # imaginary (C99)
3447// ::= <substitution> # See Compression below
3448// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3449// extension ::= <vector-type> # <vector-type> starts with Dv
3450//
3451// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3452// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003453template <typename Derived, typename Alloc>
3454Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003455 Node *Result = nullptr;
3456
Richard Smithc20d1442018-08-20 20:14:49 +00003457 switch (look()) {
3458 // ::= <qualified-type>
3459 case 'r':
3460 case 'V':
3461 case 'K': {
3462 unsigned AfterQuals = 0;
3463 if (look(AfterQuals) == 'r') ++AfterQuals;
3464 if (look(AfterQuals) == 'V') ++AfterQuals;
3465 if (look(AfterQuals) == 'K') ++AfterQuals;
3466
3467 if (look(AfterQuals) == 'F' ||
3468 (look(AfterQuals) == 'D' &&
3469 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3470 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003471 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003472 break;
3473 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003474 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003475 }
3476 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003477 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003478 break;
3479 }
3480 // <builtin-type> ::= v # void
3481 case 'v':
3482 ++First;
3483 return make<NameType>("void");
3484 // ::= w # wchar_t
3485 case 'w':
3486 ++First;
3487 return make<NameType>("wchar_t");
3488 // ::= b # bool
3489 case 'b':
3490 ++First;
3491 return make<NameType>("bool");
3492 // ::= c # char
3493 case 'c':
3494 ++First;
3495 return make<NameType>("char");
3496 // ::= a # signed char
3497 case 'a':
3498 ++First;
3499 return make<NameType>("signed char");
3500 // ::= h # unsigned char
3501 case 'h':
3502 ++First;
3503 return make<NameType>("unsigned char");
3504 // ::= s # short
3505 case 's':
3506 ++First;
3507 return make<NameType>("short");
3508 // ::= t # unsigned short
3509 case 't':
3510 ++First;
3511 return make<NameType>("unsigned short");
3512 // ::= i # int
3513 case 'i':
3514 ++First;
3515 return make<NameType>("int");
3516 // ::= j # unsigned int
3517 case 'j':
3518 ++First;
3519 return make<NameType>("unsigned int");
3520 // ::= l # long
3521 case 'l':
3522 ++First;
3523 return make<NameType>("long");
3524 // ::= m # unsigned long
3525 case 'm':
3526 ++First;
3527 return make<NameType>("unsigned long");
3528 // ::= x # long long, __int64
3529 case 'x':
3530 ++First;
3531 return make<NameType>("long long");
3532 // ::= y # unsigned long long, __int64
3533 case 'y':
3534 ++First;
3535 return make<NameType>("unsigned long long");
3536 // ::= n # __int128
3537 case 'n':
3538 ++First;
3539 return make<NameType>("__int128");
3540 // ::= o # unsigned __int128
3541 case 'o':
3542 ++First;
3543 return make<NameType>("unsigned __int128");
3544 // ::= f # float
3545 case 'f':
3546 ++First;
3547 return make<NameType>("float");
3548 // ::= d # double
3549 case 'd':
3550 ++First;
3551 return make<NameType>("double");
3552 // ::= e # long double, __float80
3553 case 'e':
3554 ++First;
3555 return make<NameType>("long double");
3556 // ::= g # __float128
3557 case 'g':
3558 ++First;
3559 return make<NameType>("__float128");
3560 // ::= z # ellipsis
3561 case 'z':
3562 ++First;
3563 return make<NameType>("...");
3564
3565 // <builtin-type> ::= u <source-name> # vendor extended type
3566 case 'u': {
3567 ++First;
3568 StringView Res = parseBareSourceName();
3569 if (Res.empty())
3570 return nullptr;
3571 return make<NameType>(Res);
3572 }
3573 case 'D':
3574 switch (look(1)) {
3575 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3576 case 'd':
3577 First += 2;
3578 return make<NameType>("decimal64");
3579 // ::= De # IEEE 754r decimal floating point (128 bits)
3580 case 'e':
3581 First += 2;
3582 return make<NameType>("decimal128");
3583 // ::= Df # IEEE 754r decimal floating point (32 bits)
3584 case 'f':
3585 First += 2;
3586 return make<NameType>("decimal32");
3587 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3588 case 'h':
3589 First += 2;
3590 return make<NameType>("decimal16");
3591 // ::= Di # char32_t
3592 case 'i':
3593 First += 2;
3594 return make<NameType>("char32_t");
3595 // ::= Ds # char16_t
3596 case 's':
3597 First += 2;
3598 return make<NameType>("char16_t");
3599 // ::= Da # auto (in dependent new-expressions)
3600 case 'a':
3601 First += 2;
3602 return make<NameType>("auto");
3603 // ::= Dc # decltype(auto)
3604 case 'c':
3605 First += 2;
3606 return make<NameType>("decltype(auto)");
3607 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3608 case 'n':
3609 First += 2;
3610 return make<NameType>("std::nullptr_t");
3611
3612 // ::= <decltype>
3613 case 't':
3614 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003615 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003616 break;
3617 }
3618 // extension ::= <vector-type> # <vector-type> starts with Dv
3619 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003620 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003621 break;
3622 }
3623 // ::= Dp <type> # pack expansion (C++0x)
3624 case 'p': {
3625 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003626 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003627 if (!Child)
3628 return nullptr;
3629 Result = make<ParameterPackExpansion>(Child);
3630 break;
3631 }
3632 // Exception specifier on a function type.
3633 case 'o':
3634 case 'O':
3635 case 'w':
3636 // Transaction safe function type.
3637 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003638 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003639 break;
3640 }
3641 break;
3642 // ::= <function-type>
3643 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003644 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003645 break;
3646 }
3647 // ::= <array-type>
3648 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003649 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003650 break;
3651 }
3652 // ::= <pointer-to-member-type>
3653 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003654 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003655 break;
3656 }
3657 // ::= <template-param>
3658 case 'T': {
3659 // This could be an elaborate type specifier on a <class-enum-type>.
3660 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00003661 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003662 break;
3663 }
3664
Pavel Labathba825192018-10-16 14:29:14 +00003665 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003666 if (Result == nullptr)
3667 return nullptr;
3668
3669 // Result could be either of:
3670 // <type> ::= <template-param>
3671 // <type> ::= <template-template-param> <template-args>
3672 //
3673 // <template-template-param> ::= <template-param>
3674 // ::= <substitution>
3675 //
3676 // If this is followed by some <template-args>, and we're permitted to
3677 // parse them, take the second production.
3678
3679 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003680 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003681 if (TA == nullptr)
3682 return nullptr;
3683 Result = make<NameWithTemplateArgs>(Result, TA);
3684 }
3685 break;
3686 }
3687 // ::= P <type> # pointer
3688 case 'P': {
3689 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003690 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003691 if (Ptr == nullptr)
3692 return nullptr;
3693 Result = make<PointerType>(Ptr);
3694 break;
3695 }
3696 // ::= R <type> # l-value reference
3697 case 'R': {
3698 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003699 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003700 if (Ref == nullptr)
3701 return nullptr;
3702 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
3703 break;
3704 }
3705 // ::= O <type> # r-value reference (C++11)
3706 case 'O': {
3707 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003708 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003709 if (Ref == nullptr)
3710 return nullptr;
3711 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
3712 break;
3713 }
3714 // ::= C <type> # complex pair (C99)
3715 case 'C': {
3716 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003717 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003718 if (P == nullptr)
3719 return nullptr;
3720 Result = make<PostfixQualifiedType>(P, " complex");
3721 break;
3722 }
3723 // ::= G <type> # imaginary (C99)
3724 case 'G': {
3725 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003726 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003727 if (P == nullptr)
3728 return P;
3729 Result = make<PostfixQualifiedType>(P, " imaginary");
3730 break;
3731 }
3732 // ::= <substitution> # See Compression below
3733 case 'S': {
3734 if (look(1) && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00003735 Node *Sub = getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003736 if (Sub == nullptr)
3737 return nullptr;
3738
3739 // Sub could be either of:
3740 // <type> ::= <substitution>
3741 // <type> ::= <template-template-param> <template-args>
3742 //
3743 // <template-template-param> ::= <template-param>
3744 // ::= <substitution>
3745 //
3746 // If this is followed by some <template-args>, and we're permitted to
3747 // parse them, take the second production.
3748
3749 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003750 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003751 if (TA == nullptr)
3752 return nullptr;
3753 Result = make<NameWithTemplateArgs>(Sub, TA);
3754 break;
3755 }
3756
3757 // If all we parsed was a substitution, don't re-insert into the
3758 // substitution table.
3759 return Sub;
3760 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003761 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003762 }
3763 // ::= <class-enum-type>
3764 default: {
Pavel Labathba825192018-10-16 14:29:14 +00003765 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003766 break;
3767 }
3768 }
3769
3770 // If we parsed a type, insert it into the substitution table. Note that all
3771 // <builtin-type>s and <substitution>s have already bailed out, because they
3772 // don't get substitutions.
3773 if (Result != nullptr)
3774 Subs.push_back(Result);
3775 return Result;
3776}
3777
Pavel Labathba825192018-10-16 14:29:14 +00003778template <typename Derived, typename Alloc>
3779Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) {
3780 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003781 if (E == nullptr)
3782 return nullptr;
3783 return make<PrefixExpr>(Kind, E);
3784}
3785
Pavel Labathba825192018-10-16 14:29:14 +00003786template <typename Derived, typename Alloc>
3787Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) {
3788 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003789 if (LHS == nullptr)
3790 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003791 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003792 if (RHS == nullptr)
3793 return nullptr;
3794 return make<BinaryExpr>(LHS, Kind, RHS);
3795}
3796
Pavel Labathba825192018-10-16 14:29:14 +00003797template <typename Derived, typename Alloc>
3798Node *
3799AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00003800 StringView Tmp = parseNumber(true);
3801 if (!Tmp.empty() && consumeIf('E'))
3802 return make<IntegerLiteral>(Lit, Tmp);
3803 return nullptr;
3804}
3805
3806// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00003807template <typename Alloc, typename Derived>
3808Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00003809 Qualifiers CVR = QualNone;
3810 if (consumeIf('r'))
3811 CVR |= QualRestrict;
3812 if (consumeIf('V'))
3813 CVR |= QualVolatile;
3814 if (consumeIf('K'))
3815 CVR |= QualConst;
3816 return CVR;
3817}
3818
3819// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
3820// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
3821// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
3822// ::= 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 +00003823template <typename Derived, typename Alloc>
3824Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00003825 if (consumeIf("fp")) {
3826 parseCVQualifiers();
3827 StringView Num = parseNumber();
3828 if (!consumeIf('_'))
3829 return nullptr;
3830 return make<FunctionParam>(Num);
3831 }
3832 if (consumeIf("fL")) {
3833 if (parseNumber().empty())
3834 return nullptr;
3835 if (!consumeIf('p'))
3836 return nullptr;
3837 parseCVQualifiers();
3838 StringView Num = parseNumber();
3839 if (!consumeIf('_'))
3840 return nullptr;
3841 return make<FunctionParam>(Num);
3842 }
3843 return nullptr;
3844}
3845
3846// [gs] nw <expression>* _ <type> E # new (expr-list) type
3847// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
3848// [gs] na <expression>* _ <type> E # new[] (expr-list) type
3849// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
3850// <initializer> ::= pi <expression>* E # parenthesized initialization
Pavel Labathba825192018-10-16 14:29:14 +00003851template <typename Derived, typename Alloc>
3852Node *AbstractManglingParser<Derived, Alloc>::parseNewExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00003853 bool Global = consumeIf("gs");
3854 bool IsArray = look(1) == 'a';
3855 if (!consumeIf("nw") && !consumeIf("na"))
3856 return nullptr;
3857 size_t Exprs = Names.size();
3858 while (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003859 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003860 if (Ex == nullptr)
3861 return nullptr;
3862 Names.push_back(Ex);
3863 }
3864 NodeArray ExprList = popTrailingNodeArray(Exprs);
Pavel Labathba825192018-10-16 14:29:14 +00003865 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003866 if (Ty == nullptr)
3867 return Ty;
3868 if (consumeIf("pi")) {
3869 size_t InitsBegin = Names.size();
3870 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003871 Node *Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003872 if (Init == nullptr)
3873 return Init;
3874 Names.push_back(Init);
3875 }
3876 NodeArray Inits = popTrailingNodeArray(InitsBegin);
3877 return make<NewExpr>(ExprList, Ty, Inits, Global, IsArray);
3878 } else if (!consumeIf('E'))
3879 return nullptr;
3880 return make<NewExpr>(ExprList, Ty, NodeArray(), Global, IsArray);
3881}
3882
3883// cv <type> <expression> # conversion with one argument
3884// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00003885template <typename Derived, typename Alloc>
3886Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00003887 if (!consumeIf("cv"))
3888 return nullptr;
3889 Node *Ty;
3890 {
3891 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00003892 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003893 }
3894
3895 if (Ty == nullptr)
3896 return nullptr;
3897
3898 if (consumeIf('_')) {
3899 size_t ExprsBegin = Names.size();
3900 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003901 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003902 if (E == nullptr)
3903 return E;
3904 Names.push_back(E);
3905 }
3906 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
3907 return make<ConversionExpr>(Ty, Exprs);
3908 }
3909
Pavel Labathba825192018-10-16 14:29:14 +00003910 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00003911 if (E[0] == nullptr)
3912 return nullptr;
3913 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
3914}
3915
3916// <expr-primary> ::= L <type> <value number> E # integer literal
3917// ::= L <type> <value float> E # floating literal
3918// ::= L <string type> E # string literal
3919// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
3920// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
3921// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00003922template <typename Derived, typename Alloc>
3923Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00003924 if (!consumeIf('L'))
3925 return nullptr;
3926 switch (look()) {
3927 case 'w':
3928 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003929 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003930 case 'b':
3931 if (consumeIf("b0E"))
3932 return make<BoolExpr>(0);
3933 if (consumeIf("b1E"))
3934 return make<BoolExpr>(1);
3935 return nullptr;
3936 case 'c':
3937 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003938 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00003939 case 'a':
3940 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003941 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00003942 case 'h':
3943 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003944 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00003945 case 's':
3946 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003947 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00003948 case 't':
3949 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003950 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00003951 case 'i':
3952 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003953 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00003954 case 'j':
3955 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003956 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00003957 case 'l':
3958 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003959 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00003960 case 'm':
3961 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003962 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00003963 case 'x':
3964 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003965 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00003966 case 'y':
3967 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003968 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00003969 case 'n':
3970 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003971 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00003972 case 'o':
3973 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003974 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00003975 case 'f':
3976 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003977 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00003978 case 'd':
3979 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003980 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00003981 case 'e':
3982 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003983 return getDerived().template parseFloatingLiteral<long double>();
Richard Smithc20d1442018-08-20 20:14:49 +00003984 case '_':
3985 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00003986 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00003987 if (R != nullptr && consumeIf('E'))
3988 return R;
3989 }
3990 return nullptr;
3991 case 'T':
3992 // Invalid mangled name per
3993 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
3994 return nullptr;
3995 default: {
3996 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00003997 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003998 if (T == nullptr)
3999 return nullptr;
4000 StringView N = parseNumber();
4001 if (!N.empty()) {
4002 if (!consumeIf('E'))
4003 return nullptr;
4004 return make<IntegerCastExpr>(T, N);
4005 }
4006 if (consumeIf('E'))
4007 return T;
4008 return nullptr;
4009 }
4010 }
4011}
4012
4013// <braced-expression> ::= <expression>
4014// ::= di <field source-name> <braced-expression> # .name = expr
4015// ::= dx <index expression> <braced-expression> # [expr] = expr
4016// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004017template <typename Derived, typename Alloc>
4018Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004019 if (look() == 'd') {
4020 switch (look(1)) {
4021 case 'i': {
4022 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004023 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004024 if (Field == nullptr)
4025 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004026 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004027 if (Init == nullptr)
4028 return nullptr;
4029 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4030 }
4031 case 'x': {
4032 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004033 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004034 if (Index == nullptr)
4035 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004036 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004037 if (Init == nullptr)
4038 return nullptr;
4039 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4040 }
4041 case 'X': {
4042 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004043 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004044 if (RangeBegin == nullptr)
4045 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004046 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004047 if (RangeEnd == nullptr)
4048 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004049 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004050 if (Init == nullptr)
4051 return nullptr;
4052 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4053 }
4054 }
4055 }
Pavel Labathba825192018-10-16 14:29:14 +00004056 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004057}
4058
4059// (not yet in the spec)
4060// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4061// ::= fR <binary-operator-name> <expression> <expression>
4062// ::= fl <binary-operator-name> <expression>
4063// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004064template <typename Derived, typename Alloc>
4065Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004066 if (!consumeIf('f'))
4067 return nullptr;
4068
4069 char FoldKind = look();
4070 bool IsLeftFold, HasInitializer;
4071 HasInitializer = FoldKind == 'L' || FoldKind == 'R';
4072 if (FoldKind == 'l' || FoldKind == 'L')
4073 IsLeftFold = true;
4074 else if (FoldKind == 'r' || FoldKind == 'R')
4075 IsLeftFold = false;
4076 else
4077 return nullptr;
4078 ++First;
4079
4080 // FIXME: This map is duplicated in parseOperatorName and parseExpr.
4081 StringView OperatorName;
4082 if (consumeIf("aa")) OperatorName = "&&";
4083 else if (consumeIf("an")) OperatorName = "&";
4084 else if (consumeIf("aN")) OperatorName = "&=";
4085 else if (consumeIf("aS")) OperatorName = "=";
4086 else if (consumeIf("cm")) OperatorName = ",";
4087 else if (consumeIf("ds")) OperatorName = ".*";
4088 else if (consumeIf("dv")) OperatorName = "/";
4089 else if (consumeIf("dV")) OperatorName = "/=";
4090 else if (consumeIf("eo")) OperatorName = "^";
4091 else if (consumeIf("eO")) OperatorName = "^=";
4092 else if (consumeIf("eq")) OperatorName = "==";
4093 else if (consumeIf("ge")) OperatorName = ">=";
4094 else if (consumeIf("gt")) OperatorName = ">";
4095 else if (consumeIf("le")) OperatorName = "<=";
4096 else if (consumeIf("ls")) OperatorName = "<<";
4097 else if (consumeIf("lS")) OperatorName = "<<=";
4098 else if (consumeIf("lt")) OperatorName = "<";
4099 else if (consumeIf("mi")) OperatorName = "-";
4100 else if (consumeIf("mI")) OperatorName = "-=";
4101 else if (consumeIf("ml")) OperatorName = "*";
4102 else if (consumeIf("mL")) OperatorName = "*=";
4103 else if (consumeIf("ne")) OperatorName = "!=";
4104 else if (consumeIf("oo")) OperatorName = "||";
4105 else if (consumeIf("or")) OperatorName = "|";
4106 else if (consumeIf("oR")) OperatorName = "|=";
4107 else if (consumeIf("pl")) OperatorName = "+";
4108 else if (consumeIf("pL")) OperatorName = "+=";
4109 else if (consumeIf("rm")) OperatorName = "%";
4110 else if (consumeIf("rM")) OperatorName = "%=";
4111 else if (consumeIf("rs")) OperatorName = ">>";
4112 else if (consumeIf("rS")) OperatorName = ">>=";
4113 else return nullptr;
4114
Pavel Labathba825192018-10-16 14:29:14 +00004115 Node *Pack = getDerived().parseExpr(), *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004116 if (Pack == nullptr)
4117 return nullptr;
4118 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004119 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004120 if (Init == nullptr)
4121 return nullptr;
4122 }
4123
4124 if (IsLeftFold && Init)
4125 std::swap(Pack, Init);
4126
4127 return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
4128}
4129
4130// <expression> ::= <unary operator-name> <expression>
4131// ::= <binary operator-name> <expression> <expression>
4132// ::= <ternary operator-name> <expression> <expression> <expression>
4133// ::= cl <expression>+ E # call
4134// ::= cv <type> <expression> # conversion with one argument
4135// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4136// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4137// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4138// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4139// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4140// ::= [gs] dl <expression> # delete expression
4141// ::= [gs] da <expression> # delete[] expression
4142// ::= pp_ <expression> # prefix ++
4143// ::= mm_ <expression> # prefix --
4144// ::= ti <type> # typeid (type)
4145// ::= te <expression> # typeid (expression)
4146// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4147// ::= sc <type> <expression> # static_cast<type> (expression)
4148// ::= cc <type> <expression> # const_cast<type> (expression)
4149// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4150// ::= st <type> # sizeof (a type)
4151// ::= sz <expression> # sizeof (an expression)
4152// ::= at <type> # alignof (a type)
4153// ::= az <expression> # alignof (an expression)
4154// ::= nx <expression> # noexcept (expression)
4155// ::= <template-param>
4156// ::= <function-param>
4157// ::= dt <expression> <unresolved-name> # expr.name
4158// ::= pt <expression> <unresolved-name> # expr->name
4159// ::= ds <expression> <expression> # expr.*expr
4160// ::= sZ <template-param> # size of a parameter pack
4161// ::= sZ <function-param> # size of a function parameter pack
4162// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4163// ::= sp <expression> # pack expansion
4164// ::= tw <expression> # throw expression
4165// ::= tr # throw with no operand (rethrow)
4166// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4167// # freestanding dependent name (e.g., T::x),
4168// # objectless nonstatic member reference
4169// ::= fL <binary-operator-name> <expression> <expression>
4170// ::= fR <binary-operator-name> <expression> <expression>
4171// ::= fl <binary-operator-name> <expression>
4172// ::= fr <binary-operator-name> <expression>
4173// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004174template <typename Derived, typename Alloc>
4175Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004176 bool Global = consumeIf("gs");
4177 if (numLeft() < 2)
4178 return nullptr;
4179
4180 switch (*First) {
4181 case 'L':
Pavel Labathba825192018-10-16 14:29:14 +00004182 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00004183 case 'T':
Pavel Labathba825192018-10-16 14:29:14 +00004184 return getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004185 case 'f': {
4186 // Disambiguate a fold expression from a <function-param>.
4187 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
Pavel Labathba825192018-10-16 14:29:14 +00004188 return getDerived().parseFunctionParam();
4189 return getDerived().parseFoldExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004190 }
4191 case 'a':
4192 switch (First[1]) {
4193 case 'a':
4194 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004195 return getDerived().parseBinaryExpr("&&");
Richard Smithc20d1442018-08-20 20:14:49 +00004196 case 'd':
4197 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004198 return getDerived().parsePrefixExpr("&");
Richard Smithc20d1442018-08-20 20:14:49 +00004199 case 'n':
4200 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004201 return getDerived().parseBinaryExpr("&");
Richard Smithc20d1442018-08-20 20:14:49 +00004202 case 'N':
4203 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004204 return getDerived().parseBinaryExpr("&=");
Richard Smithc20d1442018-08-20 20:14:49 +00004205 case 'S':
4206 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004207 return getDerived().parseBinaryExpr("=");
Richard Smithc20d1442018-08-20 20:14:49 +00004208 case 't': {
4209 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004210 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004211 if (Ty == nullptr)
4212 return nullptr;
4213 return make<EnclosingExpr>("alignof (", Ty, ")");
4214 }
4215 case 'z': {
4216 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004217 Node *Ty = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004218 if (Ty == nullptr)
4219 return nullptr;
4220 return make<EnclosingExpr>("alignof (", Ty, ")");
4221 }
4222 }
4223 return nullptr;
4224 case 'c':
4225 switch (First[1]) {
4226 // cc <type> <expression> # const_cast<type>(expression)
4227 case 'c': {
4228 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004229 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004230 if (Ty == nullptr)
4231 return Ty;
Pavel Labathba825192018-10-16 14:29:14 +00004232 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004233 if (Ex == nullptr)
4234 return Ex;
4235 return make<CastExpr>("const_cast", Ty, Ex);
4236 }
4237 // cl <expression>+ E # call
4238 case 'l': {
4239 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004240 Node *Callee = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004241 if (Callee == nullptr)
4242 return Callee;
4243 size_t ExprsBegin = Names.size();
4244 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004245 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004246 if (E == nullptr)
4247 return E;
4248 Names.push_back(E);
4249 }
4250 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin));
4251 }
4252 case 'm':
4253 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004254 return getDerived().parseBinaryExpr(",");
Richard Smithc20d1442018-08-20 20:14:49 +00004255 case 'o':
4256 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004257 return getDerived().parsePrefixExpr("~");
Richard Smithc20d1442018-08-20 20:14:49 +00004258 case 'v':
Pavel Labathba825192018-10-16 14:29:14 +00004259 return getDerived().parseConversionExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004260 }
4261 return nullptr;
4262 case 'd':
4263 switch (First[1]) {
4264 case 'a': {
4265 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004266 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004267 if (Ex == nullptr)
4268 return Ex;
4269 return make<DeleteExpr>(Ex, Global, /*is_array=*/true);
4270 }
4271 case 'c': {
4272 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004273 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004274 if (T == nullptr)
4275 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004276 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004277 if (Ex == nullptr)
4278 return Ex;
4279 return make<CastExpr>("dynamic_cast", T, Ex);
4280 }
4281 case 'e':
4282 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004283 return getDerived().parsePrefixExpr("*");
Richard Smithc20d1442018-08-20 20:14:49 +00004284 case 'l': {
4285 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004286 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004287 if (E == nullptr)
4288 return E;
4289 return make<DeleteExpr>(E, Global, /*is_array=*/false);
4290 }
4291 case 'n':
Pavel Labathba825192018-10-16 14:29:14 +00004292 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004293 case 's': {
4294 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004295 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004296 if (LHS == nullptr)
4297 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004298 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004299 if (RHS == nullptr)
4300 return nullptr;
4301 return make<MemberExpr>(LHS, ".*", RHS);
4302 }
4303 case 't': {
4304 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004305 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004306 if (LHS == nullptr)
4307 return LHS;
Pavel Labathba825192018-10-16 14:29:14 +00004308 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004309 if (RHS == nullptr)
4310 return nullptr;
4311 return make<MemberExpr>(LHS, ".", RHS);
4312 }
4313 case 'v':
4314 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004315 return getDerived().parseBinaryExpr("/");
Richard Smithc20d1442018-08-20 20:14:49 +00004316 case 'V':
4317 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004318 return getDerived().parseBinaryExpr("/=");
Richard Smithc20d1442018-08-20 20:14:49 +00004319 }
4320 return nullptr;
4321 case 'e':
4322 switch (First[1]) {
4323 case 'o':
4324 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004325 return getDerived().parseBinaryExpr("^");
Richard Smithc20d1442018-08-20 20:14:49 +00004326 case 'O':
4327 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004328 return getDerived().parseBinaryExpr("^=");
Richard Smithc20d1442018-08-20 20:14:49 +00004329 case 'q':
4330 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004331 return getDerived().parseBinaryExpr("==");
Richard Smithc20d1442018-08-20 20:14:49 +00004332 }
4333 return nullptr;
4334 case 'g':
4335 switch (First[1]) {
4336 case 'e':
4337 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004338 return getDerived().parseBinaryExpr(">=");
Richard Smithc20d1442018-08-20 20:14:49 +00004339 case 't':
4340 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004341 return getDerived().parseBinaryExpr(">");
Richard Smithc20d1442018-08-20 20:14:49 +00004342 }
4343 return nullptr;
4344 case 'i':
4345 switch (First[1]) {
4346 case 'x': {
4347 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004348 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004349 if (Base == nullptr)
4350 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004351 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004352 if (Index == nullptr)
4353 return Index;
4354 return make<ArraySubscriptExpr>(Base, Index);
4355 }
4356 case 'l': {
4357 First += 2;
4358 size_t InitsBegin = Names.size();
4359 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004360 Node *E = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004361 if (E == nullptr)
4362 return nullptr;
4363 Names.push_back(E);
4364 }
4365 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4366 }
4367 }
4368 return nullptr;
4369 case 'l':
4370 switch (First[1]) {
4371 case 'e':
4372 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004373 return getDerived().parseBinaryExpr("<=");
Richard Smithc20d1442018-08-20 20:14:49 +00004374 case 's':
4375 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004376 return getDerived().parseBinaryExpr("<<");
Richard Smithc20d1442018-08-20 20:14:49 +00004377 case 'S':
4378 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004379 return getDerived().parseBinaryExpr("<<=");
Richard Smithc20d1442018-08-20 20:14:49 +00004380 case 't':
4381 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004382 return getDerived().parseBinaryExpr("<");
Richard Smithc20d1442018-08-20 20:14:49 +00004383 }
4384 return nullptr;
4385 case 'm':
4386 switch (First[1]) {
4387 case 'i':
4388 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004389 return getDerived().parseBinaryExpr("-");
Richard Smithc20d1442018-08-20 20:14:49 +00004390 case 'I':
4391 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004392 return getDerived().parseBinaryExpr("-=");
Richard Smithc20d1442018-08-20 20:14:49 +00004393 case 'l':
4394 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004395 return getDerived().parseBinaryExpr("*");
Richard Smithc20d1442018-08-20 20:14:49 +00004396 case 'L':
4397 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004398 return getDerived().parseBinaryExpr("*=");
Richard Smithc20d1442018-08-20 20:14:49 +00004399 case 'm':
4400 First += 2;
4401 if (consumeIf('_'))
Pavel Labathba825192018-10-16 14:29:14 +00004402 return getDerived().parsePrefixExpr("--");
4403 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004404 if (Ex == nullptr)
4405 return nullptr;
4406 return make<PostfixExpr>(Ex, "--");
4407 }
4408 return nullptr;
4409 case 'n':
4410 switch (First[1]) {
4411 case 'a':
4412 case 'w':
Pavel Labathba825192018-10-16 14:29:14 +00004413 return getDerived().parseNewExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004414 case 'e':
4415 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004416 return getDerived().parseBinaryExpr("!=");
Richard Smithc20d1442018-08-20 20:14:49 +00004417 case 'g':
4418 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004419 return getDerived().parsePrefixExpr("-");
Richard Smithc20d1442018-08-20 20:14:49 +00004420 case 't':
4421 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004422 return getDerived().parsePrefixExpr("!");
Richard Smithc20d1442018-08-20 20:14:49 +00004423 case 'x':
4424 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004425 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004426 if (Ex == nullptr)
4427 return Ex;
4428 return make<EnclosingExpr>("noexcept (", Ex, ")");
4429 }
4430 return nullptr;
4431 case 'o':
4432 switch (First[1]) {
4433 case 'n':
Pavel Labathba825192018-10-16 14:29:14 +00004434 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004435 case 'o':
4436 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004437 return getDerived().parseBinaryExpr("||");
Richard Smithc20d1442018-08-20 20:14:49 +00004438 case 'r':
4439 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004440 return getDerived().parseBinaryExpr("|");
Richard Smithc20d1442018-08-20 20:14:49 +00004441 case 'R':
4442 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004443 return getDerived().parseBinaryExpr("|=");
Richard Smithc20d1442018-08-20 20:14:49 +00004444 }
4445 return nullptr;
4446 case 'p':
4447 switch (First[1]) {
4448 case 'm':
4449 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004450 return getDerived().parseBinaryExpr("->*");
Richard Smithc20d1442018-08-20 20:14:49 +00004451 case 'l':
4452 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004453 return getDerived().parseBinaryExpr("+");
Richard Smithc20d1442018-08-20 20:14:49 +00004454 case 'L':
4455 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004456 return getDerived().parseBinaryExpr("+=");
Richard Smithc20d1442018-08-20 20:14:49 +00004457 case 'p': {
4458 First += 2;
4459 if (consumeIf('_'))
Pavel Labathba825192018-10-16 14:29:14 +00004460 return getDerived().parsePrefixExpr("++");
4461 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004462 if (Ex == nullptr)
4463 return Ex;
4464 return make<PostfixExpr>(Ex, "++");
4465 }
4466 case 's':
4467 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004468 return getDerived().parsePrefixExpr("+");
Richard Smithc20d1442018-08-20 20:14:49 +00004469 case 't': {
4470 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004471 Node *L = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004472 if (L == nullptr)
4473 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004474 Node *R = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004475 if (R == nullptr)
4476 return nullptr;
4477 return make<MemberExpr>(L, "->", R);
4478 }
4479 }
4480 return nullptr;
4481 case 'q':
4482 if (First[1] == 'u') {
4483 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004484 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004485 if (Cond == nullptr)
4486 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004487 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004488 if (LHS == nullptr)
4489 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004490 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004491 if (RHS == nullptr)
4492 return nullptr;
4493 return make<ConditionalExpr>(Cond, LHS, RHS);
4494 }
4495 return nullptr;
4496 case 'r':
4497 switch (First[1]) {
4498 case 'c': {
4499 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004500 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004501 if (T == nullptr)
4502 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004503 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004504 if (Ex == nullptr)
4505 return Ex;
4506 return make<CastExpr>("reinterpret_cast", T, Ex);
4507 }
4508 case 'm':
4509 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004510 return getDerived().parseBinaryExpr("%");
Richard Smithc20d1442018-08-20 20:14:49 +00004511 case 'M':
4512 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004513 return getDerived().parseBinaryExpr("%=");
Richard Smithc20d1442018-08-20 20:14:49 +00004514 case 's':
4515 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004516 return getDerived().parseBinaryExpr(">>");
Richard Smithc20d1442018-08-20 20:14:49 +00004517 case 'S':
4518 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004519 return getDerived().parseBinaryExpr(">>=");
Richard Smithc20d1442018-08-20 20:14:49 +00004520 }
4521 return nullptr;
4522 case 's':
4523 switch (First[1]) {
4524 case 'c': {
4525 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004526 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004527 if (T == nullptr)
4528 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004529 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004530 if (Ex == nullptr)
4531 return Ex;
4532 return make<CastExpr>("static_cast", T, Ex);
4533 }
4534 case 'p': {
4535 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004536 Node *Child = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004537 if (Child == nullptr)
4538 return nullptr;
4539 return make<ParameterPackExpansion>(Child);
4540 }
4541 case 'r':
Pavel Labathba825192018-10-16 14:29:14 +00004542 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004543 case 't': {
4544 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004545 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004546 if (Ty == nullptr)
4547 return Ty;
4548 return make<EnclosingExpr>("sizeof (", Ty, ")");
4549 }
4550 case 'z': {
4551 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004552 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004553 if (Ex == nullptr)
4554 return Ex;
4555 return make<EnclosingExpr>("sizeof (", Ex, ")");
4556 }
4557 case 'Z':
4558 First += 2;
4559 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00004560 Node *R = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004561 if (R == nullptr)
4562 return nullptr;
4563 return make<SizeofParamPackExpr>(R);
4564 } else if (look() == 'f') {
Pavel Labathba825192018-10-16 14:29:14 +00004565 Node *FP = getDerived().parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004566 if (FP == nullptr)
4567 return nullptr;
4568 return make<EnclosingExpr>("sizeof... (", FP, ")");
4569 }
4570 return nullptr;
4571 case 'P': {
4572 First += 2;
4573 size_t ArgsBegin = Names.size();
4574 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004575 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00004576 if (Arg == nullptr)
4577 return nullptr;
4578 Names.push_back(Arg);
4579 }
Richard Smithb485b352018-08-24 23:30:26 +00004580 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4581 if (!Pack)
4582 return nullptr;
4583 return make<EnclosingExpr>("sizeof... (", Pack, ")");
Richard Smithc20d1442018-08-20 20:14:49 +00004584 }
4585 }
4586 return nullptr;
4587 case 't':
4588 switch (First[1]) {
4589 case 'e': {
4590 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004591 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004592 if (Ex == nullptr)
4593 return Ex;
4594 return make<EnclosingExpr>("typeid (", Ex, ")");
4595 }
4596 case 'i': {
4597 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004598 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004599 if (Ty == nullptr)
4600 return Ty;
4601 return make<EnclosingExpr>("typeid (", Ty, ")");
4602 }
4603 case 'l': {
4604 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004605 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004606 if (Ty == nullptr)
4607 return nullptr;
4608 size_t InitsBegin = Names.size();
4609 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004610 Node *E = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004611 if (E == nullptr)
4612 return nullptr;
4613 Names.push_back(E);
4614 }
4615 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4616 }
4617 case 'r':
4618 First += 2;
4619 return make<NameType>("throw");
4620 case 'w': {
4621 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004622 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004623 if (Ex == nullptr)
4624 return nullptr;
4625 return make<ThrowExpr>(Ex);
4626 }
4627 }
4628 return nullptr;
4629 case '1':
4630 case '2':
4631 case '3':
4632 case '4':
4633 case '5':
4634 case '6':
4635 case '7':
4636 case '8':
4637 case '9':
Pavel Labathba825192018-10-16 14:29:14 +00004638 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004639 }
4640 return nullptr;
4641}
4642
4643// <call-offset> ::= h <nv-offset> _
4644// ::= v <v-offset> _
4645//
4646// <nv-offset> ::= <offset number>
4647// # non-virtual base override
4648//
4649// <v-offset> ::= <offset number> _ <virtual offset number>
4650// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004651template <typename Alloc, typename Derived>
4652bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004653 // Just scan through the call offset, we never add this information into the
4654 // output.
4655 if (consumeIf('h'))
4656 return parseNumber(true).empty() || !consumeIf('_');
4657 if (consumeIf('v'))
4658 return parseNumber(true).empty() || !consumeIf('_') ||
4659 parseNumber(true).empty() || !consumeIf('_');
4660 return true;
4661}
4662
4663// <special-name> ::= TV <type> # virtual table
4664// ::= TT <type> # VTT structure (construction vtable index)
4665// ::= TI <type> # typeinfo structure
4666// ::= TS <type> # typeinfo name (null-terminated byte string)
4667// ::= Tc <call-offset> <call-offset> <base encoding>
4668// # base is the nominal target function of thunk
4669// # first call-offset is 'this' adjustment
4670// # second call-offset is result adjustment
4671// ::= T <call-offset> <base encoding>
4672// # base is the nominal target function of thunk
4673// ::= GV <object name> # Guard variable for one-time initialization
4674// # No <type>
4675// ::= TW <object name> # Thread-local wrapper
4676// ::= TH <object name> # Thread-local initialization
4677// ::= GR <object name> _ # First temporary
4678// ::= GR <object name> <seq-id> _ # Subsequent temporaries
4679// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4680// extension ::= GR <object name> # reference temporary for object
Pavel Labathba825192018-10-16 14:29:14 +00004681template <typename Derived, typename Alloc>
4682Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004683 switch (look()) {
4684 case 'T':
4685 switch (look(1)) {
4686 // TV <type> # virtual table
4687 case 'V': {
4688 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004689 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004690 if (Ty == nullptr)
4691 return nullptr;
4692 return make<SpecialName>("vtable for ", Ty);
4693 }
4694 // TT <type> # VTT structure (construction vtable index)
4695 case 'T': {
4696 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004697 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004698 if (Ty == nullptr)
4699 return nullptr;
4700 return make<SpecialName>("VTT for ", Ty);
4701 }
4702 // TI <type> # typeinfo structure
4703 case 'I': {
4704 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004705 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004706 if (Ty == nullptr)
4707 return nullptr;
4708 return make<SpecialName>("typeinfo for ", Ty);
4709 }
4710 // TS <type> # typeinfo name (null-terminated byte string)
4711 case 'S': {
4712 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004713 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004714 if (Ty == nullptr)
4715 return nullptr;
4716 return make<SpecialName>("typeinfo name for ", Ty);
4717 }
4718 // Tc <call-offset> <call-offset> <base encoding>
4719 case 'c': {
4720 First += 2;
4721 if (parseCallOffset() || parseCallOffset())
4722 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004723 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004724 if (Encoding == nullptr)
4725 return nullptr;
4726 return make<SpecialName>("covariant return thunk to ", Encoding);
4727 }
4728 // extension ::= TC <first type> <number> _ <second type>
4729 // # construction vtable for second-in-first
4730 case 'C': {
4731 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004732 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004733 if (FirstType == nullptr)
4734 return nullptr;
4735 if (parseNumber(true).empty() || !consumeIf('_'))
4736 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004737 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004738 if (SecondType == nullptr)
4739 return nullptr;
4740 return make<CtorVtableSpecialName>(SecondType, FirstType);
4741 }
4742 // TW <object name> # Thread-local wrapper
4743 case 'W': {
4744 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004745 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004746 if (Name == nullptr)
4747 return nullptr;
4748 return make<SpecialName>("thread-local wrapper routine for ", Name);
4749 }
4750 // TH <object name> # Thread-local initialization
4751 case 'H': {
4752 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004753 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004754 if (Name == nullptr)
4755 return nullptr;
4756 return make<SpecialName>("thread-local initialization routine for ", Name);
4757 }
4758 // T <call-offset> <base encoding>
4759 default: {
4760 ++First;
4761 bool IsVirt = look() == 'v';
4762 if (parseCallOffset())
4763 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004764 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004765 if (BaseEncoding == nullptr)
4766 return nullptr;
4767 if (IsVirt)
4768 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4769 else
4770 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4771 }
4772 }
4773 case 'G':
4774 switch (look(1)) {
4775 // GV <object name> # Guard variable for one-time initialization
4776 case 'V': {
4777 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004778 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004779 if (Name == nullptr)
4780 return nullptr;
4781 return make<SpecialName>("guard variable for ", Name);
4782 }
4783 // GR <object name> # reference temporary for object
4784 // GR <object name> _ # First temporary
4785 // GR <object name> <seq-id> _ # Subsequent temporaries
4786 case 'R': {
4787 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004788 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004789 if (Name == nullptr)
4790 return nullptr;
4791 size_t Count;
4792 bool ParsedSeqId = !parseSeqId(&Count);
4793 if (!consumeIf('_') && ParsedSeqId)
4794 return nullptr;
4795 return make<SpecialName>("reference temporary for ", Name);
4796 }
4797 }
4798 }
4799 return nullptr;
4800}
4801
4802// <encoding> ::= <function name> <bare-function-type>
4803// ::= <data name>
4804// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00004805template <typename Derived, typename Alloc>
4806Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithc20d1442018-08-20 20:14:49 +00004807 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00004808 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00004809
4810 auto IsEndOfEncoding = [&] {
4811 // The set of chars that can potentially follow an <encoding> (none of which
4812 // can start a <type>). Enumerating these allows us to avoid speculative
4813 // parsing.
4814 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
4815 };
4816
4817 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00004818 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00004819 if (Name == nullptr)
4820 return nullptr;
4821
4822 if (resolveForwardTemplateRefs(NameInfo))
4823 return nullptr;
4824
4825 if (IsEndOfEncoding())
4826 return Name;
4827
4828 Node *Attrs = nullptr;
4829 if (consumeIf("Ua9enable_ifI")) {
4830 size_t BeforeArgs = Names.size();
4831 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004832 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00004833 if (Arg == nullptr)
4834 return nullptr;
4835 Names.push_back(Arg);
4836 }
4837 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00004838 if (!Attrs)
4839 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004840 }
4841
4842 Node *ReturnType = nullptr;
4843 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00004844 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004845 if (ReturnType == nullptr)
4846 return nullptr;
4847 }
4848
4849 if (consumeIf('v'))
4850 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
4851 Attrs, NameInfo.CVQualifiers,
4852 NameInfo.ReferenceQualifier);
4853
4854 size_t ParamsBegin = Names.size();
4855 do {
Pavel Labathba825192018-10-16 14:29:14 +00004856 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004857 if (Ty == nullptr)
4858 return nullptr;
4859 Names.push_back(Ty);
4860 } while (!IsEndOfEncoding());
4861
4862 return make<FunctionEncoding>(ReturnType, Name,
4863 popTrailingNodeArray(ParamsBegin),
4864 Attrs, NameInfo.CVQualifiers,
4865 NameInfo.ReferenceQualifier);
4866}
4867
4868template <class Float>
4869struct FloatData;
4870
4871template <>
4872struct FloatData<float>
4873{
4874 static const size_t mangled_size = 8;
4875 static const size_t max_demangled_size = 24;
4876 static constexpr const char* spec = "%af";
4877};
4878
4879template <>
4880struct FloatData<double>
4881{
4882 static const size_t mangled_size = 16;
4883 static const size_t max_demangled_size = 32;
4884 static constexpr const char* spec = "%a";
4885};
4886
4887template <>
4888struct FloatData<long double>
4889{
4890#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
4891 defined(__wasm__)
4892 static const size_t mangled_size = 32;
4893#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
4894 static const size_t mangled_size = 16;
4895#else
4896 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
4897#endif
4898 static const size_t max_demangled_size = 40;
4899 static constexpr const char *spec = "%LaL";
4900};
4901
Pavel Labathba825192018-10-16 14:29:14 +00004902template <typename Alloc, typename Derived>
4903template <class Float>
4904Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00004905 const size_t N = FloatData<Float>::mangled_size;
4906 if (numLeft() <= N)
4907 return nullptr;
4908 StringView Data(First, First + N);
4909 for (char C : Data)
4910 if (!std::isxdigit(C))
4911 return nullptr;
4912 First += N;
4913 if (!consumeIf('E'))
4914 return nullptr;
4915 return make<FloatLiteralImpl<Float>>(Data);
4916}
4917
4918// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00004919template <typename Alloc, typename Derived>
4920bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00004921 if (!(look() >= '0' && look() <= '9') &&
4922 !(look() >= 'A' && look() <= 'Z'))
4923 return true;
4924
4925 size_t Id = 0;
4926 while (true) {
4927 if (look() >= '0' && look() <= '9') {
4928 Id *= 36;
4929 Id += static_cast<size_t>(look() - '0');
4930 } else if (look() >= 'A' && look() <= 'Z') {
4931 Id *= 36;
4932 Id += static_cast<size_t>(look() - 'A') + 10;
4933 } else {
4934 *Out = Id;
4935 return false;
4936 }
4937 ++First;
4938 }
4939}
4940
4941// <substitution> ::= S <seq-id> _
4942// ::= S_
4943// <substitution> ::= Sa # ::std::allocator
4944// <substitution> ::= Sb # ::std::basic_string
4945// <substitution> ::= Ss # ::std::basic_string < char,
4946// ::std::char_traits<char>,
4947// ::std::allocator<char> >
4948// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
4949// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
4950// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Pavel Labathba825192018-10-16 14:29:14 +00004951template <typename Derived, typename Alloc>
4952Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00004953 if (!consumeIf('S'))
4954 return nullptr;
4955
4956 if (std::islower(look())) {
4957 Node *SpecialSub;
4958 switch (look()) {
4959 case 'a':
4960 ++First;
4961 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::allocator);
4962 break;
4963 case 'b':
4964 ++First;
4965 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::basic_string);
4966 break;
4967 case 's':
4968 ++First;
4969 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::string);
4970 break;
4971 case 'i':
4972 ++First;
4973 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::istream);
4974 break;
4975 case 'o':
4976 ++First;
4977 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::ostream);
4978 break;
4979 case 'd':
4980 ++First;
4981 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::iostream);
4982 break;
4983 default:
4984 return nullptr;
4985 }
Richard Smithb485b352018-08-24 23:30:26 +00004986 if (!SpecialSub)
4987 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004988 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
4989 // has ABI tags, the tags are appended to the substitution; the result is a
4990 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00004991 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00004992 if (WithTags != SpecialSub) {
4993 Subs.push_back(WithTags);
4994 SpecialSub = WithTags;
4995 }
4996 return SpecialSub;
4997 }
4998
4999 // ::= S_
5000 if (consumeIf('_')) {
5001 if (Subs.empty())
5002 return nullptr;
5003 return Subs[0];
5004 }
5005
5006 // ::= S <seq-id> _
5007 size_t Index = 0;
5008 if (parseSeqId(&Index))
5009 return nullptr;
5010 ++Index;
5011 if (!consumeIf('_') || Index >= Subs.size())
5012 return nullptr;
5013 return Subs[Index];
5014}
5015
5016// <template-param> ::= T_ # first template parameter
5017// ::= T <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005018template <typename Derived, typename Alloc>
5019Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005020 if (!consumeIf('T'))
5021 return nullptr;
5022
5023 size_t Index = 0;
5024 if (!consumeIf('_')) {
5025 if (parsePositiveInteger(&Index))
5026 return nullptr;
5027 ++Index;
5028 if (!consumeIf('_'))
5029 return nullptr;
5030 }
5031
5032 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter list
5033 // are mangled as the corresponding artificial template type parameter.
5034 if (ParsingLambdaParams)
5035 return make<NameType>("auto");
5036
5037 // If we're in a context where this <template-param> refers to a
5038 // <template-arg> further ahead in the mangled name (currently just conversion
5039 // operator types), then we should only look it up in the right context.
5040 if (PermitForwardTemplateReferences) {
Richard Smithb485b352018-08-24 23:30:26 +00005041 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5042 if (!ForwardRef)
5043 return nullptr;
5044 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5045 ForwardTemplateRefs.push_back(
5046 static_cast<ForwardTemplateReference *>(ForwardRef));
5047 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005048 }
5049
5050 if (Index >= TemplateParams.size())
5051 return nullptr;
5052 return TemplateParams[Index];
5053}
5054
5055// <template-arg> ::= <type> # type or template
5056// ::= X <expression> E # expression
5057// ::= <expr-primary> # simple expressions
5058// ::= J <template-arg>* E # argument pack
5059// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005060template <typename Derived, typename Alloc>
5061Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005062 switch (look()) {
5063 case 'X': {
5064 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005065 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005066 if (Arg == nullptr || !consumeIf('E'))
5067 return nullptr;
5068 return Arg;
5069 }
5070 case 'J': {
5071 ++First;
5072 size_t ArgsBegin = Names.size();
5073 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005074 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005075 if (Arg == nullptr)
5076 return nullptr;
5077 Names.push_back(Arg);
5078 }
5079 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5080 return make<TemplateArgumentPack>(Args);
5081 }
5082 case 'L': {
5083 // ::= LZ <encoding> E # extension
5084 if (look(1) == 'Z') {
5085 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005086 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005087 if (Arg == nullptr || !consumeIf('E'))
5088 return nullptr;
5089 return Arg;
5090 }
5091 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005092 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005093 }
5094 default:
Pavel Labathba825192018-10-16 14:29:14 +00005095 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005096 }
5097}
5098
5099// <template-args> ::= I <template-arg>* E
5100// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005101template <typename Derived, typename Alloc>
5102Node *
5103AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005104 if (!consumeIf('I'))
5105 return nullptr;
5106
5107 // <template-params> refer to the innermost <template-args>. Clear out any
5108 // outer args that we may have inserted into TemplateParams.
5109 if (TagTemplates)
5110 TemplateParams.clear();
5111
5112 size_t ArgsBegin = Names.size();
5113 while (!consumeIf('E')) {
5114 if (TagTemplates) {
5115 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005116 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005117 TemplateParams = std::move(OldParams);
5118 if (Arg == nullptr)
5119 return nullptr;
5120 Names.push_back(Arg);
5121 Node *TableEntry = Arg;
5122 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5123 TableEntry = make<ParameterPack>(
5124 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005125 if (!TableEntry)
5126 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005127 }
5128 TemplateParams.push_back(TableEntry);
5129 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005130 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005131 if (Arg == nullptr)
5132 return nullptr;
5133 Names.push_back(Arg);
5134 }
5135 }
5136 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5137}
5138
5139// <mangled-name> ::= _Z <encoding>
5140// ::= <type>
5141// extension ::= ___Z <encoding> _block_invoke
5142// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5143// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005144template <typename Derived, typename Alloc>
5145Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005146 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005147 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005148 if (Encoding == nullptr)
5149 return nullptr;
5150 if (look() == '.') {
5151 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5152 First = Last;
5153 }
5154 if (numLeft() != 0)
5155 return nullptr;
5156 return Encoding;
5157 }
5158
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005159 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005160 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005161 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5162 return nullptr;
5163 bool RequireNumber = consumeIf('_');
5164 if (parseNumber().empty() && RequireNumber)
5165 return nullptr;
5166 if (look() == '.')
5167 First = Last;
5168 if (numLeft() != 0)
5169 return nullptr;
5170 return make<SpecialName>("invocation function for block in ", Encoding);
5171 }
5172
Pavel Labathba825192018-10-16 14:29:14 +00005173 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005174 if (numLeft() != 0)
5175 return nullptr;
5176 return Ty;
5177}
5178
Pavel Labathba825192018-10-16 14:29:14 +00005179template <typename Alloc>
5180struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5181 using AbstractManglingParser<ManglingParser<Alloc>,
5182 Alloc>::AbstractManglingParser;
5183};
5184
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005185DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005186
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005187#endif // DEMANGLE_ITANIUMDEMANGLE_H