blob: f35c062cd6d58346b21115c4e7298f9577b536c5 [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 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002483 if (consumeIf("Ub")) {
2484 (void)parseNumber();
2485 if (!consumeIf('_'))
2486 return nullptr;
2487 return make<NameType>("'block-literal'");
2488 }
Richard Smithc20d1442018-08-20 20:14:49 +00002489 return nullptr;
2490}
2491
2492// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002493template <typename Derived, typename Alloc>
2494Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002495 size_t Length = 0;
2496 if (parsePositiveInteger(&Length))
2497 return nullptr;
2498 if (numLeft() < Length || Length == 0)
2499 return nullptr;
2500 StringView Name(First, First + Length);
2501 First += Length;
2502 if (Name.startsWith("_GLOBAL__N"))
2503 return make<NameType>("(anonymous namespace)");
2504 return make<NameType>(Name);
2505}
2506
2507// <operator-name> ::= aa # &&
2508// ::= ad # & (unary)
2509// ::= an # &
2510// ::= aN # &=
2511// ::= aS # =
2512// ::= cl # ()
2513// ::= cm # ,
2514// ::= co # ~
2515// ::= cv <type> # (cast)
2516// ::= da # delete[]
2517// ::= de # * (unary)
2518// ::= dl # delete
2519// ::= dv # /
2520// ::= dV # /=
2521// ::= eo # ^
2522// ::= eO # ^=
2523// ::= eq # ==
2524// ::= ge # >=
2525// ::= gt # >
2526// ::= ix # []
2527// ::= le # <=
2528// ::= li <source-name> # operator ""
2529// ::= ls # <<
2530// ::= lS # <<=
2531// ::= lt # <
2532// ::= mi # -
2533// ::= mI # -=
2534// ::= ml # *
2535// ::= mL # *=
2536// ::= mm # -- (postfix in <expression> context)
2537// ::= na # new[]
2538// ::= ne # !=
2539// ::= ng # - (unary)
2540// ::= nt # !
2541// ::= nw # new
2542// ::= oo # ||
2543// ::= or # |
2544// ::= oR # |=
2545// ::= pm # ->*
2546// ::= pl # +
2547// ::= pL # +=
2548// ::= pp # ++ (postfix in <expression> context)
2549// ::= ps # + (unary)
2550// ::= pt # ->
2551// ::= qu # ?
2552// ::= rm # %
2553// ::= rM # %=
2554// ::= rs # >>
2555// ::= rS # >>=
2556// ::= ss # <=> C++2a
2557// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00002558template <typename Derived, typename Alloc>
2559Node *
2560AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002561 switch (look()) {
2562 case 'a':
2563 switch (look(1)) {
2564 case 'a':
2565 First += 2;
2566 return make<NameType>("operator&&");
2567 case 'd':
2568 case 'n':
2569 First += 2;
2570 return make<NameType>("operator&");
2571 case 'N':
2572 First += 2;
2573 return make<NameType>("operator&=");
2574 case 'S':
2575 First += 2;
2576 return make<NameType>("operator=");
2577 }
2578 return nullptr;
2579 case 'c':
2580 switch (look(1)) {
2581 case 'l':
2582 First += 2;
2583 return make<NameType>("operator()");
2584 case 'm':
2585 First += 2;
2586 return make<NameType>("operator,");
2587 case 'o':
2588 First += 2;
2589 return make<NameType>("operator~");
2590 // ::= cv <type> # (cast)
2591 case 'v': {
2592 First += 2;
2593 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
2594 // If we're parsing an encoding, State != nullptr and the conversion
2595 // operators' <type> could have a <template-param> that refers to some
2596 // <template-arg>s further ahead in the mangled name.
2597 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
2598 PermitForwardTemplateReferences ||
2599 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00002600 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002601 if (Ty == nullptr)
2602 return nullptr;
2603 if (State) State->CtorDtorConversion = true;
2604 return make<ConversionOperatorType>(Ty);
2605 }
2606 }
2607 return nullptr;
2608 case 'd':
2609 switch (look(1)) {
2610 case 'a':
2611 First += 2;
2612 return make<NameType>("operator delete[]");
2613 case 'e':
2614 First += 2;
2615 return make<NameType>("operator*");
2616 case 'l':
2617 First += 2;
2618 return make<NameType>("operator delete");
2619 case 'v':
2620 First += 2;
2621 return make<NameType>("operator/");
2622 case 'V':
2623 First += 2;
2624 return make<NameType>("operator/=");
2625 }
2626 return nullptr;
2627 case 'e':
2628 switch (look(1)) {
2629 case 'o':
2630 First += 2;
2631 return make<NameType>("operator^");
2632 case 'O':
2633 First += 2;
2634 return make<NameType>("operator^=");
2635 case 'q':
2636 First += 2;
2637 return make<NameType>("operator==");
2638 }
2639 return nullptr;
2640 case 'g':
2641 switch (look(1)) {
2642 case 'e':
2643 First += 2;
2644 return make<NameType>("operator>=");
2645 case 't':
2646 First += 2;
2647 return make<NameType>("operator>");
2648 }
2649 return nullptr;
2650 case 'i':
2651 if (look(1) == 'x') {
2652 First += 2;
2653 return make<NameType>("operator[]");
2654 }
2655 return nullptr;
2656 case 'l':
2657 switch (look(1)) {
2658 case 'e':
2659 First += 2;
2660 return make<NameType>("operator<=");
2661 // ::= li <source-name> # operator ""
2662 case 'i': {
2663 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00002664 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002665 if (SN == nullptr)
2666 return nullptr;
2667 return make<LiteralOperator>(SN);
2668 }
2669 case 's':
2670 First += 2;
2671 return make<NameType>("operator<<");
2672 case 'S':
2673 First += 2;
2674 return make<NameType>("operator<<=");
2675 case 't':
2676 First += 2;
2677 return make<NameType>("operator<");
2678 }
2679 return nullptr;
2680 case 'm':
2681 switch (look(1)) {
2682 case 'i':
2683 First += 2;
2684 return make<NameType>("operator-");
2685 case 'I':
2686 First += 2;
2687 return make<NameType>("operator-=");
2688 case 'l':
2689 First += 2;
2690 return make<NameType>("operator*");
2691 case 'L':
2692 First += 2;
2693 return make<NameType>("operator*=");
2694 case 'm':
2695 First += 2;
2696 return make<NameType>("operator--");
2697 }
2698 return nullptr;
2699 case 'n':
2700 switch (look(1)) {
2701 case 'a':
2702 First += 2;
2703 return make<NameType>("operator new[]");
2704 case 'e':
2705 First += 2;
2706 return make<NameType>("operator!=");
2707 case 'g':
2708 First += 2;
2709 return make<NameType>("operator-");
2710 case 't':
2711 First += 2;
2712 return make<NameType>("operator!");
2713 case 'w':
2714 First += 2;
2715 return make<NameType>("operator new");
2716 }
2717 return nullptr;
2718 case 'o':
2719 switch (look(1)) {
2720 case 'o':
2721 First += 2;
2722 return make<NameType>("operator||");
2723 case 'r':
2724 First += 2;
2725 return make<NameType>("operator|");
2726 case 'R':
2727 First += 2;
2728 return make<NameType>("operator|=");
2729 }
2730 return nullptr;
2731 case 'p':
2732 switch (look(1)) {
2733 case 'm':
2734 First += 2;
2735 return make<NameType>("operator->*");
2736 case 'l':
2737 First += 2;
2738 return make<NameType>("operator+");
2739 case 'L':
2740 First += 2;
2741 return make<NameType>("operator+=");
2742 case 'p':
2743 First += 2;
2744 return make<NameType>("operator++");
2745 case 's':
2746 First += 2;
2747 return make<NameType>("operator+");
2748 case 't':
2749 First += 2;
2750 return make<NameType>("operator->");
2751 }
2752 return nullptr;
2753 case 'q':
2754 if (look(1) == 'u') {
2755 First += 2;
2756 return make<NameType>("operator?");
2757 }
2758 return nullptr;
2759 case 'r':
2760 switch (look(1)) {
2761 case 'm':
2762 First += 2;
2763 return make<NameType>("operator%");
2764 case 'M':
2765 First += 2;
2766 return make<NameType>("operator%=");
2767 case 's':
2768 First += 2;
2769 return make<NameType>("operator>>");
2770 case 'S':
2771 First += 2;
2772 return make<NameType>("operator>>=");
2773 }
2774 return nullptr;
2775 case 's':
2776 if (look(1) == 's') {
2777 First += 2;
2778 return make<NameType>("operator<=>");
2779 }
2780 return nullptr;
2781 // ::= v <digit> <source-name> # vendor extended operator
2782 case 'v':
2783 if (std::isdigit(look(1))) {
2784 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00002785 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002786 if (SN == nullptr)
2787 return nullptr;
2788 return make<ConversionOperatorType>(SN);
2789 }
2790 return nullptr;
2791 }
2792 return nullptr;
2793}
2794
2795// <ctor-dtor-name> ::= C1 # complete object constructor
2796// ::= C2 # base object constructor
2797// ::= C3 # complete object allocating constructor
2798// extension ::= C5 # ?
2799// ::= D0 # deleting destructor
2800// ::= D1 # complete object destructor
2801// ::= D2 # base object destructor
2802// extension ::= D5 # ?
Pavel Labathba825192018-10-16 14:29:14 +00002803template <typename Derived, typename Alloc>
2804Node *
2805AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
2806 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002807 if (SoFar->getKind() == Node::KSpecialSubstitution) {
2808 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
2809 switch (SSK) {
2810 case SpecialSubKind::string:
2811 case SpecialSubKind::istream:
2812 case SpecialSubKind::ostream:
2813 case SpecialSubKind::iostream:
2814 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00002815 if (!SoFar)
2816 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00002817 break;
Richard Smithc20d1442018-08-20 20:14:49 +00002818 default:
2819 break;
2820 }
2821 }
2822
2823 if (consumeIf('C')) {
2824 bool IsInherited = consumeIf('I');
2825 if (look() != '1' && look() != '2' && look() != '3' && look() != '5')
2826 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002827 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00002828 ++First;
2829 if (State) State->CtorDtorConversion = true;
2830 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00002831 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00002832 return nullptr;
2833 }
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002834 return make<CtorDtorName>(SoFar, false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00002835 }
2836
2837 if (look() == 'D' &&
2838 (look(1) == '0' || look(1) == '1' || look(1) == '2' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002839 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00002840 First += 2;
2841 if (State) State->CtorDtorConversion = true;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00002842 return make<CtorDtorName>(SoFar, true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00002843 }
2844
2845 return nullptr;
2846}
2847
2848// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
2849// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
2850//
2851// <prefix> ::= <prefix> <unqualified-name>
2852// ::= <template-prefix> <template-args>
2853// ::= <template-param>
2854// ::= <decltype>
2855// ::= # empty
2856// ::= <substitution>
2857// ::= <prefix> <data-member-prefix>
2858// extension ::= L
2859//
2860// <data-member-prefix> := <member source-name> [<template-args>] M
2861//
2862// <template-prefix> ::= <prefix> <template unqualified-name>
2863// ::= <template-param>
2864// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002865template <typename Derived, typename Alloc>
2866Node *
2867AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002868 if (!consumeIf('N'))
2869 return nullptr;
2870
2871 Qualifiers CVTmp = parseCVQualifiers();
2872 if (State) State->CVQualifiers = CVTmp;
2873
2874 if (consumeIf('O')) {
2875 if (State) State->ReferenceQualifier = FrefQualRValue;
2876 } else if (consumeIf('R')) {
2877 if (State) State->ReferenceQualifier = FrefQualLValue;
2878 } else
2879 if (State) State->ReferenceQualifier = FrefQualNone;
2880
2881 Node *SoFar = nullptr;
2882 auto PushComponent = [&](Node *Comp) {
Richard Smithb485b352018-08-24 23:30:26 +00002883 if (!Comp) return false;
Richard Smithc20d1442018-08-20 20:14:49 +00002884 if (SoFar) SoFar = make<NestedName>(SoFar, Comp);
2885 else SoFar = Comp;
2886 if (State) State->EndsWithTemplateArgs = false;
Richard Smithb485b352018-08-24 23:30:26 +00002887 return SoFar != nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002888 };
2889
Richard Smithb485b352018-08-24 23:30:26 +00002890 if (consumeIf("St")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002891 SoFar = make<NameType>("std");
Richard Smithb485b352018-08-24 23:30:26 +00002892 if (!SoFar)
2893 return nullptr;
2894 }
Richard Smithc20d1442018-08-20 20:14:49 +00002895
2896 while (!consumeIf('E')) {
2897 consumeIf('L'); // extension
2898
2899 // <data-member-prefix> := <member source-name> [<template-args>] M
2900 if (consumeIf('M')) {
2901 if (SoFar == nullptr)
2902 return nullptr;
2903 continue;
2904 }
2905
2906 // ::= <template-param>
2907 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00002908 if (!PushComponent(getDerived().parseTemplateParam()))
Richard Smithc20d1442018-08-20 20:14:49 +00002909 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002910 Subs.push_back(SoFar);
2911 continue;
2912 }
2913
2914 // ::= <template-prefix> <template-args>
2915 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00002916 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002917 if (TA == nullptr || SoFar == nullptr)
2918 return nullptr;
2919 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00002920 if (!SoFar)
2921 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002922 if (State) State->EndsWithTemplateArgs = true;
2923 Subs.push_back(SoFar);
2924 continue;
2925 }
2926
2927 // ::= <decltype>
2928 if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
Pavel Labathba825192018-10-16 14:29:14 +00002929 if (!PushComponent(getDerived().parseDecltype()))
Richard Smithc20d1442018-08-20 20:14:49 +00002930 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002931 Subs.push_back(SoFar);
2932 continue;
2933 }
2934
2935 // ::= <substitution>
2936 if (look() == 'S' && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00002937 Node *S = getDerived().parseSubstitution();
Richard Smithb485b352018-08-24 23:30:26 +00002938 if (!PushComponent(S))
Richard Smithc20d1442018-08-20 20:14:49 +00002939 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002940 if (SoFar != S)
2941 Subs.push_back(S);
2942 continue;
2943 }
2944
2945 // Parse an <unqualified-name> thats actually a <ctor-dtor-name>.
2946 if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {
2947 if (SoFar == nullptr)
2948 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002949 if (!PushComponent(getDerived().parseCtorDtorName(SoFar, State)))
Richard Smithc20d1442018-08-20 20:14:49 +00002950 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002951 SoFar = getDerived().parseAbiTags(SoFar);
Richard Smithc20d1442018-08-20 20:14:49 +00002952 if (SoFar == nullptr)
2953 return nullptr;
2954 Subs.push_back(SoFar);
2955 continue;
2956 }
2957
2958 // ::= <prefix> <unqualified-name>
Pavel Labathba825192018-10-16 14:29:14 +00002959 if (!PushComponent(getDerived().parseUnqualifiedName(State)))
Richard Smithc20d1442018-08-20 20:14:49 +00002960 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002961 Subs.push_back(SoFar);
2962 }
2963
2964 if (SoFar == nullptr || Subs.empty())
2965 return nullptr;
2966
2967 Subs.pop_back();
2968 return SoFar;
2969}
2970
2971// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00002972template <typename Derived, typename Alloc>
2973Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
2974 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002975 if (SN == nullptr)
2976 return nullptr;
2977 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00002978 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00002979 if (TA == nullptr)
2980 return nullptr;
2981 return make<NameWithTemplateArgs>(SN, TA);
2982 }
2983 return SN;
2984}
2985
2986// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
2987// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00002988template <typename Derived, typename Alloc>
2989Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00002990 Node *Result;
2991 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00002992 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00002993 else
Pavel Labathba825192018-10-16 14:29:14 +00002994 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00002995 if (Result == nullptr)
2996 return nullptr;
2997 return make<DtorName>(Result);
2998}
2999
3000// <unresolved-type> ::= <template-param>
3001// ::= <decltype>
3002// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003003template <typename Derived, typename Alloc>
3004Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003005 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003006 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003007 if (TP == nullptr)
3008 return nullptr;
3009 Subs.push_back(TP);
3010 return TP;
3011 }
3012 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003013 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003014 if (DT == nullptr)
3015 return nullptr;
3016 Subs.push_back(DT);
3017 return DT;
3018 }
Pavel Labathba825192018-10-16 14:29:14 +00003019 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003020}
3021
3022// <base-unresolved-name> ::= <simple-id> # unresolved name
3023// extension ::= <operator-name> # unresolved operator-function-id
3024// extension ::= <operator-name> <template-args> # unresolved operator template-id
3025// ::= on <operator-name> # unresolved operator-function-id
3026// ::= on <operator-name> <template-args> # unresolved operator template-id
3027// ::= dn <destructor-name> # destructor or pseudo-destructor;
3028// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003029template <typename Derived, typename Alloc>
3030Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003031 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003032 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003033
3034 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003035 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003036
3037 consumeIf("on");
3038
Pavel Labathba825192018-10-16 14:29:14 +00003039 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003040 if (Oper == nullptr)
3041 return nullptr;
3042 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003043 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003044 if (TA == nullptr)
3045 return nullptr;
3046 return make<NameWithTemplateArgs>(Oper, TA);
3047 }
3048 return Oper;
3049}
3050
3051// <unresolved-name>
3052// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3053// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3054// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3055// # A::x, N::y, A<T>::z; "gs" means leading "::"
3056// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3057// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3058// # T::N::x /decltype(p)::N::x
3059// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3060//
3061// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003062template <typename Derived, typename Alloc>
3063Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003064 Node *SoFar = nullptr;
3065
3066 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3067 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3068 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003069 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003070 if (SoFar == nullptr)
3071 return nullptr;
3072
3073 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003074 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003075 if (TA == nullptr)
3076 return nullptr;
3077 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003078 if (!SoFar)
3079 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003080 }
3081
3082 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003083 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003084 if (Qual == nullptr)
3085 return nullptr;
3086 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003087 if (!SoFar)
3088 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003089 }
3090
Pavel Labathba825192018-10-16 14:29:14 +00003091 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003092 if (Base == nullptr)
3093 return nullptr;
3094 return make<QualifiedName>(SoFar, Base);
3095 }
3096
3097 bool Global = consumeIf("gs");
3098
3099 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3100 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003101 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003102 if (SoFar == nullptr)
3103 return nullptr;
3104 if (Global)
3105 SoFar = make<GlobalQualifiedName>(SoFar);
3106 return SoFar;
3107 }
3108
3109 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3110 if (std::isdigit(look())) {
3111 do {
Pavel Labathba825192018-10-16 14:29:14 +00003112 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003113 if (Qual == nullptr)
3114 return nullptr;
3115 if (SoFar)
3116 SoFar = make<QualifiedName>(SoFar, Qual);
3117 else if (Global)
3118 SoFar = make<GlobalQualifiedName>(Qual);
3119 else
3120 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003121 if (!SoFar)
3122 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003123 } while (!consumeIf('E'));
3124 }
3125 // sr <unresolved-type> <base-unresolved-name>
3126 // sr <unresolved-type> <template-args> <base-unresolved-name>
3127 else {
Pavel Labathba825192018-10-16 14:29:14 +00003128 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003129 if (SoFar == nullptr)
3130 return nullptr;
3131
3132 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003133 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003134 if (TA == nullptr)
3135 return nullptr;
3136 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003137 if (!SoFar)
3138 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003139 }
3140 }
3141
3142 assert(SoFar != nullptr);
3143
Pavel Labathba825192018-10-16 14:29:14 +00003144 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003145 if (Base == nullptr)
3146 return nullptr;
3147 return make<QualifiedName>(SoFar, Base);
3148}
3149
3150// <abi-tags> ::= <abi-tag> [<abi-tags>]
3151// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003152template <typename Derived, typename Alloc>
3153Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003154 while (consumeIf('B')) {
3155 StringView SN = parseBareSourceName();
3156 if (SN.empty())
3157 return nullptr;
3158 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003159 if (!N)
3160 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003161 }
3162 return N;
3163}
3164
3165// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003166template <typename Alloc, typename Derived>
3167StringView
3168AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003169 const char *Tmp = First;
3170 if (AllowNegative)
3171 consumeIf('n');
3172 if (numLeft() == 0 || !std::isdigit(*First))
3173 return StringView();
3174 while (numLeft() != 0 && std::isdigit(*First))
3175 ++First;
3176 return StringView(Tmp, First);
3177}
3178
3179// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003180template <typename Alloc, typename Derived>
3181bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003182 *Out = 0;
3183 if (look() < '0' || look() > '9')
3184 return true;
3185 while (look() >= '0' && look() <= '9') {
3186 *Out *= 10;
3187 *Out += static_cast<size_t>(consume() - '0');
3188 }
3189 return false;
3190}
3191
Pavel Labathba825192018-10-16 14:29:14 +00003192template <typename Alloc, typename Derived>
3193StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003194 size_t Int = 0;
3195 if (parsePositiveInteger(&Int) || numLeft() < Int)
3196 return StringView();
3197 StringView R(First, First + Int);
3198 First += Int;
3199 return R;
3200}
3201
3202// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3203//
3204// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3205// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3206// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3207//
3208// <ref-qualifier> ::= R # & ref-qualifier
3209// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003210template <typename Derived, typename Alloc>
3211Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003212 Qualifiers CVQuals = parseCVQualifiers();
3213
3214 Node *ExceptionSpec = nullptr;
3215 if (consumeIf("Do")) {
3216 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003217 if (!ExceptionSpec)
3218 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003219 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003220 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003221 if (E == nullptr || !consumeIf('E'))
3222 return nullptr;
3223 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003224 if (!ExceptionSpec)
3225 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003226 } else if (consumeIf("Dw")) {
3227 size_t SpecsBegin = Names.size();
3228 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003229 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003230 if (T == nullptr)
3231 return nullptr;
3232 Names.push_back(T);
3233 }
3234 ExceptionSpec =
3235 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003236 if (!ExceptionSpec)
3237 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003238 }
3239
3240 consumeIf("Dx"); // transaction safe
3241
3242 if (!consumeIf('F'))
3243 return nullptr;
3244 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003245 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003246 if (ReturnType == nullptr)
3247 return nullptr;
3248
3249 FunctionRefQual ReferenceQualifier = FrefQualNone;
3250 size_t ParamsBegin = Names.size();
3251 while (true) {
3252 if (consumeIf('E'))
3253 break;
3254 if (consumeIf('v'))
3255 continue;
3256 if (consumeIf("RE")) {
3257 ReferenceQualifier = FrefQualLValue;
3258 break;
3259 }
3260 if (consumeIf("OE")) {
3261 ReferenceQualifier = FrefQualRValue;
3262 break;
3263 }
Pavel Labathba825192018-10-16 14:29:14 +00003264 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003265 if (T == nullptr)
3266 return nullptr;
3267 Names.push_back(T);
3268 }
3269
3270 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3271 return make<FunctionType>(ReturnType, Params, CVQuals,
3272 ReferenceQualifier, ExceptionSpec);
3273}
3274
3275// extension:
3276// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3277// ::= Dv [<dimension expression>] _ <element type>
3278// <extended element type> ::= <element type>
3279// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003280template <typename Derived, typename Alloc>
3281Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003282 if (!consumeIf("Dv"))
3283 return nullptr;
3284 if (look() >= '1' && look() <= '9') {
3285 StringView DimensionNumber = parseNumber();
3286 if (!consumeIf('_'))
3287 return nullptr;
3288 if (consumeIf('p'))
3289 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003290 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003291 if (ElemType == nullptr)
3292 return nullptr;
3293 return make<VectorType>(ElemType, DimensionNumber);
3294 }
3295
3296 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003297 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003298 if (!DimExpr)
3299 return nullptr;
3300 if (!consumeIf('_'))
3301 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003302 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003303 if (!ElemType)
3304 return nullptr;
3305 return make<VectorType>(ElemType, DimExpr);
3306 }
Pavel Labathba825192018-10-16 14:29:14 +00003307 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003308 if (!ElemType)
3309 return nullptr;
3310 return make<VectorType>(ElemType, StringView());
3311}
3312
3313// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3314// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003315template <typename Derived, typename Alloc>
3316Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003317 if (!consumeIf('D'))
3318 return nullptr;
3319 if (!consumeIf('t') && !consumeIf('T'))
3320 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003321 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003322 if (E == nullptr)
3323 return nullptr;
3324 if (!consumeIf('E'))
3325 return nullptr;
3326 return make<EnclosingExpr>("decltype(", E, ")");
3327}
3328
3329// <array-type> ::= A <positive dimension number> _ <element type>
3330// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003331template <typename Derived, typename Alloc>
3332Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003333 if (!consumeIf('A'))
3334 return nullptr;
3335
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003336 NodeOrString Dimension;
3337
Richard Smithc20d1442018-08-20 20:14:49 +00003338 if (std::isdigit(look())) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003339 Dimension = parseNumber();
Richard Smithc20d1442018-08-20 20:14:49 +00003340 if (!consumeIf('_'))
3341 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003342 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003343 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003344 if (DimExpr == nullptr)
3345 return nullptr;
3346 if (!consumeIf('_'))
3347 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003348 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003349 }
3350
Pavel Labathba825192018-10-16 14:29:14 +00003351 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003352 if (Ty == nullptr)
3353 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003354 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003355}
3356
3357// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003358template <typename Derived, typename Alloc>
3359Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003360 if (!consumeIf('M'))
3361 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003362 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003363 if (ClassType == nullptr)
3364 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003365 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003366 if (MemberType == nullptr)
3367 return nullptr;
3368 return make<PointerToMemberType>(ClassType, MemberType);
3369}
3370
3371// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3372// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3373// ::= Tu <name> # dependent elaborated type specifier using 'union'
3374// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003375template <typename Derived, typename Alloc>
3376Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003377 StringView ElabSpef;
3378 if (consumeIf("Ts"))
3379 ElabSpef = "struct";
3380 else if (consumeIf("Tu"))
3381 ElabSpef = "union";
3382 else if (consumeIf("Te"))
3383 ElabSpef = "enum";
3384
Pavel Labathba825192018-10-16 14:29:14 +00003385 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003386 if (Name == nullptr)
3387 return nullptr;
3388
3389 if (!ElabSpef.empty())
3390 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3391
3392 return Name;
3393}
3394
3395// <qualified-type> ::= <qualifiers> <type>
3396// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3397// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003398template <typename Derived, typename Alloc>
3399Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003400 if (consumeIf('U')) {
3401 StringView Qual = parseBareSourceName();
3402 if (Qual.empty())
3403 return nullptr;
3404
3405 // FIXME parse the optional <template-args> here!
3406
3407 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3408 if (Qual.startsWith("objcproto")) {
3409 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3410 StringView Proto;
3411 {
3412 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3413 SaveLast(Last, ProtoSourceName.end());
3414 Proto = parseBareSourceName();
3415 }
3416 if (Proto.empty())
3417 return nullptr;
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<ObjCProtoName>(Child, Proto);
3422 }
3423
Pavel Labathba825192018-10-16 14:29:14 +00003424 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003425 if (Child == nullptr)
3426 return nullptr;
3427 return make<VendorExtQualType>(Child, Qual);
3428 }
3429
3430 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003431 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003432 if (Ty == nullptr)
3433 return nullptr;
3434 if (Quals != QualNone)
3435 Ty = make<QualType>(Ty, Quals);
3436 return Ty;
3437}
3438
3439// <type> ::= <builtin-type>
3440// ::= <qualified-type>
3441// ::= <function-type>
3442// ::= <class-enum-type>
3443// ::= <array-type>
3444// ::= <pointer-to-member-type>
3445// ::= <template-param>
3446// ::= <template-template-param> <template-args>
3447// ::= <decltype>
3448// ::= P <type> # pointer
3449// ::= R <type> # l-value reference
3450// ::= O <type> # r-value reference (C++11)
3451// ::= C <type> # complex pair (C99)
3452// ::= G <type> # imaginary (C99)
3453// ::= <substitution> # See Compression below
3454// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3455// extension ::= <vector-type> # <vector-type> starts with Dv
3456//
3457// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3458// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003459template <typename Derived, typename Alloc>
3460Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003461 Node *Result = nullptr;
3462
Richard Smithc20d1442018-08-20 20:14:49 +00003463 switch (look()) {
3464 // ::= <qualified-type>
3465 case 'r':
3466 case 'V':
3467 case 'K': {
3468 unsigned AfterQuals = 0;
3469 if (look(AfterQuals) == 'r') ++AfterQuals;
3470 if (look(AfterQuals) == 'V') ++AfterQuals;
3471 if (look(AfterQuals) == 'K') ++AfterQuals;
3472
3473 if (look(AfterQuals) == 'F' ||
3474 (look(AfterQuals) == 'D' &&
3475 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3476 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003477 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003478 break;
3479 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003480 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003481 }
3482 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003483 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003484 break;
3485 }
3486 // <builtin-type> ::= v # void
3487 case 'v':
3488 ++First;
3489 return make<NameType>("void");
3490 // ::= w # wchar_t
3491 case 'w':
3492 ++First;
3493 return make<NameType>("wchar_t");
3494 // ::= b # bool
3495 case 'b':
3496 ++First;
3497 return make<NameType>("bool");
3498 // ::= c # char
3499 case 'c':
3500 ++First;
3501 return make<NameType>("char");
3502 // ::= a # signed char
3503 case 'a':
3504 ++First;
3505 return make<NameType>("signed char");
3506 // ::= h # unsigned char
3507 case 'h':
3508 ++First;
3509 return make<NameType>("unsigned char");
3510 // ::= s # short
3511 case 's':
3512 ++First;
3513 return make<NameType>("short");
3514 // ::= t # unsigned short
3515 case 't':
3516 ++First;
3517 return make<NameType>("unsigned short");
3518 // ::= i # int
3519 case 'i':
3520 ++First;
3521 return make<NameType>("int");
3522 // ::= j # unsigned int
3523 case 'j':
3524 ++First;
3525 return make<NameType>("unsigned int");
3526 // ::= l # long
3527 case 'l':
3528 ++First;
3529 return make<NameType>("long");
3530 // ::= m # unsigned long
3531 case 'm':
3532 ++First;
3533 return make<NameType>("unsigned long");
3534 // ::= x # long long, __int64
3535 case 'x':
3536 ++First;
3537 return make<NameType>("long long");
3538 // ::= y # unsigned long long, __int64
3539 case 'y':
3540 ++First;
3541 return make<NameType>("unsigned long long");
3542 // ::= n # __int128
3543 case 'n':
3544 ++First;
3545 return make<NameType>("__int128");
3546 // ::= o # unsigned __int128
3547 case 'o':
3548 ++First;
3549 return make<NameType>("unsigned __int128");
3550 // ::= f # float
3551 case 'f':
3552 ++First;
3553 return make<NameType>("float");
3554 // ::= d # double
3555 case 'd':
3556 ++First;
3557 return make<NameType>("double");
3558 // ::= e # long double, __float80
3559 case 'e':
3560 ++First;
3561 return make<NameType>("long double");
3562 // ::= g # __float128
3563 case 'g':
3564 ++First;
3565 return make<NameType>("__float128");
3566 // ::= z # ellipsis
3567 case 'z':
3568 ++First;
3569 return make<NameType>("...");
3570
3571 // <builtin-type> ::= u <source-name> # vendor extended type
3572 case 'u': {
3573 ++First;
3574 StringView Res = parseBareSourceName();
3575 if (Res.empty())
3576 return nullptr;
3577 return make<NameType>(Res);
3578 }
3579 case 'D':
3580 switch (look(1)) {
3581 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3582 case 'd':
3583 First += 2;
3584 return make<NameType>("decimal64");
3585 // ::= De # IEEE 754r decimal floating point (128 bits)
3586 case 'e':
3587 First += 2;
3588 return make<NameType>("decimal128");
3589 // ::= Df # IEEE 754r decimal floating point (32 bits)
3590 case 'f':
3591 First += 2;
3592 return make<NameType>("decimal32");
3593 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3594 case 'h':
3595 First += 2;
3596 return make<NameType>("decimal16");
3597 // ::= Di # char32_t
3598 case 'i':
3599 First += 2;
3600 return make<NameType>("char32_t");
3601 // ::= Ds # char16_t
3602 case 's':
3603 First += 2;
3604 return make<NameType>("char16_t");
3605 // ::= Da # auto (in dependent new-expressions)
3606 case 'a':
3607 First += 2;
3608 return make<NameType>("auto");
3609 // ::= Dc # decltype(auto)
3610 case 'c':
3611 First += 2;
3612 return make<NameType>("decltype(auto)");
3613 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3614 case 'n':
3615 First += 2;
3616 return make<NameType>("std::nullptr_t");
3617
3618 // ::= <decltype>
3619 case 't':
3620 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003621 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003622 break;
3623 }
3624 // extension ::= <vector-type> # <vector-type> starts with Dv
3625 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003626 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003627 break;
3628 }
3629 // ::= Dp <type> # pack expansion (C++0x)
3630 case 'p': {
3631 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003632 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003633 if (!Child)
3634 return nullptr;
3635 Result = make<ParameterPackExpansion>(Child);
3636 break;
3637 }
3638 // Exception specifier on a function type.
3639 case 'o':
3640 case 'O':
3641 case 'w':
3642 // Transaction safe function type.
3643 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003644 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003645 break;
3646 }
3647 break;
3648 // ::= <function-type>
3649 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003650 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003651 break;
3652 }
3653 // ::= <array-type>
3654 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003655 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003656 break;
3657 }
3658 // ::= <pointer-to-member-type>
3659 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003660 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003661 break;
3662 }
3663 // ::= <template-param>
3664 case 'T': {
3665 // This could be an elaborate type specifier on a <class-enum-type>.
3666 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00003667 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003668 break;
3669 }
3670
Pavel Labathba825192018-10-16 14:29:14 +00003671 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003672 if (Result == nullptr)
3673 return nullptr;
3674
3675 // Result could be either of:
3676 // <type> ::= <template-param>
3677 // <type> ::= <template-template-param> <template-args>
3678 //
3679 // <template-template-param> ::= <template-param>
3680 // ::= <substitution>
3681 //
3682 // If this is followed by some <template-args>, and we're permitted to
3683 // parse them, take the second production.
3684
3685 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003686 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003687 if (TA == nullptr)
3688 return nullptr;
3689 Result = make<NameWithTemplateArgs>(Result, TA);
3690 }
3691 break;
3692 }
3693 // ::= P <type> # pointer
3694 case 'P': {
3695 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003696 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003697 if (Ptr == nullptr)
3698 return nullptr;
3699 Result = make<PointerType>(Ptr);
3700 break;
3701 }
3702 // ::= R <type> # l-value reference
3703 case 'R': {
3704 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003705 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003706 if (Ref == nullptr)
3707 return nullptr;
3708 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
3709 break;
3710 }
3711 // ::= O <type> # r-value reference (C++11)
3712 case 'O': {
3713 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003714 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003715 if (Ref == nullptr)
3716 return nullptr;
3717 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
3718 break;
3719 }
3720 // ::= C <type> # complex pair (C99)
3721 case 'C': {
3722 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003723 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003724 if (P == nullptr)
3725 return nullptr;
3726 Result = make<PostfixQualifiedType>(P, " complex");
3727 break;
3728 }
3729 // ::= G <type> # imaginary (C99)
3730 case 'G': {
3731 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003732 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003733 if (P == nullptr)
3734 return P;
3735 Result = make<PostfixQualifiedType>(P, " imaginary");
3736 break;
3737 }
3738 // ::= <substitution> # See Compression below
3739 case 'S': {
3740 if (look(1) && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00003741 Node *Sub = getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003742 if (Sub == nullptr)
3743 return nullptr;
3744
3745 // Sub could be either of:
3746 // <type> ::= <substitution>
3747 // <type> ::= <template-template-param> <template-args>
3748 //
3749 // <template-template-param> ::= <template-param>
3750 // ::= <substitution>
3751 //
3752 // If this is followed by some <template-args>, and we're permitted to
3753 // parse them, take the second production.
3754
3755 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003756 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003757 if (TA == nullptr)
3758 return nullptr;
3759 Result = make<NameWithTemplateArgs>(Sub, TA);
3760 break;
3761 }
3762
3763 // If all we parsed was a substitution, don't re-insert into the
3764 // substitution table.
3765 return Sub;
3766 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003767 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003768 }
3769 // ::= <class-enum-type>
3770 default: {
Pavel Labathba825192018-10-16 14:29:14 +00003771 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003772 break;
3773 }
3774 }
3775
3776 // If we parsed a type, insert it into the substitution table. Note that all
3777 // <builtin-type>s and <substitution>s have already bailed out, because they
3778 // don't get substitutions.
3779 if (Result != nullptr)
3780 Subs.push_back(Result);
3781 return Result;
3782}
3783
Pavel Labathba825192018-10-16 14:29:14 +00003784template <typename Derived, typename Alloc>
3785Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) {
3786 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003787 if (E == nullptr)
3788 return nullptr;
3789 return make<PrefixExpr>(Kind, E);
3790}
3791
Pavel Labathba825192018-10-16 14:29:14 +00003792template <typename Derived, typename Alloc>
3793Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) {
3794 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003795 if (LHS == nullptr)
3796 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003797 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003798 if (RHS == nullptr)
3799 return nullptr;
3800 return make<BinaryExpr>(LHS, Kind, RHS);
3801}
3802
Pavel Labathba825192018-10-16 14:29:14 +00003803template <typename Derived, typename Alloc>
3804Node *
3805AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00003806 StringView Tmp = parseNumber(true);
3807 if (!Tmp.empty() && consumeIf('E'))
3808 return make<IntegerLiteral>(Lit, Tmp);
3809 return nullptr;
3810}
3811
3812// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00003813template <typename Alloc, typename Derived>
3814Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00003815 Qualifiers CVR = QualNone;
3816 if (consumeIf('r'))
3817 CVR |= QualRestrict;
3818 if (consumeIf('V'))
3819 CVR |= QualVolatile;
3820 if (consumeIf('K'))
3821 CVR |= QualConst;
3822 return CVR;
3823}
3824
3825// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
3826// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
3827// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
3828// ::= 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 +00003829template <typename Derived, typename Alloc>
3830Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00003831 if (consumeIf("fp")) {
3832 parseCVQualifiers();
3833 StringView Num = parseNumber();
3834 if (!consumeIf('_'))
3835 return nullptr;
3836 return make<FunctionParam>(Num);
3837 }
3838 if (consumeIf("fL")) {
3839 if (parseNumber().empty())
3840 return nullptr;
3841 if (!consumeIf('p'))
3842 return nullptr;
3843 parseCVQualifiers();
3844 StringView Num = parseNumber();
3845 if (!consumeIf('_'))
3846 return nullptr;
3847 return make<FunctionParam>(Num);
3848 }
3849 return nullptr;
3850}
3851
3852// [gs] nw <expression>* _ <type> E # new (expr-list) type
3853// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
3854// [gs] na <expression>* _ <type> E # new[] (expr-list) type
3855// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
3856// <initializer> ::= pi <expression>* E # parenthesized initialization
Pavel Labathba825192018-10-16 14:29:14 +00003857template <typename Derived, typename Alloc>
3858Node *AbstractManglingParser<Derived, Alloc>::parseNewExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00003859 bool Global = consumeIf("gs");
3860 bool IsArray = look(1) == 'a';
3861 if (!consumeIf("nw") && !consumeIf("na"))
3862 return nullptr;
3863 size_t Exprs = Names.size();
3864 while (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003865 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003866 if (Ex == nullptr)
3867 return nullptr;
3868 Names.push_back(Ex);
3869 }
3870 NodeArray ExprList = popTrailingNodeArray(Exprs);
Pavel Labathba825192018-10-16 14:29:14 +00003871 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003872 if (Ty == nullptr)
3873 return Ty;
3874 if (consumeIf("pi")) {
3875 size_t InitsBegin = Names.size();
3876 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003877 Node *Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003878 if (Init == nullptr)
3879 return Init;
3880 Names.push_back(Init);
3881 }
3882 NodeArray Inits = popTrailingNodeArray(InitsBegin);
3883 return make<NewExpr>(ExprList, Ty, Inits, Global, IsArray);
3884 } else if (!consumeIf('E'))
3885 return nullptr;
3886 return make<NewExpr>(ExprList, Ty, NodeArray(), Global, IsArray);
3887}
3888
3889// cv <type> <expression> # conversion with one argument
3890// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00003891template <typename Derived, typename Alloc>
3892Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00003893 if (!consumeIf("cv"))
3894 return nullptr;
3895 Node *Ty;
3896 {
3897 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00003898 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003899 }
3900
3901 if (Ty == nullptr)
3902 return nullptr;
3903
3904 if (consumeIf('_')) {
3905 size_t ExprsBegin = Names.size();
3906 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003907 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003908 if (E == nullptr)
3909 return E;
3910 Names.push_back(E);
3911 }
3912 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
3913 return make<ConversionExpr>(Ty, Exprs);
3914 }
3915
Pavel Labathba825192018-10-16 14:29:14 +00003916 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00003917 if (E[0] == nullptr)
3918 return nullptr;
3919 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
3920}
3921
3922// <expr-primary> ::= L <type> <value number> E # integer literal
3923// ::= L <type> <value float> E # floating literal
3924// ::= L <string type> E # string literal
3925// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
3926// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
3927// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00003928template <typename Derived, typename Alloc>
3929Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00003930 if (!consumeIf('L'))
3931 return nullptr;
3932 switch (look()) {
3933 case 'w':
3934 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003935 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003936 case 'b':
3937 if (consumeIf("b0E"))
3938 return make<BoolExpr>(0);
3939 if (consumeIf("b1E"))
3940 return make<BoolExpr>(1);
3941 return nullptr;
3942 case 'c':
3943 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003944 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00003945 case 'a':
3946 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003947 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00003948 case 'h':
3949 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003950 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00003951 case 's':
3952 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003953 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00003954 case 't':
3955 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003956 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00003957 case 'i':
3958 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003959 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00003960 case 'j':
3961 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003962 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00003963 case 'l':
3964 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003965 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00003966 case 'm':
3967 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003968 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00003969 case 'x':
3970 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003971 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00003972 case 'y':
3973 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003974 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00003975 case 'n':
3976 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003977 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00003978 case 'o':
3979 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003980 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00003981 case 'f':
3982 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003983 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00003984 case 'd':
3985 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003986 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00003987 case 'e':
3988 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003989 return getDerived().template parseFloatingLiteral<long double>();
Richard Smithc20d1442018-08-20 20:14:49 +00003990 case '_':
3991 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00003992 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00003993 if (R != nullptr && consumeIf('E'))
3994 return R;
3995 }
3996 return nullptr;
3997 case 'T':
3998 // Invalid mangled name per
3999 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4000 return nullptr;
4001 default: {
4002 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004003 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004004 if (T == nullptr)
4005 return nullptr;
4006 StringView N = parseNumber();
4007 if (!N.empty()) {
4008 if (!consumeIf('E'))
4009 return nullptr;
4010 return make<IntegerCastExpr>(T, N);
4011 }
4012 if (consumeIf('E'))
4013 return T;
4014 return nullptr;
4015 }
4016 }
4017}
4018
4019// <braced-expression> ::= <expression>
4020// ::= di <field source-name> <braced-expression> # .name = expr
4021// ::= dx <index expression> <braced-expression> # [expr] = expr
4022// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004023template <typename Derived, typename Alloc>
4024Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004025 if (look() == 'd') {
4026 switch (look(1)) {
4027 case 'i': {
4028 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004029 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004030 if (Field == nullptr)
4031 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004032 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004033 if (Init == nullptr)
4034 return nullptr;
4035 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4036 }
4037 case 'x': {
4038 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004039 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004040 if (Index == nullptr)
4041 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004042 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004043 if (Init == nullptr)
4044 return nullptr;
4045 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4046 }
4047 case 'X': {
4048 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004049 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004050 if (RangeBegin == nullptr)
4051 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004052 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004053 if (RangeEnd == nullptr)
4054 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004055 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004056 if (Init == nullptr)
4057 return nullptr;
4058 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4059 }
4060 }
4061 }
Pavel Labathba825192018-10-16 14:29:14 +00004062 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004063}
4064
4065// (not yet in the spec)
4066// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4067// ::= fR <binary-operator-name> <expression> <expression>
4068// ::= fl <binary-operator-name> <expression>
4069// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004070template <typename Derived, typename Alloc>
4071Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004072 if (!consumeIf('f'))
4073 return nullptr;
4074
4075 char FoldKind = look();
4076 bool IsLeftFold, HasInitializer;
4077 HasInitializer = FoldKind == 'L' || FoldKind == 'R';
4078 if (FoldKind == 'l' || FoldKind == 'L')
4079 IsLeftFold = true;
4080 else if (FoldKind == 'r' || FoldKind == 'R')
4081 IsLeftFold = false;
4082 else
4083 return nullptr;
4084 ++First;
4085
4086 // FIXME: This map is duplicated in parseOperatorName and parseExpr.
4087 StringView OperatorName;
4088 if (consumeIf("aa")) OperatorName = "&&";
4089 else if (consumeIf("an")) OperatorName = "&";
4090 else if (consumeIf("aN")) OperatorName = "&=";
4091 else if (consumeIf("aS")) OperatorName = "=";
4092 else if (consumeIf("cm")) OperatorName = ",";
4093 else if (consumeIf("ds")) OperatorName = ".*";
4094 else if (consumeIf("dv")) OperatorName = "/";
4095 else if (consumeIf("dV")) OperatorName = "/=";
4096 else if (consumeIf("eo")) OperatorName = "^";
4097 else if (consumeIf("eO")) OperatorName = "^=";
4098 else if (consumeIf("eq")) OperatorName = "==";
4099 else if (consumeIf("ge")) OperatorName = ">=";
4100 else if (consumeIf("gt")) OperatorName = ">";
4101 else if (consumeIf("le")) OperatorName = "<=";
4102 else if (consumeIf("ls")) OperatorName = "<<";
4103 else if (consumeIf("lS")) OperatorName = "<<=";
4104 else if (consumeIf("lt")) OperatorName = "<";
4105 else if (consumeIf("mi")) OperatorName = "-";
4106 else if (consumeIf("mI")) OperatorName = "-=";
4107 else if (consumeIf("ml")) OperatorName = "*";
4108 else if (consumeIf("mL")) OperatorName = "*=";
4109 else if (consumeIf("ne")) OperatorName = "!=";
4110 else if (consumeIf("oo")) OperatorName = "||";
4111 else if (consumeIf("or")) OperatorName = "|";
4112 else if (consumeIf("oR")) OperatorName = "|=";
4113 else if (consumeIf("pl")) OperatorName = "+";
4114 else if (consumeIf("pL")) OperatorName = "+=";
4115 else if (consumeIf("rm")) OperatorName = "%";
4116 else if (consumeIf("rM")) OperatorName = "%=";
4117 else if (consumeIf("rs")) OperatorName = ">>";
4118 else if (consumeIf("rS")) OperatorName = ">>=";
4119 else return nullptr;
4120
Pavel Labathba825192018-10-16 14:29:14 +00004121 Node *Pack = getDerived().parseExpr(), *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004122 if (Pack == nullptr)
4123 return nullptr;
4124 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004125 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004126 if (Init == nullptr)
4127 return nullptr;
4128 }
4129
4130 if (IsLeftFold && Init)
4131 std::swap(Pack, Init);
4132
4133 return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
4134}
4135
4136// <expression> ::= <unary operator-name> <expression>
4137// ::= <binary operator-name> <expression> <expression>
4138// ::= <ternary operator-name> <expression> <expression> <expression>
4139// ::= cl <expression>+ E # call
4140// ::= cv <type> <expression> # conversion with one argument
4141// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4142// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4143// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4144// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4145// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4146// ::= [gs] dl <expression> # delete expression
4147// ::= [gs] da <expression> # delete[] expression
4148// ::= pp_ <expression> # prefix ++
4149// ::= mm_ <expression> # prefix --
4150// ::= ti <type> # typeid (type)
4151// ::= te <expression> # typeid (expression)
4152// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4153// ::= sc <type> <expression> # static_cast<type> (expression)
4154// ::= cc <type> <expression> # const_cast<type> (expression)
4155// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4156// ::= st <type> # sizeof (a type)
4157// ::= sz <expression> # sizeof (an expression)
4158// ::= at <type> # alignof (a type)
4159// ::= az <expression> # alignof (an expression)
4160// ::= nx <expression> # noexcept (expression)
4161// ::= <template-param>
4162// ::= <function-param>
4163// ::= dt <expression> <unresolved-name> # expr.name
4164// ::= pt <expression> <unresolved-name> # expr->name
4165// ::= ds <expression> <expression> # expr.*expr
4166// ::= sZ <template-param> # size of a parameter pack
4167// ::= sZ <function-param> # size of a function parameter pack
4168// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4169// ::= sp <expression> # pack expansion
4170// ::= tw <expression> # throw expression
4171// ::= tr # throw with no operand (rethrow)
4172// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4173// # freestanding dependent name (e.g., T::x),
4174// # objectless nonstatic member reference
4175// ::= fL <binary-operator-name> <expression> <expression>
4176// ::= fR <binary-operator-name> <expression> <expression>
4177// ::= fl <binary-operator-name> <expression>
4178// ::= fr <binary-operator-name> <expression>
4179// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004180template <typename Derived, typename Alloc>
4181Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004182 bool Global = consumeIf("gs");
4183 if (numLeft() < 2)
4184 return nullptr;
4185
4186 switch (*First) {
4187 case 'L':
Pavel Labathba825192018-10-16 14:29:14 +00004188 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00004189 case 'T':
Pavel Labathba825192018-10-16 14:29:14 +00004190 return getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004191 case 'f': {
4192 // Disambiguate a fold expression from a <function-param>.
4193 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
Pavel Labathba825192018-10-16 14:29:14 +00004194 return getDerived().parseFunctionParam();
4195 return getDerived().parseFoldExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004196 }
4197 case 'a':
4198 switch (First[1]) {
4199 case 'a':
4200 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004201 return getDerived().parseBinaryExpr("&&");
Richard Smithc20d1442018-08-20 20:14:49 +00004202 case 'd':
4203 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004204 return getDerived().parsePrefixExpr("&");
Richard Smithc20d1442018-08-20 20:14:49 +00004205 case 'n':
4206 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004207 return getDerived().parseBinaryExpr("&");
Richard Smithc20d1442018-08-20 20:14:49 +00004208 case 'N':
4209 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004210 return getDerived().parseBinaryExpr("&=");
Richard Smithc20d1442018-08-20 20:14:49 +00004211 case 'S':
4212 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004213 return getDerived().parseBinaryExpr("=");
Richard Smithc20d1442018-08-20 20:14:49 +00004214 case 't': {
4215 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004216 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004217 if (Ty == nullptr)
4218 return nullptr;
4219 return make<EnclosingExpr>("alignof (", Ty, ")");
4220 }
4221 case 'z': {
4222 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004223 Node *Ty = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004224 if (Ty == nullptr)
4225 return nullptr;
4226 return make<EnclosingExpr>("alignof (", Ty, ")");
4227 }
4228 }
4229 return nullptr;
4230 case 'c':
4231 switch (First[1]) {
4232 // cc <type> <expression> # const_cast<type>(expression)
4233 case 'c': {
4234 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004235 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004236 if (Ty == nullptr)
4237 return Ty;
Pavel Labathba825192018-10-16 14:29:14 +00004238 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004239 if (Ex == nullptr)
4240 return Ex;
4241 return make<CastExpr>("const_cast", Ty, Ex);
4242 }
4243 // cl <expression>+ E # call
4244 case 'l': {
4245 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004246 Node *Callee = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004247 if (Callee == nullptr)
4248 return Callee;
4249 size_t ExprsBegin = Names.size();
4250 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004251 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004252 if (E == nullptr)
4253 return E;
4254 Names.push_back(E);
4255 }
4256 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin));
4257 }
4258 case 'm':
4259 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004260 return getDerived().parseBinaryExpr(",");
Richard Smithc20d1442018-08-20 20:14:49 +00004261 case 'o':
4262 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004263 return getDerived().parsePrefixExpr("~");
Richard Smithc20d1442018-08-20 20:14:49 +00004264 case 'v':
Pavel Labathba825192018-10-16 14:29:14 +00004265 return getDerived().parseConversionExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004266 }
4267 return nullptr;
4268 case 'd':
4269 switch (First[1]) {
4270 case 'a': {
4271 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004272 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004273 if (Ex == nullptr)
4274 return Ex;
4275 return make<DeleteExpr>(Ex, Global, /*is_array=*/true);
4276 }
4277 case 'c': {
4278 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004279 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004280 if (T == nullptr)
4281 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004282 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004283 if (Ex == nullptr)
4284 return Ex;
4285 return make<CastExpr>("dynamic_cast", T, Ex);
4286 }
4287 case 'e':
4288 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004289 return getDerived().parsePrefixExpr("*");
Richard Smithc20d1442018-08-20 20:14:49 +00004290 case 'l': {
4291 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004292 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004293 if (E == nullptr)
4294 return E;
4295 return make<DeleteExpr>(E, Global, /*is_array=*/false);
4296 }
4297 case 'n':
Pavel Labathba825192018-10-16 14:29:14 +00004298 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004299 case 's': {
4300 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004301 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004302 if (LHS == nullptr)
4303 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004304 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004305 if (RHS == nullptr)
4306 return nullptr;
4307 return make<MemberExpr>(LHS, ".*", RHS);
4308 }
4309 case 't': {
4310 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004311 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004312 if (LHS == nullptr)
4313 return LHS;
Pavel Labathba825192018-10-16 14:29:14 +00004314 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004315 if (RHS == nullptr)
4316 return nullptr;
4317 return make<MemberExpr>(LHS, ".", RHS);
4318 }
4319 case 'v':
4320 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004321 return getDerived().parseBinaryExpr("/");
Richard Smithc20d1442018-08-20 20:14:49 +00004322 case 'V':
4323 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004324 return getDerived().parseBinaryExpr("/=");
Richard Smithc20d1442018-08-20 20:14:49 +00004325 }
4326 return nullptr;
4327 case 'e':
4328 switch (First[1]) {
4329 case 'o':
4330 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004331 return getDerived().parseBinaryExpr("^");
Richard Smithc20d1442018-08-20 20:14:49 +00004332 case 'O':
4333 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004334 return getDerived().parseBinaryExpr("^=");
Richard Smithc20d1442018-08-20 20:14:49 +00004335 case 'q':
4336 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004337 return getDerived().parseBinaryExpr("==");
Richard Smithc20d1442018-08-20 20:14:49 +00004338 }
4339 return nullptr;
4340 case 'g':
4341 switch (First[1]) {
4342 case 'e':
4343 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004344 return getDerived().parseBinaryExpr(">=");
Richard Smithc20d1442018-08-20 20:14:49 +00004345 case 't':
4346 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004347 return getDerived().parseBinaryExpr(">");
Richard Smithc20d1442018-08-20 20:14:49 +00004348 }
4349 return nullptr;
4350 case 'i':
4351 switch (First[1]) {
4352 case 'x': {
4353 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004354 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004355 if (Base == nullptr)
4356 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004357 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004358 if (Index == nullptr)
4359 return Index;
4360 return make<ArraySubscriptExpr>(Base, Index);
4361 }
4362 case 'l': {
4363 First += 2;
4364 size_t InitsBegin = Names.size();
4365 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004366 Node *E = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004367 if (E == nullptr)
4368 return nullptr;
4369 Names.push_back(E);
4370 }
4371 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4372 }
4373 }
4374 return nullptr;
4375 case 'l':
4376 switch (First[1]) {
4377 case 'e':
4378 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004379 return getDerived().parseBinaryExpr("<=");
Richard Smithc20d1442018-08-20 20:14:49 +00004380 case 's':
4381 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004382 return getDerived().parseBinaryExpr("<<");
Richard Smithc20d1442018-08-20 20:14:49 +00004383 case 'S':
4384 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004385 return getDerived().parseBinaryExpr("<<=");
Richard Smithc20d1442018-08-20 20:14:49 +00004386 case 't':
4387 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004388 return getDerived().parseBinaryExpr("<");
Richard Smithc20d1442018-08-20 20:14:49 +00004389 }
4390 return nullptr;
4391 case 'm':
4392 switch (First[1]) {
4393 case 'i':
4394 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004395 return getDerived().parseBinaryExpr("-");
Richard Smithc20d1442018-08-20 20:14:49 +00004396 case 'I':
4397 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004398 return getDerived().parseBinaryExpr("-=");
Richard Smithc20d1442018-08-20 20:14:49 +00004399 case 'l':
4400 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004401 return getDerived().parseBinaryExpr("*");
Richard Smithc20d1442018-08-20 20:14:49 +00004402 case 'L':
4403 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004404 return getDerived().parseBinaryExpr("*=");
Richard Smithc20d1442018-08-20 20:14:49 +00004405 case 'm':
4406 First += 2;
4407 if (consumeIf('_'))
Pavel Labathba825192018-10-16 14:29:14 +00004408 return getDerived().parsePrefixExpr("--");
4409 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004410 if (Ex == nullptr)
4411 return nullptr;
4412 return make<PostfixExpr>(Ex, "--");
4413 }
4414 return nullptr;
4415 case 'n':
4416 switch (First[1]) {
4417 case 'a':
4418 case 'w':
Pavel Labathba825192018-10-16 14:29:14 +00004419 return getDerived().parseNewExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004420 case 'e':
4421 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004422 return getDerived().parseBinaryExpr("!=");
Richard Smithc20d1442018-08-20 20:14:49 +00004423 case 'g':
4424 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004425 return getDerived().parsePrefixExpr("-");
Richard Smithc20d1442018-08-20 20:14:49 +00004426 case 't':
4427 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004428 return getDerived().parsePrefixExpr("!");
Richard Smithc20d1442018-08-20 20:14:49 +00004429 case 'x':
4430 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004431 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004432 if (Ex == nullptr)
4433 return Ex;
4434 return make<EnclosingExpr>("noexcept (", Ex, ")");
4435 }
4436 return nullptr;
4437 case 'o':
4438 switch (First[1]) {
4439 case 'n':
Pavel Labathba825192018-10-16 14:29:14 +00004440 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004441 case 'o':
4442 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004443 return getDerived().parseBinaryExpr("||");
Richard Smithc20d1442018-08-20 20:14:49 +00004444 case 'r':
4445 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004446 return getDerived().parseBinaryExpr("|");
Richard Smithc20d1442018-08-20 20:14:49 +00004447 case 'R':
4448 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004449 return getDerived().parseBinaryExpr("|=");
Richard Smithc20d1442018-08-20 20:14:49 +00004450 }
4451 return nullptr;
4452 case 'p':
4453 switch (First[1]) {
4454 case 'm':
4455 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004456 return getDerived().parseBinaryExpr("->*");
Richard Smithc20d1442018-08-20 20:14:49 +00004457 case 'l':
4458 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004459 return getDerived().parseBinaryExpr("+");
Richard Smithc20d1442018-08-20 20:14:49 +00004460 case 'L':
4461 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004462 return getDerived().parseBinaryExpr("+=");
Richard Smithc20d1442018-08-20 20:14:49 +00004463 case 'p': {
4464 First += 2;
4465 if (consumeIf('_'))
Pavel Labathba825192018-10-16 14:29:14 +00004466 return getDerived().parsePrefixExpr("++");
4467 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004468 if (Ex == nullptr)
4469 return Ex;
4470 return make<PostfixExpr>(Ex, "++");
4471 }
4472 case 's':
4473 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004474 return getDerived().parsePrefixExpr("+");
Richard Smithc20d1442018-08-20 20:14:49 +00004475 case 't': {
4476 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004477 Node *L = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004478 if (L == nullptr)
4479 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004480 Node *R = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004481 if (R == nullptr)
4482 return nullptr;
4483 return make<MemberExpr>(L, "->", R);
4484 }
4485 }
4486 return nullptr;
4487 case 'q':
4488 if (First[1] == 'u') {
4489 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004490 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004491 if (Cond == nullptr)
4492 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004493 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004494 if (LHS == nullptr)
4495 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004496 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004497 if (RHS == nullptr)
4498 return nullptr;
4499 return make<ConditionalExpr>(Cond, LHS, RHS);
4500 }
4501 return nullptr;
4502 case 'r':
4503 switch (First[1]) {
4504 case 'c': {
4505 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004506 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004507 if (T == nullptr)
4508 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004509 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004510 if (Ex == nullptr)
4511 return Ex;
4512 return make<CastExpr>("reinterpret_cast", T, Ex);
4513 }
4514 case 'm':
4515 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004516 return getDerived().parseBinaryExpr("%");
Richard Smithc20d1442018-08-20 20:14:49 +00004517 case 'M':
4518 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004519 return getDerived().parseBinaryExpr("%=");
Richard Smithc20d1442018-08-20 20:14:49 +00004520 case 's':
4521 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004522 return getDerived().parseBinaryExpr(">>");
Richard Smithc20d1442018-08-20 20:14:49 +00004523 case 'S':
4524 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004525 return getDerived().parseBinaryExpr(">>=");
Richard Smithc20d1442018-08-20 20:14:49 +00004526 }
4527 return nullptr;
4528 case 's':
4529 switch (First[1]) {
4530 case 'c': {
4531 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004532 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004533 if (T == nullptr)
4534 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004535 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004536 if (Ex == nullptr)
4537 return Ex;
4538 return make<CastExpr>("static_cast", T, Ex);
4539 }
4540 case 'p': {
4541 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004542 Node *Child = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004543 if (Child == nullptr)
4544 return nullptr;
4545 return make<ParameterPackExpansion>(Child);
4546 }
4547 case 'r':
Pavel Labathba825192018-10-16 14:29:14 +00004548 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004549 case 't': {
4550 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004551 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004552 if (Ty == nullptr)
4553 return Ty;
4554 return make<EnclosingExpr>("sizeof (", Ty, ")");
4555 }
4556 case 'z': {
4557 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004558 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004559 if (Ex == nullptr)
4560 return Ex;
4561 return make<EnclosingExpr>("sizeof (", Ex, ")");
4562 }
4563 case 'Z':
4564 First += 2;
4565 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00004566 Node *R = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004567 if (R == nullptr)
4568 return nullptr;
4569 return make<SizeofParamPackExpr>(R);
4570 } else if (look() == 'f') {
Pavel Labathba825192018-10-16 14:29:14 +00004571 Node *FP = getDerived().parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004572 if (FP == nullptr)
4573 return nullptr;
4574 return make<EnclosingExpr>("sizeof... (", FP, ")");
4575 }
4576 return nullptr;
4577 case 'P': {
4578 First += 2;
4579 size_t ArgsBegin = Names.size();
4580 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004581 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00004582 if (Arg == nullptr)
4583 return nullptr;
4584 Names.push_back(Arg);
4585 }
Richard Smithb485b352018-08-24 23:30:26 +00004586 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4587 if (!Pack)
4588 return nullptr;
4589 return make<EnclosingExpr>("sizeof... (", Pack, ")");
Richard Smithc20d1442018-08-20 20:14:49 +00004590 }
4591 }
4592 return nullptr;
4593 case 't':
4594 switch (First[1]) {
4595 case 'e': {
4596 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004597 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004598 if (Ex == nullptr)
4599 return Ex;
4600 return make<EnclosingExpr>("typeid (", Ex, ")");
4601 }
4602 case 'i': {
4603 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004604 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004605 if (Ty == nullptr)
4606 return Ty;
4607 return make<EnclosingExpr>("typeid (", Ty, ")");
4608 }
4609 case 'l': {
4610 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004611 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004612 if (Ty == nullptr)
4613 return nullptr;
4614 size_t InitsBegin = Names.size();
4615 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004616 Node *E = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004617 if (E == nullptr)
4618 return nullptr;
4619 Names.push_back(E);
4620 }
4621 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4622 }
4623 case 'r':
4624 First += 2;
4625 return make<NameType>("throw");
4626 case 'w': {
4627 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004628 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004629 if (Ex == nullptr)
4630 return nullptr;
4631 return make<ThrowExpr>(Ex);
4632 }
4633 }
4634 return nullptr;
4635 case '1':
4636 case '2':
4637 case '3':
4638 case '4':
4639 case '5':
4640 case '6':
4641 case '7':
4642 case '8':
4643 case '9':
Pavel Labathba825192018-10-16 14:29:14 +00004644 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004645 }
4646 return nullptr;
4647}
4648
4649// <call-offset> ::= h <nv-offset> _
4650// ::= v <v-offset> _
4651//
4652// <nv-offset> ::= <offset number>
4653// # non-virtual base override
4654//
4655// <v-offset> ::= <offset number> _ <virtual offset number>
4656// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004657template <typename Alloc, typename Derived>
4658bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004659 // Just scan through the call offset, we never add this information into the
4660 // output.
4661 if (consumeIf('h'))
4662 return parseNumber(true).empty() || !consumeIf('_');
4663 if (consumeIf('v'))
4664 return parseNumber(true).empty() || !consumeIf('_') ||
4665 parseNumber(true).empty() || !consumeIf('_');
4666 return true;
4667}
4668
4669// <special-name> ::= TV <type> # virtual table
4670// ::= TT <type> # VTT structure (construction vtable index)
4671// ::= TI <type> # typeinfo structure
4672// ::= TS <type> # typeinfo name (null-terminated byte string)
4673// ::= Tc <call-offset> <call-offset> <base encoding>
4674// # base is the nominal target function of thunk
4675// # first call-offset is 'this' adjustment
4676// # second call-offset is result adjustment
4677// ::= T <call-offset> <base encoding>
4678// # base is the nominal target function of thunk
4679// ::= GV <object name> # Guard variable for one-time initialization
4680// # No <type>
4681// ::= TW <object name> # Thread-local wrapper
4682// ::= TH <object name> # Thread-local initialization
4683// ::= GR <object name> _ # First temporary
4684// ::= GR <object name> <seq-id> _ # Subsequent temporaries
4685// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
4686// extension ::= GR <object name> # reference temporary for object
Pavel Labathba825192018-10-16 14:29:14 +00004687template <typename Derived, typename Alloc>
4688Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004689 switch (look()) {
4690 case 'T':
4691 switch (look(1)) {
4692 // TV <type> # virtual table
4693 case 'V': {
4694 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004695 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004696 if (Ty == nullptr)
4697 return nullptr;
4698 return make<SpecialName>("vtable for ", Ty);
4699 }
4700 // TT <type> # VTT structure (construction vtable index)
4701 case 'T': {
4702 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004703 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004704 if (Ty == nullptr)
4705 return nullptr;
4706 return make<SpecialName>("VTT for ", Ty);
4707 }
4708 // TI <type> # typeinfo structure
4709 case 'I': {
4710 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004711 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004712 if (Ty == nullptr)
4713 return nullptr;
4714 return make<SpecialName>("typeinfo for ", Ty);
4715 }
4716 // TS <type> # typeinfo name (null-terminated byte string)
4717 case 'S': {
4718 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004719 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004720 if (Ty == nullptr)
4721 return nullptr;
4722 return make<SpecialName>("typeinfo name for ", Ty);
4723 }
4724 // Tc <call-offset> <call-offset> <base encoding>
4725 case 'c': {
4726 First += 2;
4727 if (parseCallOffset() || parseCallOffset())
4728 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004729 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004730 if (Encoding == nullptr)
4731 return nullptr;
4732 return make<SpecialName>("covariant return thunk to ", Encoding);
4733 }
4734 // extension ::= TC <first type> <number> _ <second type>
4735 // # construction vtable for second-in-first
4736 case 'C': {
4737 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004738 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004739 if (FirstType == nullptr)
4740 return nullptr;
4741 if (parseNumber(true).empty() || !consumeIf('_'))
4742 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004743 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004744 if (SecondType == nullptr)
4745 return nullptr;
4746 return make<CtorVtableSpecialName>(SecondType, FirstType);
4747 }
4748 // TW <object name> # Thread-local wrapper
4749 case 'W': {
4750 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004751 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004752 if (Name == nullptr)
4753 return nullptr;
4754 return make<SpecialName>("thread-local wrapper routine for ", Name);
4755 }
4756 // TH <object name> # Thread-local initialization
4757 case 'H': {
4758 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004759 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004760 if (Name == nullptr)
4761 return nullptr;
4762 return make<SpecialName>("thread-local initialization routine for ", Name);
4763 }
4764 // T <call-offset> <base encoding>
4765 default: {
4766 ++First;
4767 bool IsVirt = look() == 'v';
4768 if (parseCallOffset())
4769 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004770 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004771 if (BaseEncoding == nullptr)
4772 return nullptr;
4773 if (IsVirt)
4774 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4775 else
4776 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4777 }
4778 }
4779 case 'G':
4780 switch (look(1)) {
4781 // GV <object name> # Guard variable for one-time initialization
4782 case 'V': {
4783 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004784 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004785 if (Name == nullptr)
4786 return nullptr;
4787 return make<SpecialName>("guard variable for ", Name);
4788 }
4789 // GR <object name> # reference temporary for object
4790 // GR <object name> _ # First temporary
4791 // GR <object name> <seq-id> _ # Subsequent temporaries
4792 case 'R': {
4793 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004794 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004795 if (Name == nullptr)
4796 return nullptr;
4797 size_t Count;
4798 bool ParsedSeqId = !parseSeqId(&Count);
4799 if (!consumeIf('_') && ParsedSeqId)
4800 return nullptr;
4801 return make<SpecialName>("reference temporary for ", Name);
4802 }
4803 }
4804 }
4805 return nullptr;
4806}
4807
4808// <encoding> ::= <function name> <bare-function-type>
4809// ::= <data name>
4810// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00004811template <typename Derived, typename Alloc>
4812Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithc20d1442018-08-20 20:14:49 +00004813 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00004814 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00004815
4816 auto IsEndOfEncoding = [&] {
4817 // The set of chars that can potentially follow an <encoding> (none of which
4818 // can start a <type>). Enumerating these allows us to avoid speculative
4819 // parsing.
4820 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
4821 };
4822
4823 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00004824 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00004825 if (Name == nullptr)
4826 return nullptr;
4827
4828 if (resolveForwardTemplateRefs(NameInfo))
4829 return nullptr;
4830
4831 if (IsEndOfEncoding())
4832 return Name;
4833
4834 Node *Attrs = nullptr;
4835 if (consumeIf("Ua9enable_ifI")) {
4836 size_t BeforeArgs = Names.size();
4837 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004838 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00004839 if (Arg == nullptr)
4840 return nullptr;
4841 Names.push_back(Arg);
4842 }
4843 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00004844 if (!Attrs)
4845 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004846 }
4847
4848 Node *ReturnType = nullptr;
4849 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00004850 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004851 if (ReturnType == nullptr)
4852 return nullptr;
4853 }
4854
4855 if (consumeIf('v'))
4856 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
4857 Attrs, NameInfo.CVQualifiers,
4858 NameInfo.ReferenceQualifier);
4859
4860 size_t ParamsBegin = Names.size();
4861 do {
Pavel Labathba825192018-10-16 14:29:14 +00004862 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004863 if (Ty == nullptr)
4864 return nullptr;
4865 Names.push_back(Ty);
4866 } while (!IsEndOfEncoding());
4867
4868 return make<FunctionEncoding>(ReturnType, Name,
4869 popTrailingNodeArray(ParamsBegin),
4870 Attrs, NameInfo.CVQualifiers,
4871 NameInfo.ReferenceQualifier);
4872}
4873
4874template <class Float>
4875struct FloatData;
4876
4877template <>
4878struct FloatData<float>
4879{
4880 static const size_t mangled_size = 8;
4881 static const size_t max_demangled_size = 24;
4882 static constexpr const char* spec = "%af";
4883};
4884
4885template <>
4886struct FloatData<double>
4887{
4888 static const size_t mangled_size = 16;
4889 static const size_t max_demangled_size = 32;
4890 static constexpr const char* spec = "%a";
4891};
4892
4893template <>
4894struct FloatData<long double>
4895{
4896#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
4897 defined(__wasm__)
4898 static const size_t mangled_size = 32;
4899#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
4900 static const size_t mangled_size = 16;
4901#else
4902 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
4903#endif
4904 static const size_t max_demangled_size = 40;
4905 static constexpr const char *spec = "%LaL";
4906};
4907
Pavel Labathba825192018-10-16 14:29:14 +00004908template <typename Alloc, typename Derived>
4909template <class Float>
4910Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00004911 const size_t N = FloatData<Float>::mangled_size;
4912 if (numLeft() <= N)
4913 return nullptr;
4914 StringView Data(First, First + N);
4915 for (char C : Data)
4916 if (!std::isxdigit(C))
4917 return nullptr;
4918 First += N;
4919 if (!consumeIf('E'))
4920 return nullptr;
4921 return make<FloatLiteralImpl<Float>>(Data);
4922}
4923
4924// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00004925template <typename Alloc, typename Derived>
4926bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00004927 if (!(look() >= '0' && look() <= '9') &&
4928 !(look() >= 'A' && look() <= 'Z'))
4929 return true;
4930
4931 size_t Id = 0;
4932 while (true) {
4933 if (look() >= '0' && look() <= '9') {
4934 Id *= 36;
4935 Id += static_cast<size_t>(look() - '0');
4936 } else if (look() >= 'A' && look() <= 'Z') {
4937 Id *= 36;
4938 Id += static_cast<size_t>(look() - 'A') + 10;
4939 } else {
4940 *Out = Id;
4941 return false;
4942 }
4943 ++First;
4944 }
4945}
4946
4947// <substitution> ::= S <seq-id> _
4948// ::= S_
4949// <substitution> ::= Sa # ::std::allocator
4950// <substitution> ::= Sb # ::std::basic_string
4951// <substitution> ::= Ss # ::std::basic_string < char,
4952// ::std::char_traits<char>,
4953// ::std::allocator<char> >
4954// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
4955// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
4956// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Pavel Labathba825192018-10-16 14:29:14 +00004957template <typename Derived, typename Alloc>
4958Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00004959 if (!consumeIf('S'))
4960 return nullptr;
4961
4962 if (std::islower(look())) {
4963 Node *SpecialSub;
4964 switch (look()) {
4965 case 'a':
4966 ++First;
4967 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::allocator);
4968 break;
4969 case 'b':
4970 ++First;
4971 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::basic_string);
4972 break;
4973 case 's':
4974 ++First;
4975 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::string);
4976 break;
4977 case 'i':
4978 ++First;
4979 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::istream);
4980 break;
4981 case 'o':
4982 ++First;
4983 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::ostream);
4984 break;
4985 case 'd':
4986 ++First;
4987 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::iostream);
4988 break;
4989 default:
4990 return nullptr;
4991 }
Richard Smithb485b352018-08-24 23:30:26 +00004992 if (!SpecialSub)
4993 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004994 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
4995 // has ABI tags, the tags are appended to the substitution; the result is a
4996 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00004997 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00004998 if (WithTags != SpecialSub) {
4999 Subs.push_back(WithTags);
5000 SpecialSub = WithTags;
5001 }
5002 return SpecialSub;
5003 }
5004
5005 // ::= S_
5006 if (consumeIf('_')) {
5007 if (Subs.empty())
5008 return nullptr;
5009 return Subs[0];
5010 }
5011
5012 // ::= S <seq-id> _
5013 size_t Index = 0;
5014 if (parseSeqId(&Index))
5015 return nullptr;
5016 ++Index;
5017 if (!consumeIf('_') || Index >= Subs.size())
5018 return nullptr;
5019 return Subs[Index];
5020}
5021
5022// <template-param> ::= T_ # first template parameter
5023// ::= T <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005024template <typename Derived, typename Alloc>
5025Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005026 if (!consumeIf('T'))
5027 return nullptr;
5028
5029 size_t Index = 0;
5030 if (!consumeIf('_')) {
5031 if (parsePositiveInteger(&Index))
5032 return nullptr;
5033 ++Index;
5034 if (!consumeIf('_'))
5035 return nullptr;
5036 }
5037
5038 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter list
5039 // are mangled as the corresponding artificial template type parameter.
5040 if (ParsingLambdaParams)
5041 return make<NameType>("auto");
5042
5043 // If we're in a context where this <template-param> refers to a
5044 // <template-arg> further ahead in the mangled name (currently just conversion
5045 // operator types), then we should only look it up in the right context.
5046 if (PermitForwardTemplateReferences) {
Richard Smithb485b352018-08-24 23:30:26 +00005047 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5048 if (!ForwardRef)
5049 return nullptr;
5050 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5051 ForwardTemplateRefs.push_back(
5052 static_cast<ForwardTemplateReference *>(ForwardRef));
5053 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005054 }
5055
5056 if (Index >= TemplateParams.size())
5057 return nullptr;
5058 return TemplateParams[Index];
5059}
5060
5061// <template-arg> ::= <type> # type or template
5062// ::= X <expression> E # expression
5063// ::= <expr-primary> # simple expressions
5064// ::= J <template-arg>* E # argument pack
5065// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005066template <typename Derived, typename Alloc>
5067Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005068 switch (look()) {
5069 case 'X': {
5070 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005071 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005072 if (Arg == nullptr || !consumeIf('E'))
5073 return nullptr;
5074 return Arg;
5075 }
5076 case 'J': {
5077 ++First;
5078 size_t ArgsBegin = Names.size();
5079 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005080 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005081 if (Arg == nullptr)
5082 return nullptr;
5083 Names.push_back(Arg);
5084 }
5085 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5086 return make<TemplateArgumentPack>(Args);
5087 }
5088 case 'L': {
5089 // ::= LZ <encoding> E # extension
5090 if (look(1) == 'Z') {
5091 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005092 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005093 if (Arg == nullptr || !consumeIf('E'))
5094 return nullptr;
5095 return Arg;
5096 }
5097 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005098 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005099 }
5100 default:
Pavel Labathba825192018-10-16 14:29:14 +00005101 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005102 }
5103}
5104
5105// <template-args> ::= I <template-arg>* E
5106// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005107template <typename Derived, typename Alloc>
5108Node *
5109AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005110 if (!consumeIf('I'))
5111 return nullptr;
5112
5113 // <template-params> refer to the innermost <template-args>. Clear out any
5114 // outer args that we may have inserted into TemplateParams.
5115 if (TagTemplates)
5116 TemplateParams.clear();
5117
5118 size_t ArgsBegin = Names.size();
5119 while (!consumeIf('E')) {
5120 if (TagTemplates) {
5121 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005122 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005123 TemplateParams = std::move(OldParams);
5124 if (Arg == nullptr)
5125 return nullptr;
5126 Names.push_back(Arg);
5127 Node *TableEntry = Arg;
5128 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5129 TableEntry = make<ParameterPack>(
5130 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005131 if (!TableEntry)
5132 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005133 }
5134 TemplateParams.push_back(TableEntry);
5135 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005136 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005137 if (Arg == nullptr)
5138 return nullptr;
5139 Names.push_back(Arg);
5140 }
5141 }
5142 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5143}
5144
5145// <mangled-name> ::= _Z <encoding>
5146// ::= <type>
5147// extension ::= ___Z <encoding> _block_invoke
5148// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5149// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005150template <typename Derived, typename Alloc>
5151Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005152 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005153 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005154 if (Encoding == nullptr)
5155 return nullptr;
5156 if (look() == '.') {
5157 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5158 First = Last;
5159 }
5160 if (numLeft() != 0)
5161 return nullptr;
5162 return Encoding;
5163 }
5164
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005165 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005166 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005167 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5168 return nullptr;
5169 bool RequireNumber = consumeIf('_');
5170 if (parseNumber().empty() && RequireNumber)
5171 return nullptr;
5172 if (look() == '.')
5173 First = Last;
5174 if (numLeft() != 0)
5175 return nullptr;
5176 return make<SpecialName>("invocation function for block in ", Encoding);
5177 }
5178
Pavel Labathba825192018-10-16 14:29:14 +00005179 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005180 if (numLeft() != 0)
5181 return nullptr;
5182 return Ty;
5183}
5184
Pavel Labathba825192018-10-16 14:29:14 +00005185template <typename Alloc>
5186struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5187 using AbstractManglingParser<ManglingParser<Alloc>,
5188 Alloc>::AbstractManglingParser;
5189};
5190
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005191DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005192
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005193#endif // DEMANGLE_ITANIUMDEMANGLE_H