blob: e5fca98f9271798a3476ca5c6a5c10cacaa01ffd [file] [log] [blame]
Richard Smithc20d1442018-08-20 20:14:49 +00001//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===//
2//
Chandler Carruth8ee27c32019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Richard Smithc20d1442018-08-20 20:14:49 +00006//
7//===----------------------------------------------------------------------===//
8//
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00009// Generic itanium demangler library. This file has two byte-per-byte identical
10// copies in the source tree, one in libcxxabi, and the other in llvm.
Richard Smithc20d1442018-08-20 20:14:49 +000011//
12//===----------------------------------------------------------------------===//
13
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000014#ifndef DEMANGLE_ITANIUMDEMANGLE_H
15#define DEMANGLE_ITANIUMDEMANGLE_H
Richard Smithc20d1442018-08-20 20:14:49 +000016
17// FIXME: (possibly) incomplete list of features that clang mangles that this
18// file does not yet support:
19// - C++ modules TS
20
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000021#include "DemangleConfig.h"
Richard Smithc20d1442018-08-20 20:14:49 +000022#include "StringView.h"
23#include "Utility.h"
Richard Smithc20d1442018-08-20 20:14:49 +000024#include <cassert>
25#include <cctype>
26#include <cstdio>
27#include <cstdlib>
28#include <cstring>
29#include <numeric>
30#include <utility>
31
32#define FOR_EACH_NODE_KIND(X) \
33 X(NodeArrayNode) \
34 X(DotSuffix) \
35 X(VendorExtQualType) \
36 X(QualType) \
37 X(ConversionOperatorType) \
38 X(PostfixQualifiedType) \
39 X(ElaboratedTypeSpefType) \
40 X(NameType) \
41 X(AbiTagAttr) \
42 X(EnableIfAttr) \
43 X(ObjCProtoName) \
44 X(PointerType) \
45 X(ReferenceType) \
46 X(PointerToMemberType) \
47 X(ArrayType) \
48 X(FunctionType) \
49 X(NoexceptSpec) \
50 X(DynamicExceptionSpec) \
51 X(FunctionEncoding) \
52 X(LiteralOperator) \
53 X(SpecialName) \
54 X(CtorVtableSpecialName) \
55 X(QualifiedName) \
56 X(NestedName) \
57 X(LocalName) \
58 X(VectorType) \
59 X(PixelVectorType) \
Richard Smithdf1c14c2019-09-06 23:53:21 +000060 X(SyntheticTemplateParamName) \
61 X(TypeTemplateParamDecl) \
62 X(NonTypeTemplateParamDecl) \
63 X(TemplateTemplateParamDecl) \
64 X(TemplateParamPackDecl) \
Richard Smithc20d1442018-08-20 20:14:49 +000065 X(ParameterPack) \
66 X(TemplateArgumentPack) \
67 X(ParameterPackExpansion) \
68 X(TemplateArgs) \
69 X(ForwardTemplateReference) \
70 X(NameWithTemplateArgs) \
71 X(GlobalQualifiedName) \
72 X(StdQualifiedName) \
73 X(ExpandedSpecialSubstitution) \
74 X(SpecialSubstitution) \
75 X(CtorDtorName) \
76 X(DtorName) \
77 X(UnnamedTypeName) \
78 X(ClosureTypeName) \
79 X(StructuredBindingName) \
80 X(BinaryExpr) \
81 X(ArraySubscriptExpr) \
82 X(PostfixExpr) \
83 X(ConditionalExpr) \
84 X(MemberExpr) \
Richard Smith1865d2f2020-10-22 19:29:36 -070085 X(SubobjectExpr) \
Richard Smithc20d1442018-08-20 20:14:49 +000086 X(EnclosingExpr) \
87 X(CastExpr) \
88 X(SizeofParamPackExpr) \
89 X(CallExpr) \
90 X(NewExpr) \
91 X(DeleteExpr) \
92 X(PrefixExpr) \
93 X(FunctionParam) \
94 X(ConversionExpr) \
Richard Smith1865d2f2020-10-22 19:29:36 -070095 X(PointerToMemberConversionExpr) \
Richard Smithc20d1442018-08-20 20:14:49 +000096 X(InitListExpr) \
97 X(FoldExpr) \
98 X(ThrowExpr) \
99 X(BoolExpr) \
Richard Smithdf1c14c2019-09-06 23:53:21 +0000100 X(StringLiteral) \
101 X(LambdaExpr) \
Erik Pilkington0a170f12020-05-13 14:13:37 -0400102 X(EnumLiteral) \
Richard Smithc20d1442018-08-20 20:14:49 +0000103 X(IntegerLiteral) \
104 X(FloatLiteral) \
105 X(DoubleLiteral) \
106 X(LongDoubleLiteral) \
107 X(BracedExpr) \
108 X(BracedRangeExpr)
109
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000110DEMANGLE_NAMESPACE_BEGIN
111
Richard Smithc20d1442018-08-20 20:14:49 +0000112// Base class of all AST nodes. The AST is built by the parser, then is
113// traversed by the printLeft/Right functions to produce a demangled string.
114class Node {
115public:
116 enum Kind : unsigned char {
117#define ENUMERATOR(NodeKind) K ## NodeKind,
118 FOR_EACH_NODE_KIND(ENUMERATOR)
119#undef ENUMERATOR
120 };
121
122 /// Three-way bool to track a cached value. Unknown is possible if this node
123 /// has an unexpanded parameter pack below it that may affect this cache.
124 enum class Cache : unsigned char { Yes, No, Unknown, };
125
126private:
127 Kind K;
128
129 // FIXME: Make these protected.
130public:
131 /// Tracks if this node has a component on its right side, in which case we
132 /// need to call printRight.
133 Cache RHSComponentCache;
134
135 /// Track if this node is a (possibly qualified) array type. This can affect
136 /// how we format the output string.
137 Cache ArrayCache;
138
139 /// Track if this node is a (possibly qualified) function type. This can
140 /// affect how we format the output string.
141 Cache FunctionCache;
142
143public:
144 Node(Kind K_, Cache RHSComponentCache_ = Cache::No,
145 Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No)
146 : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),
147 FunctionCache(FunctionCache_) {}
148
149 /// Visit the most-derived object corresponding to this object.
150 template<typename Fn> void visit(Fn F) const;
151
152 // The following function is provided by all derived classes:
153 //
154 // Call F with arguments that, when passed to the constructor of this node,
155 // would construct an equivalent node.
156 //template<typename Fn> void match(Fn F) const;
157
158 bool hasRHSComponent(OutputStream &S) const {
159 if (RHSComponentCache != Cache::Unknown)
160 return RHSComponentCache == Cache::Yes;
161 return hasRHSComponentSlow(S);
162 }
163
164 bool hasArray(OutputStream &S) const {
165 if (ArrayCache != Cache::Unknown)
166 return ArrayCache == Cache::Yes;
167 return hasArraySlow(S);
168 }
169
170 bool hasFunction(OutputStream &S) const {
171 if (FunctionCache != Cache::Unknown)
172 return FunctionCache == Cache::Yes;
173 return hasFunctionSlow(S);
174 }
175
176 Kind getKind() const { return K; }
177
178 virtual bool hasRHSComponentSlow(OutputStream &) const { return false; }
179 virtual bool hasArraySlow(OutputStream &) const { return false; }
180 virtual bool hasFunctionSlow(OutputStream &) const { return false; }
181
182 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
183 // get at a node that actually represents some concrete syntax.
184 virtual const Node *getSyntaxNode(OutputStream &) const {
185 return this;
186 }
187
188 void print(OutputStream &S) const {
189 printLeft(S);
190 if (RHSComponentCache != Cache::No)
191 printRight(S);
192 }
193
194 // Print the "left" side of this Node into OutputStream.
195 virtual void printLeft(OutputStream &) const = 0;
196
197 // Print the "right". This distinction is necessary to represent C++ types
198 // that appear on the RHS of their subtype, such as arrays or functions.
199 // Since most types don't have such a component, provide a default
200 // implementation.
201 virtual void printRight(OutputStream &) const {}
202
203 virtual StringView getBaseName() const { return StringView(); }
204
205 // Silence compiler warnings, this dtor will never be called.
206 virtual ~Node() = default;
207
208#ifndef NDEBUG
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000209 DEMANGLE_DUMP_METHOD void dump() const;
Richard Smithc20d1442018-08-20 20:14:49 +0000210#endif
211};
212
213class NodeArray {
214 Node **Elements;
215 size_t NumElements;
216
217public:
218 NodeArray() : Elements(nullptr), NumElements(0) {}
219 NodeArray(Node **Elements_, size_t NumElements_)
220 : Elements(Elements_), NumElements(NumElements_) {}
221
222 bool empty() const { return NumElements == 0; }
223 size_t size() const { return NumElements; }
224
225 Node **begin() const { return Elements; }
226 Node **end() const { return Elements + NumElements; }
227
228 Node *operator[](size_t Idx) const { return Elements[Idx]; }
229
230 void printWithComma(OutputStream &S) const {
231 bool FirstElement = true;
232 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
233 size_t BeforeComma = S.getCurrentPosition();
234 if (!FirstElement)
235 S += ", ";
236 size_t AfterComma = S.getCurrentPosition();
237 Elements[Idx]->print(S);
238
239 // Elements[Idx] is an empty parameter pack expansion, we should erase the
240 // comma we just printed.
241 if (AfterComma == S.getCurrentPosition()) {
242 S.setCurrentPosition(BeforeComma);
243 continue;
244 }
245
246 FirstElement = false;
247 }
248 }
249};
250
251struct NodeArrayNode : Node {
252 NodeArray Array;
253 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
254
255 template<typename Fn> void match(Fn F) const { F(Array); }
256
257 void printLeft(OutputStream &S) const override {
258 Array.printWithComma(S);
259 }
260};
261
262class DotSuffix final : public Node {
263 const Node *Prefix;
264 const StringView Suffix;
265
266public:
267 DotSuffix(const Node *Prefix_, StringView Suffix_)
268 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
269
270 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
271
272 void printLeft(OutputStream &s) const override {
273 Prefix->print(s);
274 s += " (";
275 s += Suffix;
276 s += ")";
277 }
278};
279
280class VendorExtQualType final : public Node {
281 const Node *Ty;
282 StringView Ext;
283
284public:
285 VendorExtQualType(const Node *Ty_, StringView Ext_)
286 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {}
287
288 template<typename Fn> void match(Fn F) const { F(Ty, Ext); }
289
290 void printLeft(OutputStream &S) const override {
291 Ty->print(S);
292 S += " ";
293 S += Ext;
294 }
295};
296
297enum FunctionRefQual : unsigned char {
298 FrefQualNone,
299 FrefQualLValue,
300 FrefQualRValue,
301};
302
303enum Qualifiers {
304 QualNone = 0,
305 QualConst = 0x1,
306 QualVolatile = 0x2,
307 QualRestrict = 0x4,
308};
309
310inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
311 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
312}
313
Richard Smithdf1c14c2019-09-06 23:53:21 +0000314class QualType final : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +0000315protected:
316 const Qualifiers Quals;
317 const Node *Child;
318
319 void printQuals(OutputStream &S) const {
320 if (Quals & QualConst)
321 S += " const";
322 if (Quals & QualVolatile)
323 S += " volatile";
324 if (Quals & QualRestrict)
325 S += " restrict";
326 }
327
328public:
329 QualType(const Node *Child_, Qualifiers Quals_)
330 : Node(KQualType, Child_->RHSComponentCache,
331 Child_->ArrayCache, Child_->FunctionCache),
332 Quals(Quals_), Child(Child_) {}
333
334 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
335
336 bool hasRHSComponentSlow(OutputStream &S) const override {
337 return Child->hasRHSComponent(S);
338 }
339 bool hasArraySlow(OutputStream &S) const override {
340 return Child->hasArray(S);
341 }
342 bool hasFunctionSlow(OutputStream &S) const override {
343 return Child->hasFunction(S);
344 }
345
346 void printLeft(OutputStream &S) const override {
347 Child->printLeft(S);
348 printQuals(S);
349 }
350
351 void printRight(OutputStream &S) const override { Child->printRight(S); }
352};
353
354class ConversionOperatorType final : public Node {
355 const Node *Ty;
356
357public:
358 ConversionOperatorType(const Node *Ty_)
359 : Node(KConversionOperatorType), Ty(Ty_) {}
360
361 template<typename Fn> void match(Fn F) const { F(Ty); }
362
363 void printLeft(OutputStream &S) const override {
364 S += "operator ";
365 Ty->print(S);
366 }
367};
368
369class PostfixQualifiedType final : public Node {
370 const Node *Ty;
371 const StringView Postfix;
372
373public:
374 PostfixQualifiedType(Node *Ty_, StringView Postfix_)
375 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
376
377 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
378
379 void printLeft(OutputStream &s) const override {
380 Ty->printLeft(s);
381 s += Postfix;
382 }
383};
384
385class NameType final : public Node {
386 const StringView Name;
387
388public:
389 NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
390
391 template<typename Fn> void match(Fn F) const { F(Name); }
392
393 StringView getName() const { return Name; }
394 StringView getBaseName() const override { return Name; }
395
396 void printLeft(OutputStream &s) const override { s += Name; }
397};
398
399class ElaboratedTypeSpefType : public Node {
400 StringView Kind;
401 Node *Child;
402public:
403 ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
404 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
405
406 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
407
408 void printLeft(OutputStream &S) const override {
409 S += Kind;
410 S += ' ';
411 Child->print(S);
412 }
413};
414
415struct AbiTagAttr : Node {
416 Node *Base;
417 StringView Tag;
418
419 AbiTagAttr(Node* Base_, StringView Tag_)
420 : Node(KAbiTagAttr, Base_->RHSComponentCache,
421 Base_->ArrayCache, Base_->FunctionCache),
422 Base(Base_), Tag(Tag_) {}
423
424 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
425
426 void printLeft(OutputStream &S) const override {
427 Base->printLeft(S);
428 S += "[abi:";
429 S += Tag;
430 S += "]";
431 }
432};
433
434class EnableIfAttr : public Node {
435 NodeArray Conditions;
436public:
437 EnableIfAttr(NodeArray Conditions_)
438 : Node(KEnableIfAttr), Conditions(Conditions_) {}
439
440 template<typename Fn> void match(Fn F) const { F(Conditions); }
441
442 void printLeft(OutputStream &S) const override {
443 S += " [enable_if:";
444 Conditions.printWithComma(S);
445 S += ']';
446 }
447};
448
449class ObjCProtoName : public Node {
450 const Node *Ty;
451 StringView Protocol;
452
453 friend class PointerType;
454
455public:
456 ObjCProtoName(const Node *Ty_, StringView Protocol_)
457 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
458
459 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
460
461 bool isObjCObject() const {
462 return Ty->getKind() == KNameType &&
463 static_cast<const NameType *>(Ty)->getName() == "objc_object";
464 }
465
466 void printLeft(OutputStream &S) const override {
467 Ty->print(S);
468 S += "<";
469 S += Protocol;
470 S += ">";
471 }
472};
473
474class PointerType final : public Node {
475 const Node *Pointee;
476
477public:
478 PointerType(const Node *Pointee_)
479 : Node(KPointerType, Pointee_->RHSComponentCache),
480 Pointee(Pointee_) {}
481
482 template<typename Fn> void match(Fn F) const { F(Pointee); }
483
484 bool hasRHSComponentSlow(OutputStream &S) const override {
485 return Pointee->hasRHSComponent(S);
486 }
487
488 void printLeft(OutputStream &s) const override {
489 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
490 if (Pointee->getKind() != KObjCProtoName ||
491 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
492 Pointee->printLeft(s);
493 if (Pointee->hasArray(s))
494 s += " ";
495 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
496 s += "(";
497 s += "*";
498 } else {
499 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
500 s += "id<";
501 s += objcProto->Protocol;
502 s += ">";
503 }
504 }
505
506 void printRight(OutputStream &s) const override {
507 if (Pointee->getKind() != KObjCProtoName ||
508 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
509 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
510 s += ")";
511 Pointee->printRight(s);
512 }
513 }
514};
515
516enum class ReferenceKind {
517 LValue,
518 RValue,
519};
520
521// Represents either a LValue or an RValue reference type.
522class ReferenceType : public Node {
523 const Node *Pointee;
524 ReferenceKind RK;
525
526 mutable bool Printing = false;
527
528 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
529 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
530 // other combination collapses to a lvalue ref.
531 std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const {
532 auto SoFar = std::make_pair(RK, Pointee);
533 for (;;) {
534 const Node *SN = SoFar.second->getSyntaxNode(S);
535 if (SN->getKind() != KReferenceType)
536 break;
537 auto *RT = static_cast<const ReferenceType *>(SN);
538 SoFar.second = RT->Pointee;
539 SoFar.first = std::min(SoFar.first, RT->RK);
540 }
541 return SoFar;
542 }
543
544public:
545 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
546 : Node(KReferenceType, Pointee_->RHSComponentCache),
547 Pointee(Pointee_), RK(RK_) {}
548
549 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
550
551 bool hasRHSComponentSlow(OutputStream &S) const override {
552 return Pointee->hasRHSComponent(S);
553 }
554
555 void printLeft(OutputStream &s) const override {
556 if (Printing)
557 return;
558 SwapAndRestore<bool> SavePrinting(Printing, true);
559 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
560 Collapsed.second->printLeft(s);
561 if (Collapsed.second->hasArray(s))
562 s += " ";
563 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
564 s += "(";
565
566 s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
567 }
568 void printRight(OutputStream &s) const override {
569 if (Printing)
570 return;
571 SwapAndRestore<bool> SavePrinting(Printing, true);
572 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
573 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
574 s += ")";
575 Collapsed.second->printRight(s);
576 }
577};
578
579class PointerToMemberType final : public Node {
580 const Node *ClassType;
581 const Node *MemberType;
582
583public:
584 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
585 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
586 ClassType(ClassType_), MemberType(MemberType_) {}
587
588 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
589
590 bool hasRHSComponentSlow(OutputStream &S) const override {
591 return MemberType->hasRHSComponent(S);
592 }
593
594 void printLeft(OutputStream &s) const override {
595 MemberType->printLeft(s);
596 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
597 s += "(";
598 else
599 s += " ";
600 ClassType->print(s);
601 s += "::*";
602 }
603
604 void printRight(OutputStream &s) const override {
605 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
606 s += ")";
607 MemberType->printRight(s);
608 }
609};
610
Richard Smithc20d1442018-08-20 20:14:49 +0000611class ArrayType final : public Node {
612 const Node *Base;
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800613 Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000614
615public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800616 ArrayType(const Node *Base_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000617 : Node(KArrayType,
618 /*RHSComponentCache=*/Cache::Yes,
619 /*ArrayCache=*/Cache::Yes),
620 Base(Base_), Dimension(Dimension_) {}
621
622 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
623
624 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
625 bool hasArraySlow(OutputStream &) const override { return true; }
626
627 void printLeft(OutputStream &S) const override { Base->printLeft(S); }
628
629 void printRight(OutputStream &S) const override {
630 if (S.back() != ']')
631 S += " ";
632 S += "[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800633 if (Dimension)
634 Dimension->print(S);
Richard Smithc20d1442018-08-20 20:14:49 +0000635 S += "]";
636 Base->printRight(S);
637 }
638};
639
640class FunctionType final : public Node {
641 const Node *Ret;
642 NodeArray Params;
643 Qualifiers CVQuals;
644 FunctionRefQual RefQual;
645 const Node *ExceptionSpec;
646
647public:
648 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
649 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
650 : Node(KFunctionType,
651 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
652 /*FunctionCache=*/Cache::Yes),
653 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
654 ExceptionSpec(ExceptionSpec_) {}
655
656 template<typename Fn> void match(Fn F) const {
657 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
658 }
659
660 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
661 bool hasFunctionSlow(OutputStream &) const override { return true; }
662
663 // Handle C++'s ... quirky decl grammar by using the left & right
664 // distinction. Consider:
665 // int (*f(float))(char) {}
666 // f is a function that takes a float and returns a pointer to a function
667 // that takes a char and returns an int. If we're trying to print f, start
668 // by printing out the return types's left, then print our parameters, then
669 // finally print right of the return type.
670 void printLeft(OutputStream &S) const override {
671 Ret->printLeft(S);
672 S += " ";
673 }
674
675 void printRight(OutputStream &S) const override {
676 S += "(";
677 Params.printWithComma(S);
678 S += ")";
679 Ret->printRight(S);
680
681 if (CVQuals & QualConst)
682 S += " const";
683 if (CVQuals & QualVolatile)
684 S += " volatile";
685 if (CVQuals & QualRestrict)
686 S += " restrict";
687
688 if (RefQual == FrefQualLValue)
689 S += " &";
690 else if (RefQual == FrefQualRValue)
691 S += " &&";
692
693 if (ExceptionSpec != nullptr) {
694 S += ' ';
695 ExceptionSpec->print(S);
696 }
697 }
698};
699
700class NoexceptSpec : public Node {
701 const Node *E;
702public:
703 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
704
705 template<typename Fn> void match(Fn F) const { F(E); }
706
707 void printLeft(OutputStream &S) const override {
708 S += "noexcept(";
709 E->print(S);
710 S += ")";
711 }
712};
713
714class DynamicExceptionSpec : public Node {
715 NodeArray Types;
716public:
717 DynamicExceptionSpec(NodeArray Types_)
718 : Node(KDynamicExceptionSpec), Types(Types_) {}
719
720 template<typename Fn> void match(Fn F) const { F(Types); }
721
722 void printLeft(OutputStream &S) const override {
723 S += "throw(";
724 Types.printWithComma(S);
725 S += ')';
726 }
727};
728
729class FunctionEncoding final : public Node {
730 const Node *Ret;
731 const Node *Name;
732 NodeArray Params;
733 const Node *Attrs;
734 Qualifiers CVQuals;
735 FunctionRefQual RefQual;
736
737public:
738 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
739 const Node *Attrs_, Qualifiers CVQuals_,
740 FunctionRefQual RefQual_)
741 : Node(KFunctionEncoding,
742 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
743 /*FunctionCache=*/Cache::Yes),
744 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
745 CVQuals(CVQuals_), RefQual(RefQual_) {}
746
747 template<typename Fn> void match(Fn F) const {
748 F(Ret, Name, Params, Attrs, CVQuals, RefQual);
749 }
750
751 Qualifiers getCVQuals() const { return CVQuals; }
752 FunctionRefQual getRefQual() const { return RefQual; }
753 NodeArray getParams() const { return Params; }
754 const Node *getReturnType() const { return Ret; }
755
756 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
757 bool hasFunctionSlow(OutputStream &) const override { return true; }
758
759 const Node *getName() const { return Name; }
760
761 void printLeft(OutputStream &S) const override {
762 if (Ret) {
763 Ret->printLeft(S);
764 if (!Ret->hasRHSComponent(S))
765 S += " ";
766 }
767 Name->print(S);
768 }
769
770 void printRight(OutputStream &S) const override {
771 S += "(";
772 Params.printWithComma(S);
773 S += ")";
774 if (Ret)
775 Ret->printRight(S);
776
777 if (CVQuals & QualConst)
778 S += " const";
779 if (CVQuals & QualVolatile)
780 S += " volatile";
781 if (CVQuals & QualRestrict)
782 S += " restrict";
783
784 if (RefQual == FrefQualLValue)
785 S += " &";
786 else if (RefQual == FrefQualRValue)
787 S += " &&";
788
789 if (Attrs != nullptr)
790 Attrs->print(S);
791 }
792};
793
794class LiteralOperator : public Node {
795 const Node *OpName;
796
797public:
798 LiteralOperator(const Node *OpName_)
799 : Node(KLiteralOperator), OpName(OpName_) {}
800
801 template<typename Fn> void match(Fn F) const { F(OpName); }
802
803 void printLeft(OutputStream &S) const override {
804 S += "operator\"\" ";
805 OpName->print(S);
806 }
807};
808
809class SpecialName final : public Node {
810 const StringView Special;
811 const Node *Child;
812
813public:
814 SpecialName(StringView Special_, const Node *Child_)
815 : Node(KSpecialName), Special(Special_), Child(Child_) {}
816
817 template<typename Fn> void match(Fn F) const { F(Special, Child); }
818
819 void printLeft(OutputStream &S) const override {
820 S += Special;
821 Child->print(S);
822 }
823};
824
825class CtorVtableSpecialName final : public Node {
826 const Node *FirstType;
827 const Node *SecondType;
828
829public:
830 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
831 : Node(KCtorVtableSpecialName),
832 FirstType(FirstType_), SecondType(SecondType_) {}
833
834 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
835
836 void printLeft(OutputStream &S) const override {
837 S += "construction vtable for ";
838 FirstType->print(S);
839 S += "-in-";
840 SecondType->print(S);
841 }
842};
843
844struct NestedName : Node {
845 Node *Qual;
846 Node *Name;
847
848 NestedName(Node *Qual_, Node *Name_)
849 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
850
851 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
852
853 StringView getBaseName() const override { return Name->getBaseName(); }
854
855 void printLeft(OutputStream &S) const override {
856 Qual->print(S);
857 S += "::";
858 Name->print(S);
859 }
860};
861
862struct LocalName : Node {
863 Node *Encoding;
864 Node *Entity;
865
866 LocalName(Node *Encoding_, Node *Entity_)
867 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
868
869 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
870
871 void printLeft(OutputStream &S) const override {
872 Encoding->print(S);
873 S += "::";
874 Entity->print(S);
875 }
876};
877
878class QualifiedName final : public Node {
879 // qualifier::name
880 const Node *Qualifier;
881 const Node *Name;
882
883public:
884 QualifiedName(const Node *Qualifier_, const Node *Name_)
885 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
886
887 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
888
889 StringView getBaseName() const override { return Name->getBaseName(); }
890
891 void printLeft(OutputStream &S) const override {
892 Qualifier->print(S);
893 S += "::";
894 Name->print(S);
895 }
896};
897
898class VectorType final : public Node {
899 const Node *BaseType;
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800900 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000901
902public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800903 VectorType(const Node *BaseType_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000904 : Node(KVectorType), BaseType(BaseType_),
905 Dimension(Dimension_) {}
906
907 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
908
909 void printLeft(OutputStream &S) const override {
910 BaseType->print(S);
911 S += " vector[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800912 if (Dimension)
913 Dimension->print(S);
Richard Smithc20d1442018-08-20 20:14:49 +0000914 S += "]";
915 }
916};
917
918class PixelVectorType final : public Node {
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800919 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000920
921public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800922 PixelVectorType(const Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000923 : Node(KPixelVectorType), Dimension(Dimension_) {}
924
925 template<typename Fn> void match(Fn F) const { F(Dimension); }
926
927 void printLeft(OutputStream &S) const override {
928 // FIXME: This should demangle as "vector pixel".
929 S += "pixel vector[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800930 Dimension->print(S);
Richard Smithc20d1442018-08-20 20:14:49 +0000931 S += "]";
932 }
933};
934
Richard Smithdf1c14c2019-09-06 23:53:21 +0000935enum class TemplateParamKind { Type, NonType, Template };
936
937/// An invented name for a template parameter for which we don't have a
938/// corresponding template argument.
939///
940/// This node is created when parsing the <lambda-sig> for a lambda with
941/// explicit template arguments, which might be referenced in the parameter
942/// types appearing later in the <lambda-sig>.
943class SyntheticTemplateParamName final : public Node {
944 TemplateParamKind Kind;
945 unsigned Index;
946
947public:
948 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
949 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
950
951 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
952
953 void printLeft(OutputStream &S) const override {
954 switch (Kind) {
955 case TemplateParamKind::Type:
956 S += "$T";
957 break;
958 case TemplateParamKind::NonType:
959 S += "$N";
960 break;
961 case TemplateParamKind::Template:
962 S += "$TT";
963 break;
964 }
965 if (Index > 0)
966 S << Index - 1;
967 }
968};
969
970/// A template type parameter declaration, 'typename T'.
971class TypeTemplateParamDecl final : public Node {
972 Node *Name;
973
974public:
975 TypeTemplateParamDecl(Node *Name_)
976 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
977
978 template<typename Fn> void match(Fn F) const { F(Name); }
979
980 void printLeft(OutputStream &S) const override {
981 S += "typename ";
982 }
983
984 void printRight(OutputStream &S) const override {
985 Name->print(S);
986 }
987};
988
989/// A non-type template parameter declaration, 'int N'.
990class NonTypeTemplateParamDecl final : public Node {
991 Node *Name;
992 Node *Type;
993
994public:
995 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
996 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
997
998 template<typename Fn> void match(Fn F) const { F(Name, Type); }
999
1000 void printLeft(OutputStream &S) const override {
1001 Type->printLeft(S);
1002 if (!Type->hasRHSComponent(S))
1003 S += " ";
1004 }
1005
1006 void printRight(OutputStream &S) const override {
1007 Name->print(S);
1008 Type->printRight(S);
1009 }
1010};
1011
1012/// A template template parameter declaration,
1013/// 'template<typename T> typename N'.
1014class TemplateTemplateParamDecl final : public Node {
1015 Node *Name;
1016 NodeArray Params;
1017
1018public:
1019 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
1020 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1021 Params(Params_) {}
1022
1023 template<typename Fn> void match(Fn F) const { F(Name, Params); }
1024
1025 void printLeft(OutputStream &S) const override {
1026 S += "template<";
1027 Params.printWithComma(S);
1028 S += "> typename ";
1029 }
1030
1031 void printRight(OutputStream &S) const override {
1032 Name->print(S);
1033 }
1034};
1035
1036/// A template parameter pack declaration, 'typename ...T'.
1037class TemplateParamPackDecl final : public Node {
1038 Node *Param;
1039
1040public:
1041 TemplateParamPackDecl(Node *Param_)
1042 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1043
1044 template<typename Fn> void match(Fn F) const { F(Param); }
1045
1046 void printLeft(OutputStream &S) const override {
1047 Param->printLeft(S);
1048 S += "...";
1049 }
1050
1051 void printRight(OutputStream &S) const override {
1052 Param->printRight(S);
1053 }
1054};
1055
Richard Smithc20d1442018-08-20 20:14:49 +00001056/// An unexpanded parameter pack (either in the expression or type context). If
1057/// this AST is correct, this node will have a ParameterPackExpansion node above
1058/// it.
1059///
1060/// This node is created when some <template-args> are found that apply to an
1061/// <encoding>, and is stored in the TemplateParams table. In order for this to
1062/// appear in the final AST, it has to referenced via a <template-param> (ie,
1063/// T_).
1064class ParameterPack final : public Node {
1065 NodeArray Data;
1066
1067 // Setup OutputStream for a pack expansion unless we're already expanding one.
1068 void initializePackExpansion(OutputStream &S) const {
1069 if (S.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1070 S.CurrentPackMax = static_cast<unsigned>(Data.size());
1071 S.CurrentPackIndex = 0;
1072 }
1073 }
1074
1075public:
1076 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1077 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
1078 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1079 return P->ArrayCache == Cache::No;
1080 }))
1081 ArrayCache = Cache::No;
1082 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1083 return P->FunctionCache == Cache::No;
1084 }))
1085 FunctionCache = Cache::No;
1086 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1087 return P->RHSComponentCache == Cache::No;
1088 }))
1089 RHSComponentCache = Cache::No;
1090 }
1091
1092 template<typename Fn> void match(Fn F) const { F(Data); }
1093
1094 bool hasRHSComponentSlow(OutputStream &S) const override {
1095 initializePackExpansion(S);
1096 size_t Idx = S.CurrentPackIndex;
1097 return Idx < Data.size() && Data[Idx]->hasRHSComponent(S);
1098 }
1099 bool hasArraySlow(OutputStream &S) const override {
1100 initializePackExpansion(S);
1101 size_t Idx = S.CurrentPackIndex;
1102 return Idx < Data.size() && Data[Idx]->hasArray(S);
1103 }
1104 bool hasFunctionSlow(OutputStream &S) const override {
1105 initializePackExpansion(S);
1106 size_t Idx = S.CurrentPackIndex;
1107 return Idx < Data.size() && Data[Idx]->hasFunction(S);
1108 }
1109 const Node *getSyntaxNode(OutputStream &S) const override {
1110 initializePackExpansion(S);
1111 size_t Idx = S.CurrentPackIndex;
1112 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this;
1113 }
1114
1115 void printLeft(OutputStream &S) const override {
1116 initializePackExpansion(S);
1117 size_t Idx = S.CurrentPackIndex;
1118 if (Idx < Data.size())
1119 Data[Idx]->printLeft(S);
1120 }
1121 void printRight(OutputStream &S) const override {
1122 initializePackExpansion(S);
1123 size_t Idx = S.CurrentPackIndex;
1124 if (Idx < Data.size())
1125 Data[Idx]->printRight(S);
1126 }
1127};
1128
1129/// A variadic template argument. This node represents an occurrence of
1130/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1131/// one of it's Elements is. The parser inserts a ParameterPack into the
1132/// TemplateParams table if the <template-args> this pack belongs to apply to an
1133/// <encoding>.
1134class TemplateArgumentPack final : public Node {
1135 NodeArray Elements;
1136public:
1137 TemplateArgumentPack(NodeArray Elements_)
1138 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1139
1140 template<typename Fn> void match(Fn F) const { F(Elements); }
1141
1142 NodeArray getElements() const { return Elements; }
1143
1144 void printLeft(OutputStream &S) const override {
1145 Elements.printWithComma(S);
1146 }
1147};
1148
1149/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1150/// which each have Child->ParameterPackSize elements.
1151class ParameterPackExpansion final : public Node {
1152 const Node *Child;
1153
1154public:
1155 ParameterPackExpansion(const Node *Child_)
1156 : Node(KParameterPackExpansion), Child(Child_) {}
1157
1158 template<typename Fn> void match(Fn F) const { F(Child); }
1159
1160 const Node *getChild() const { return Child; }
1161
1162 void printLeft(OutputStream &S) const override {
1163 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
1164 SwapAndRestore<unsigned> SavePackIdx(S.CurrentPackIndex, Max);
1165 SwapAndRestore<unsigned> SavePackMax(S.CurrentPackMax, Max);
1166 size_t StreamPos = S.getCurrentPosition();
1167
1168 // Print the first element in the pack. If Child contains a ParameterPack,
1169 // it will set up S.CurrentPackMax and print the first element.
1170 Child->print(S);
1171
1172 // No ParameterPack was found in Child. This can occur if we've found a pack
1173 // expansion on a <function-param>.
1174 if (S.CurrentPackMax == Max) {
1175 S += "...";
1176 return;
1177 }
1178
1179 // We found a ParameterPack, but it has no elements. Erase whatever we may
1180 // of printed.
1181 if (S.CurrentPackMax == 0) {
1182 S.setCurrentPosition(StreamPos);
1183 return;
1184 }
1185
1186 // Else, iterate through the rest of the elements in the pack.
1187 for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) {
1188 S += ", ";
1189 S.CurrentPackIndex = I;
1190 Child->print(S);
1191 }
1192 }
1193};
1194
1195class TemplateArgs final : public Node {
1196 NodeArray Params;
1197
1198public:
1199 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1200
1201 template<typename Fn> void match(Fn F) const { F(Params); }
1202
1203 NodeArray getParams() { return Params; }
1204
1205 void printLeft(OutputStream &S) const override {
1206 S += "<";
1207 Params.printWithComma(S);
1208 if (S.back() == '>')
1209 S += " ";
1210 S += ">";
1211 }
1212};
1213
Richard Smithb485b352018-08-24 23:30:26 +00001214/// A forward-reference to a template argument that was not known at the point
1215/// where the template parameter name was parsed in a mangling.
1216///
1217/// This is created when demangling the name of a specialization of a
1218/// conversion function template:
1219///
1220/// \code
1221/// struct A {
1222/// template<typename T> operator T*();
1223/// };
1224/// \endcode
1225///
1226/// When demangling a specialization of the conversion function template, we
1227/// encounter the name of the template (including the \c T) before we reach
1228/// the template argument list, so we cannot substitute the parameter name
1229/// for the corresponding argument while parsing. Instead, we create a
1230/// \c ForwardTemplateReference node that is resolved after we parse the
1231/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001232struct ForwardTemplateReference : Node {
1233 size_t Index;
1234 Node *Ref = nullptr;
1235
1236 // If we're currently printing this node. It is possible (though invalid) for
1237 // a forward template reference to refer to itself via a substitution. This
1238 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1239 // out if more than one print* function is active.
1240 mutable bool Printing = false;
1241
1242 ForwardTemplateReference(size_t Index_)
1243 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1244 Cache::Unknown),
1245 Index(Index_) {}
1246
1247 // We don't provide a matcher for these, because the value of the node is
1248 // not determined by its construction parameters, and it generally needs
1249 // special handling.
1250 template<typename Fn> void match(Fn F) const = delete;
1251
1252 bool hasRHSComponentSlow(OutputStream &S) const override {
1253 if (Printing)
1254 return false;
1255 SwapAndRestore<bool> SavePrinting(Printing, true);
1256 return Ref->hasRHSComponent(S);
1257 }
1258 bool hasArraySlow(OutputStream &S) const override {
1259 if (Printing)
1260 return false;
1261 SwapAndRestore<bool> SavePrinting(Printing, true);
1262 return Ref->hasArray(S);
1263 }
1264 bool hasFunctionSlow(OutputStream &S) const override {
1265 if (Printing)
1266 return false;
1267 SwapAndRestore<bool> SavePrinting(Printing, true);
1268 return Ref->hasFunction(S);
1269 }
1270 const Node *getSyntaxNode(OutputStream &S) const override {
1271 if (Printing)
1272 return this;
1273 SwapAndRestore<bool> SavePrinting(Printing, true);
1274 return Ref->getSyntaxNode(S);
1275 }
1276
1277 void printLeft(OutputStream &S) const override {
1278 if (Printing)
1279 return;
1280 SwapAndRestore<bool> SavePrinting(Printing, true);
1281 Ref->printLeft(S);
1282 }
1283 void printRight(OutputStream &S) const override {
1284 if (Printing)
1285 return;
1286 SwapAndRestore<bool> SavePrinting(Printing, true);
1287 Ref->printRight(S);
1288 }
1289};
1290
1291struct NameWithTemplateArgs : Node {
1292 // name<template_args>
1293 Node *Name;
1294 Node *TemplateArgs;
1295
1296 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1297 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1298
1299 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1300
1301 StringView getBaseName() const override { return Name->getBaseName(); }
1302
1303 void printLeft(OutputStream &S) const override {
1304 Name->print(S);
1305 TemplateArgs->print(S);
1306 }
1307};
1308
1309class GlobalQualifiedName final : public Node {
1310 Node *Child;
1311
1312public:
1313 GlobalQualifiedName(Node* Child_)
1314 : Node(KGlobalQualifiedName), Child(Child_) {}
1315
1316 template<typename Fn> void match(Fn F) const { F(Child); }
1317
1318 StringView getBaseName() const override { return Child->getBaseName(); }
1319
1320 void printLeft(OutputStream &S) const override {
1321 S += "::";
1322 Child->print(S);
1323 }
1324};
1325
1326struct StdQualifiedName : Node {
1327 Node *Child;
1328
1329 StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {}
1330
1331 template<typename Fn> void match(Fn F) const { F(Child); }
1332
1333 StringView getBaseName() const override { return Child->getBaseName(); }
1334
1335 void printLeft(OutputStream &S) const override {
1336 S += "std::";
1337 Child->print(S);
1338 }
1339};
1340
1341enum class SpecialSubKind {
1342 allocator,
1343 basic_string,
1344 string,
1345 istream,
1346 ostream,
1347 iostream,
1348};
1349
1350class ExpandedSpecialSubstitution final : public Node {
1351 SpecialSubKind SSK;
1352
1353public:
1354 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1355 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1356
1357 template<typename Fn> void match(Fn F) const { F(SSK); }
1358
1359 StringView getBaseName() const override {
1360 switch (SSK) {
1361 case SpecialSubKind::allocator:
1362 return StringView("allocator");
1363 case SpecialSubKind::basic_string:
1364 return StringView("basic_string");
1365 case SpecialSubKind::string:
1366 return StringView("basic_string");
1367 case SpecialSubKind::istream:
1368 return StringView("basic_istream");
1369 case SpecialSubKind::ostream:
1370 return StringView("basic_ostream");
1371 case SpecialSubKind::iostream:
1372 return StringView("basic_iostream");
1373 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001374 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001375 }
1376
1377 void printLeft(OutputStream &S) const override {
1378 switch (SSK) {
1379 case SpecialSubKind::allocator:
Richard Smithb485b352018-08-24 23:30:26 +00001380 S += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001381 break;
1382 case SpecialSubKind::basic_string:
Richard Smithb485b352018-08-24 23:30:26 +00001383 S += "std::basic_string";
1384 break;
Richard Smithc20d1442018-08-20 20:14:49 +00001385 case SpecialSubKind::string:
1386 S += "std::basic_string<char, std::char_traits<char>, "
1387 "std::allocator<char> >";
1388 break;
1389 case SpecialSubKind::istream:
1390 S += "std::basic_istream<char, std::char_traits<char> >";
1391 break;
1392 case SpecialSubKind::ostream:
1393 S += "std::basic_ostream<char, std::char_traits<char> >";
1394 break;
1395 case SpecialSubKind::iostream:
1396 S += "std::basic_iostream<char, std::char_traits<char> >";
1397 break;
1398 }
1399 }
1400};
1401
1402class SpecialSubstitution final : public Node {
1403public:
1404 SpecialSubKind SSK;
1405
1406 SpecialSubstitution(SpecialSubKind SSK_)
1407 : Node(KSpecialSubstitution), SSK(SSK_) {}
1408
1409 template<typename Fn> void match(Fn F) const { F(SSK); }
1410
1411 StringView getBaseName() const override {
1412 switch (SSK) {
1413 case SpecialSubKind::allocator:
1414 return StringView("allocator");
1415 case SpecialSubKind::basic_string:
1416 return StringView("basic_string");
1417 case SpecialSubKind::string:
1418 return StringView("string");
1419 case SpecialSubKind::istream:
1420 return StringView("istream");
1421 case SpecialSubKind::ostream:
1422 return StringView("ostream");
1423 case SpecialSubKind::iostream:
1424 return StringView("iostream");
1425 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001426 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001427 }
1428
1429 void printLeft(OutputStream &S) const override {
1430 switch (SSK) {
1431 case SpecialSubKind::allocator:
1432 S += "std::allocator";
1433 break;
1434 case SpecialSubKind::basic_string:
1435 S += "std::basic_string";
1436 break;
1437 case SpecialSubKind::string:
1438 S += "std::string";
1439 break;
1440 case SpecialSubKind::istream:
1441 S += "std::istream";
1442 break;
1443 case SpecialSubKind::ostream:
1444 S += "std::ostream";
1445 break;
1446 case SpecialSubKind::iostream:
1447 S += "std::iostream";
1448 break;
1449 }
1450 }
1451};
1452
1453class CtorDtorName final : public Node {
1454 const Node *Basename;
1455 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001456 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001457
1458public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001459 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1460 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1461 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001462
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001463 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001464
1465 void printLeft(OutputStream &S) const override {
1466 if (IsDtor)
1467 S += "~";
1468 S += Basename->getBaseName();
1469 }
1470};
1471
1472class DtorName : public Node {
1473 const Node *Base;
1474
1475public:
1476 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1477
1478 template<typename Fn> void match(Fn F) const { F(Base); }
1479
1480 void printLeft(OutputStream &S) const override {
1481 S += "~";
1482 Base->printLeft(S);
1483 }
1484};
1485
1486class UnnamedTypeName : public Node {
1487 const StringView Count;
1488
1489public:
1490 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1491
1492 template<typename Fn> void match(Fn F) const { F(Count); }
1493
1494 void printLeft(OutputStream &S) const override {
1495 S += "'unnamed";
1496 S += Count;
1497 S += "\'";
1498 }
1499};
1500
1501class ClosureTypeName : public Node {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001502 NodeArray TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00001503 NodeArray Params;
1504 StringView Count;
1505
1506public:
Richard Smithdf1c14c2019-09-06 23:53:21 +00001507 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1508 StringView Count_)
1509 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1510 Params(Params_), Count(Count_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001511
Richard Smithdf1c14c2019-09-06 23:53:21 +00001512 template<typename Fn> void match(Fn F) const {
1513 F(TemplateParams, Params, Count);
1514 }
1515
1516 void printDeclarator(OutputStream &S) const {
1517 if (!TemplateParams.empty()) {
1518 S += "<";
1519 TemplateParams.printWithComma(S);
1520 S += ">";
1521 }
1522 S += "(";
1523 Params.printWithComma(S);
1524 S += ")";
1525 }
Richard Smithc20d1442018-08-20 20:14:49 +00001526
1527 void printLeft(OutputStream &S) const override {
1528 S += "\'lambda";
1529 S += Count;
Richard Smithdf1c14c2019-09-06 23:53:21 +00001530 S += "\'";
1531 printDeclarator(S);
Richard Smithc20d1442018-08-20 20:14:49 +00001532 }
1533};
1534
1535class StructuredBindingName : public Node {
1536 NodeArray Bindings;
1537public:
1538 StructuredBindingName(NodeArray Bindings_)
1539 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1540
1541 template<typename Fn> void match(Fn F) const { F(Bindings); }
1542
1543 void printLeft(OutputStream &S) const override {
1544 S += '[';
1545 Bindings.printWithComma(S);
1546 S += ']';
1547 }
1548};
1549
1550// -- Expression Nodes --
1551
1552class BinaryExpr : public Node {
1553 const Node *LHS;
1554 const StringView InfixOperator;
1555 const Node *RHS;
1556
1557public:
1558 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_)
1559 : Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {
1560 }
1561
1562 template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }
1563
1564 void printLeft(OutputStream &S) const override {
1565 // might be a template argument expression, then we need to disambiguate
1566 // with parens.
1567 if (InfixOperator == ">")
1568 S += "(";
1569
1570 S += "(";
1571 LHS->print(S);
1572 S += ") ";
1573 S += InfixOperator;
1574 S += " (";
1575 RHS->print(S);
1576 S += ")";
1577
1578 if (InfixOperator == ">")
1579 S += ")";
1580 }
1581};
1582
1583class ArraySubscriptExpr : public Node {
1584 const Node *Op1;
1585 const Node *Op2;
1586
1587public:
1588 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_)
1589 : Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {}
1590
1591 template<typename Fn> void match(Fn F) const { F(Op1, Op2); }
1592
1593 void printLeft(OutputStream &S) const override {
1594 S += "(";
1595 Op1->print(S);
1596 S += ")[";
1597 Op2->print(S);
1598 S += "]";
1599 }
1600};
1601
1602class PostfixExpr : public Node {
1603 const Node *Child;
1604 const StringView Operator;
1605
1606public:
1607 PostfixExpr(const Node *Child_, StringView Operator_)
1608 : Node(KPostfixExpr), Child(Child_), Operator(Operator_) {}
1609
1610 template<typename Fn> void match(Fn F) const { F(Child, Operator); }
1611
1612 void printLeft(OutputStream &S) const override {
1613 S += "(";
1614 Child->print(S);
1615 S += ")";
1616 S += Operator;
1617 }
1618};
1619
1620class ConditionalExpr : public Node {
1621 const Node *Cond;
1622 const Node *Then;
1623 const Node *Else;
1624
1625public:
1626 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_)
1627 : Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {}
1628
1629 template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }
1630
1631 void printLeft(OutputStream &S) const override {
1632 S += "(";
1633 Cond->print(S);
1634 S += ") ? (";
1635 Then->print(S);
1636 S += ") : (";
1637 Else->print(S);
1638 S += ")";
1639 }
1640};
1641
1642class MemberExpr : public Node {
1643 const Node *LHS;
1644 const StringView Kind;
1645 const Node *RHS;
1646
1647public:
1648 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_)
1649 : Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
1650
1651 template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }
1652
1653 void printLeft(OutputStream &S) const override {
1654 LHS->print(S);
1655 S += Kind;
1656 RHS->print(S);
1657 }
1658};
1659
Richard Smith1865d2f2020-10-22 19:29:36 -07001660class SubobjectExpr : public Node {
1661 const Node *Type;
1662 const Node *SubExpr;
1663 StringView Offset;
1664 NodeArray UnionSelectors;
1665 bool OnePastTheEnd;
1666
1667public:
1668 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1669 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1670 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1671 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1672
1673 template<typename Fn> void match(Fn F) const {
1674 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1675 }
1676
1677 void printLeft(OutputStream &S) const override {
1678 SubExpr->print(S);
1679 S += ".<";
1680 Type->print(S);
1681 S += " at offset ";
1682 if (Offset.empty()) {
1683 S += "0";
1684 } else if (Offset[0] == 'n') {
1685 S += "-";
1686 S += Offset.dropFront();
1687 } else {
1688 S += Offset;
1689 }
1690 S += ">";
1691 }
1692};
1693
Richard Smithc20d1442018-08-20 20:14:49 +00001694class EnclosingExpr : public Node {
1695 const StringView Prefix;
1696 const Node *Infix;
1697 const StringView Postfix;
1698
1699public:
1700 EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_)
1701 : Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_),
1702 Postfix(Postfix_) {}
1703
1704 template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); }
1705
1706 void printLeft(OutputStream &S) const override {
1707 S += Prefix;
1708 Infix->print(S);
1709 S += Postfix;
1710 }
1711};
1712
1713class CastExpr : public Node {
1714 // cast_kind<to>(from)
1715 const StringView CastKind;
1716 const Node *To;
1717 const Node *From;
1718
1719public:
1720 CastExpr(StringView CastKind_, const Node *To_, const Node *From_)
1721 : Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {}
1722
1723 template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }
1724
1725 void printLeft(OutputStream &S) const override {
1726 S += CastKind;
1727 S += "<";
1728 To->printLeft(S);
1729 S += ">(";
1730 From->printLeft(S);
1731 S += ")";
1732 }
1733};
1734
1735class SizeofParamPackExpr : public Node {
1736 const Node *Pack;
1737
1738public:
1739 SizeofParamPackExpr(const Node *Pack_)
1740 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1741
1742 template<typename Fn> void match(Fn F) const { F(Pack); }
1743
1744 void printLeft(OutputStream &S) const override {
1745 S += "sizeof...(";
1746 ParameterPackExpansion PPE(Pack);
1747 PPE.printLeft(S);
1748 S += ")";
1749 }
1750};
1751
1752class CallExpr : public Node {
1753 const Node *Callee;
1754 NodeArray Args;
1755
1756public:
1757 CallExpr(const Node *Callee_, NodeArray Args_)
1758 : Node(KCallExpr), Callee(Callee_), Args(Args_) {}
1759
1760 template<typename Fn> void match(Fn F) const { F(Callee, Args); }
1761
1762 void printLeft(OutputStream &S) const override {
1763 Callee->print(S);
1764 S += "(";
1765 Args.printWithComma(S);
1766 S += ")";
1767 }
1768};
1769
1770class NewExpr : public Node {
1771 // new (expr_list) type(init_list)
1772 NodeArray ExprList;
1773 Node *Type;
1774 NodeArray InitList;
1775 bool IsGlobal; // ::operator new ?
1776 bool IsArray; // new[] ?
1777public:
1778 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
1779 bool IsArray_)
1780 : Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_),
1781 IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1782
1783 template<typename Fn> void match(Fn F) const {
1784 F(ExprList, Type, InitList, IsGlobal, IsArray);
1785 }
1786
1787 void printLeft(OutputStream &S) const override {
1788 if (IsGlobal)
1789 S += "::operator ";
1790 S += "new";
1791 if (IsArray)
1792 S += "[]";
1793 S += ' ';
1794 if (!ExprList.empty()) {
1795 S += "(";
1796 ExprList.printWithComma(S);
1797 S += ")";
1798 }
1799 Type->print(S);
1800 if (!InitList.empty()) {
1801 S += "(";
1802 InitList.printWithComma(S);
1803 S += ")";
1804 }
1805
1806 }
1807};
1808
1809class DeleteExpr : public Node {
1810 Node *Op;
1811 bool IsGlobal;
1812 bool IsArray;
1813
1814public:
1815 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_)
1816 : Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1817
1818 template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }
1819
1820 void printLeft(OutputStream &S) const override {
1821 if (IsGlobal)
1822 S += "::";
1823 S += "delete";
1824 if (IsArray)
1825 S += "[] ";
1826 Op->print(S);
1827 }
1828};
1829
1830class PrefixExpr : public Node {
1831 StringView Prefix;
1832 Node *Child;
1833
1834public:
1835 PrefixExpr(StringView Prefix_, Node *Child_)
1836 : Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {}
1837
1838 template<typename Fn> void match(Fn F) const { F(Prefix, Child); }
1839
1840 void printLeft(OutputStream &S) const override {
1841 S += Prefix;
1842 S += "(";
1843 Child->print(S);
1844 S += ")";
1845 }
1846};
1847
1848class FunctionParam : public Node {
1849 StringView Number;
1850
1851public:
1852 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
1853
1854 template<typename Fn> void match(Fn F) const { F(Number); }
1855
1856 void printLeft(OutputStream &S) const override {
1857 S += "fp";
1858 S += Number;
1859 }
1860};
1861
1862class ConversionExpr : public Node {
1863 const Node *Type;
1864 NodeArray Expressions;
1865
1866public:
1867 ConversionExpr(const Node *Type_, NodeArray Expressions_)
1868 : Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {}
1869
1870 template<typename Fn> void match(Fn F) const { F(Type, Expressions); }
1871
1872 void printLeft(OutputStream &S) const override {
1873 S += "(";
1874 Type->print(S);
1875 S += ")(";
1876 Expressions.printWithComma(S);
1877 S += ")";
1878 }
1879};
1880
Richard Smith1865d2f2020-10-22 19:29:36 -07001881class PointerToMemberConversionExpr : public Node {
1882 const Node *Type;
1883 const Node *SubExpr;
1884 StringView Offset;
1885
1886public:
1887 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
1888 StringView Offset_)
1889 : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_),
1890 Offset(Offset_) {}
1891
1892 template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }
1893
1894 void printLeft(OutputStream &S) const override {
1895 S += "(";
1896 Type->print(S);
1897 S += ")(";
1898 SubExpr->print(S);
1899 S += ")";
1900 }
1901};
1902
Richard Smithc20d1442018-08-20 20:14:49 +00001903class InitListExpr : public Node {
1904 const Node *Ty;
1905 NodeArray Inits;
1906public:
1907 InitListExpr(const Node *Ty_, NodeArray Inits_)
1908 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
1909
1910 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
1911
1912 void printLeft(OutputStream &S) const override {
1913 if (Ty)
1914 Ty->print(S);
1915 S += '{';
1916 Inits.printWithComma(S);
1917 S += '}';
1918 }
1919};
1920
1921class BracedExpr : public Node {
1922 const Node *Elem;
1923 const Node *Init;
1924 bool IsArray;
1925public:
1926 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
1927 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
1928
1929 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
1930
1931 void printLeft(OutputStream &S) const override {
1932 if (IsArray) {
1933 S += '[';
1934 Elem->print(S);
1935 S += ']';
1936 } else {
1937 S += '.';
1938 Elem->print(S);
1939 }
1940 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1941 S += " = ";
1942 Init->print(S);
1943 }
1944};
1945
1946class BracedRangeExpr : public Node {
1947 const Node *First;
1948 const Node *Last;
1949 const Node *Init;
1950public:
1951 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
1952 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
1953
1954 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
1955
1956 void printLeft(OutputStream &S) const override {
1957 S += '[';
1958 First->print(S);
1959 S += " ... ";
1960 Last->print(S);
1961 S += ']';
1962 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1963 S += " = ";
1964 Init->print(S);
1965 }
1966};
1967
1968class FoldExpr : public Node {
1969 const Node *Pack, *Init;
1970 StringView OperatorName;
1971 bool IsLeftFold;
1972
1973public:
1974 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
1975 const Node *Init_)
1976 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
1977 IsLeftFold(IsLeftFold_) {}
1978
1979 template<typename Fn> void match(Fn F) const {
1980 F(IsLeftFold, OperatorName, Pack, Init);
1981 }
1982
1983 void printLeft(OutputStream &S) const override {
1984 auto PrintPack = [&] {
1985 S += '(';
1986 ParameterPackExpansion(Pack).print(S);
1987 S += ')';
1988 };
1989
1990 S += '(';
1991
1992 if (IsLeftFold) {
1993 // init op ... op pack
1994 if (Init != nullptr) {
1995 Init->print(S);
1996 S += ' ';
1997 S += OperatorName;
1998 S += ' ';
1999 }
2000 // ... op pack
2001 S += "... ";
2002 S += OperatorName;
2003 S += ' ';
2004 PrintPack();
2005 } else { // !IsLeftFold
2006 // pack op ...
2007 PrintPack();
2008 S += ' ';
2009 S += OperatorName;
2010 S += " ...";
2011 // pack op ... op init
2012 if (Init != nullptr) {
2013 S += ' ';
2014 S += OperatorName;
2015 S += ' ';
2016 Init->print(S);
2017 }
2018 }
2019 S += ')';
2020 }
2021};
2022
2023class ThrowExpr : public Node {
2024 const Node *Op;
2025
2026public:
2027 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2028
2029 template<typename Fn> void match(Fn F) const { F(Op); }
2030
2031 void printLeft(OutputStream &S) const override {
2032 S += "throw ";
2033 Op->print(S);
2034 }
2035};
2036
2037class BoolExpr : public Node {
2038 bool Value;
2039
2040public:
2041 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2042
2043 template<typename Fn> void match(Fn F) const { F(Value); }
2044
2045 void printLeft(OutputStream &S) const override {
2046 S += Value ? StringView("true") : StringView("false");
2047 }
2048};
2049
Richard Smithdf1c14c2019-09-06 23:53:21 +00002050class StringLiteral : public Node {
2051 const Node *Type;
2052
2053public:
2054 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2055
2056 template<typename Fn> void match(Fn F) const { F(Type); }
2057
2058 void printLeft(OutputStream &S) const override {
2059 S += "\"<";
2060 Type->print(S);
2061 S += ">\"";
2062 }
2063};
2064
2065class LambdaExpr : public Node {
2066 const Node *Type;
2067
Richard Smithdf1c14c2019-09-06 23:53:21 +00002068public:
2069 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2070
2071 template<typename Fn> void match(Fn F) const { F(Type); }
2072
2073 void printLeft(OutputStream &S) const override {
2074 S += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002075 if (Type->getKind() == KClosureTypeName)
2076 static_cast<const ClosureTypeName *>(Type)->printDeclarator(S);
Richard Smithdf1c14c2019-09-06 23:53:21 +00002077 S += "{...}";
2078 }
2079};
2080
Erik Pilkington0a170f12020-05-13 14:13:37 -04002081class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002082 // ty(integer)
2083 const Node *Ty;
2084 StringView Integer;
2085
2086public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002087 EnumLiteral(const Node *Ty_, StringView Integer_)
2088 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002089
2090 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2091
2092 void printLeft(OutputStream &S) const override {
Erik Pilkington0a170f12020-05-13 14:13:37 -04002093 S << "(";
Richard Smithc20d1442018-08-20 20:14:49 +00002094 Ty->print(S);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002095 S << ")";
2096
2097 if (Integer[0] == 'n')
2098 S << "-" << Integer.dropFront(1);
2099 else
2100 S << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002101 }
2102};
2103
2104class IntegerLiteral : public Node {
2105 StringView Type;
2106 StringView Value;
2107
2108public:
2109 IntegerLiteral(StringView Type_, StringView Value_)
2110 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2111
2112 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2113
2114 void printLeft(OutputStream &S) const override {
2115 if (Type.size() > 3) {
2116 S += "(";
2117 S += Type;
2118 S += ")";
2119 }
2120
2121 if (Value[0] == 'n') {
2122 S += "-";
2123 S += Value.dropFront(1);
2124 } else
2125 S += Value;
2126
2127 if (Type.size() <= 3)
2128 S += Type;
2129 }
2130};
2131
2132template <class Float> struct FloatData;
2133
2134namespace float_literal_impl {
2135constexpr Node::Kind getFloatLiteralKind(float *) {
2136 return Node::KFloatLiteral;
2137}
2138constexpr Node::Kind getFloatLiteralKind(double *) {
2139 return Node::KDoubleLiteral;
2140}
2141constexpr Node::Kind getFloatLiteralKind(long double *) {
2142 return Node::KLongDoubleLiteral;
2143}
2144}
2145
2146template <class Float> class FloatLiteralImpl : public Node {
2147 const StringView Contents;
2148
2149 static constexpr Kind KindForClass =
2150 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2151
2152public:
2153 FloatLiteralImpl(StringView Contents_)
2154 : Node(KindForClass), Contents(Contents_) {}
2155
2156 template<typename Fn> void match(Fn F) const { F(Contents); }
2157
2158 void printLeft(OutputStream &s) const override {
2159 const char *first = Contents.begin();
2160 const char *last = Contents.end() + 1;
2161
2162 const size_t N = FloatData<Float>::mangled_size;
2163 if (static_cast<std::size_t>(last - first) > N) {
2164 last = first + N;
2165 union {
2166 Float value;
2167 char buf[sizeof(Float)];
2168 };
2169 const char *t = first;
2170 char *e = buf;
2171 for (; t != last; ++t, ++e) {
2172 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2173 : static_cast<unsigned>(*t - 'a' + 10);
2174 ++t;
2175 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2176 : static_cast<unsigned>(*t - 'a' + 10);
2177 *e = static_cast<char>((d1 << 4) + d0);
2178 }
2179#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2180 std::reverse(buf, e);
2181#endif
2182 char num[FloatData<Float>::max_demangled_size] = {0};
2183 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
2184 s += StringView(num, num + n);
2185 }
2186 }
2187};
2188
2189using FloatLiteral = FloatLiteralImpl<float>;
2190using DoubleLiteral = FloatLiteralImpl<double>;
2191using LongDoubleLiteral = FloatLiteralImpl<long double>;
2192
2193/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2194/// appropriate derived class.
2195template<typename Fn>
2196void Node::visit(Fn F) const {
2197 switch (K) {
2198#define CASE(X) case K ## X: return F(static_cast<const X*>(this));
2199 FOR_EACH_NODE_KIND(CASE)
2200#undef CASE
2201 }
2202 assert(0 && "unknown mangling node kind");
2203}
2204
2205/// Determine the kind of a node from its type.
2206template<typename NodeT> struct NodeKind;
2207#define SPECIALIZATION(X) \
2208 template<> struct NodeKind<X> { \
2209 static constexpr Node::Kind Kind = Node::K##X; \
2210 static constexpr const char *name() { return #X; } \
2211 };
2212FOR_EACH_NODE_KIND(SPECIALIZATION)
2213#undef SPECIALIZATION
2214
2215#undef FOR_EACH_NODE_KIND
2216
2217template <class T, size_t N>
2218class PODSmallVector {
2219 static_assert(std::is_pod<T>::value,
2220 "T is required to be a plain old data type");
2221
Erik Pilkingtond95b7fd2020-01-09 10:24:09 -08002222 T* First = nullptr;
2223 T* Last = nullptr;
2224 T* Cap = nullptr;
2225 T Inline[N] = {0};
Richard Smithc20d1442018-08-20 20:14:49 +00002226
2227 bool isInline() const { return First == Inline; }
2228
2229 void clearInline() {
2230 First = Inline;
2231 Last = Inline;
2232 Cap = Inline + N;
2233 }
2234
2235 void reserve(size_t NewCap) {
2236 size_t S = size();
2237 if (isInline()) {
2238 auto* Tmp = static_cast<T*>(std::malloc(NewCap * sizeof(T)));
2239 if (Tmp == nullptr)
2240 std::terminate();
2241 std::copy(First, Last, Tmp);
2242 First = Tmp;
2243 } else {
2244 First = static_cast<T*>(std::realloc(First, NewCap * sizeof(T)));
2245 if (First == nullptr)
2246 std::terminate();
2247 }
2248 Last = First + S;
2249 Cap = First + NewCap;
2250 }
2251
2252public:
2253 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
2254
2255 PODSmallVector(const PODSmallVector&) = delete;
2256 PODSmallVector& operator=(const PODSmallVector&) = delete;
2257
2258 PODSmallVector(PODSmallVector&& Other) : PODSmallVector() {
2259 if (Other.isInline()) {
2260 std::copy(Other.begin(), Other.end(), First);
2261 Last = First + Other.size();
2262 Other.clear();
2263 return;
2264 }
2265
2266 First = Other.First;
2267 Last = Other.Last;
2268 Cap = Other.Cap;
2269 Other.clearInline();
2270 }
2271
2272 PODSmallVector& operator=(PODSmallVector&& Other) {
2273 if (Other.isInline()) {
2274 if (!isInline()) {
2275 std::free(First);
2276 clearInline();
2277 }
2278 std::copy(Other.begin(), Other.end(), First);
2279 Last = First + Other.size();
2280 Other.clear();
2281 return *this;
2282 }
2283
2284 if (isInline()) {
2285 First = Other.First;
2286 Last = Other.Last;
2287 Cap = Other.Cap;
2288 Other.clearInline();
2289 return *this;
2290 }
2291
2292 std::swap(First, Other.First);
2293 std::swap(Last, Other.Last);
2294 std::swap(Cap, Other.Cap);
2295 Other.clear();
2296 return *this;
2297 }
2298
2299 void push_back(const T& Elem) {
2300 if (Last == Cap)
2301 reserve(size() * 2);
2302 *Last++ = Elem;
2303 }
2304
2305 void pop_back() {
2306 assert(Last != First && "Popping empty vector!");
2307 --Last;
2308 }
2309
2310 void dropBack(size_t Index) {
2311 assert(Index <= size() && "dropBack() can't expand!");
2312 Last = First + Index;
2313 }
2314
2315 T* begin() { return First; }
2316 T* end() { return Last; }
2317
2318 bool empty() const { return First == Last; }
2319 size_t size() const { return static_cast<size_t>(Last - First); }
2320 T& back() {
2321 assert(Last != First && "Calling back() on empty vector!");
2322 return *(Last - 1);
2323 }
2324 T& operator[](size_t Index) {
2325 assert(Index < size() && "Invalid access!");
2326 return *(begin() + Index);
2327 }
2328 void clear() { Last = First; }
2329
2330 ~PODSmallVector() {
2331 if (!isInline())
2332 std::free(First);
2333 }
2334};
2335
Pavel Labathba825192018-10-16 14:29:14 +00002336template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002337 const char *First;
2338 const char *Last;
2339
2340 // Name stack, this is used by the parser to hold temporary names that were
2341 // parsed. The parser collapses multiple names into new nodes to construct
2342 // the AST. Once the parser is finished, names.size() == 1.
2343 PODSmallVector<Node *, 32> Names;
2344
2345 // Substitution table. Itanium supports name substitutions as a means of
2346 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2347 // table.
2348 PODSmallVector<Node *, 32> Subs;
2349
Richard Smithdf1c14c2019-09-06 23:53:21 +00002350 using TemplateParamList = PODSmallVector<Node *, 8>;
2351
2352 class ScopedTemplateParamList {
2353 AbstractManglingParser *Parser;
2354 size_t OldNumTemplateParamLists;
2355 TemplateParamList Params;
2356
2357 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002358 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2359 : Parser(TheParser),
2360 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002361 Parser->TemplateParams.push_back(&Params);
2362 }
2363 ~ScopedTemplateParamList() {
2364 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2365 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2366 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002367 };
2368
Richard Smithc20d1442018-08-20 20:14:49 +00002369 // Template parameter table. Like the above, but referenced like "T42_".
2370 // This has a smaller size compared to Subs and Names because it can be
2371 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002372 TemplateParamList OuterTemplateParams;
2373
2374 // Lists of template parameters indexed by template parameter depth,
2375 // referenced like "TL2_4_". If nonempty, element 0 is always
2376 // OuterTemplateParams; inner elements are always template parameter lists of
2377 // lambda expressions. For a generic lambda with no explicit template
2378 // parameter list, the corresponding parameter list pointer will be null.
2379 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002380
2381 // Set of unresolved forward <template-param> references. These can occur in a
2382 // conversion operator's type, and are resolved in the enclosing <encoding>.
2383 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2384
Richard Smithc20d1442018-08-20 20:14:49 +00002385 bool TryToParseTemplateArgs = true;
2386 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002387 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2388
2389 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002390
2391 Alloc ASTAllocator;
2392
Pavel Labathba825192018-10-16 14:29:14 +00002393 AbstractManglingParser(const char *First_, const char *Last_)
2394 : First(First_), Last(Last_) {}
2395
2396 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002397
2398 void reset(const char *First_, const char *Last_) {
2399 First = First_;
2400 Last = Last_;
2401 Names.clear();
2402 Subs.clear();
2403 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002404 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002405 TryToParseTemplateArgs = true;
2406 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002407 for (int I = 0; I != 3; ++I)
2408 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002409 ASTAllocator.reset();
2410 }
2411
Richard Smithb485b352018-08-24 23:30:26 +00002412 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002413 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2414 }
2415
2416 template <class It> NodeArray makeNodeArray(It begin, It end) {
2417 size_t sz = static_cast<size_t>(end - begin);
2418 void *mem = ASTAllocator.allocateNodeArray(sz);
2419 Node **data = new (mem) Node *[sz];
2420 std::copy(begin, end, data);
2421 return NodeArray(data, sz);
2422 }
2423
2424 NodeArray popTrailingNodeArray(size_t FromPosition) {
2425 assert(FromPosition <= Names.size());
2426 NodeArray res =
2427 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2428 Names.dropBack(FromPosition);
2429 return res;
2430 }
2431
2432 bool consumeIf(StringView S) {
2433 if (StringView(First, Last).startsWith(S)) {
2434 First += S.size();
2435 return true;
2436 }
2437 return false;
2438 }
2439
2440 bool consumeIf(char C) {
2441 if (First != Last && *First == C) {
2442 ++First;
2443 return true;
2444 }
2445 return false;
2446 }
2447
2448 char consume() { return First != Last ? *First++ : '\0'; }
2449
2450 char look(unsigned Lookahead = 0) {
2451 if (static_cast<size_t>(Last - First) <= Lookahead)
2452 return '\0';
2453 return First[Lookahead];
2454 }
2455
2456 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2457
2458 StringView parseNumber(bool AllowNegative = false);
2459 Qualifiers parseCVQualifiers();
2460 bool parsePositiveInteger(size_t *Out);
2461 StringView parseBareSourceName();
2462
2463 bool parseSeqId(size_t *Out);
2464 Node *parseSubstitution();
2465 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002466 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002467 Node *parseTemplateArgs(bool TagTemplates = false);
2468 Node *parseTemplateArg();
2469
2470 /// Parse the <expr> production.
2471 Node *parseExpr();
2472 Node *parsePrefixExpr(StringView Kind);
2473 Node *parseBinaryExpr(StringView Kind);
2474 Node *parseIntegerLiteral(StringView Lit);
2475 Node *parseExprPrimary();
2476 template <class Float> Node *parseFloatingLiteral();
2477 Node *parseFunctionParam();
2478 Node *parseNewExpr();
2479 Node *parseConversionExpr();
2480 Node *parseBracedExpr();
2481 Node *parseFoldExpr();
Richard Smith1865d2f2020-10-22 19:29:36 -07002482 Node *parsePointerToMemberConversionExpr();
2483 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002484
2485 /// Parse the <type> production.
2486 Node *parseType();
2487 Node *parseFunctionType();
2488 Node *parseVectorType();
2489 Node *parseDecltype();
2490 Node *parseArrayType();
2491 Node *parsePointerToMemberType();
2492 Node *parseClassEnumType();
2493 Node *parseQualifiedType();
2494
2495 Node *parseEncoding();
2496 bool parseCallOffset();
2497 Node *parseSpecialName();
2498
2499 /// Holds some extra information about a <name> that is being parsed. This
2500 /// information is only pertinent if the <name> refers to an <encoding>.
2501 struct NameState {
2502 bool CtorDtorConversion = false;
2503 bool EndsWithTemplateArgs = false;
2504 Qualifiers CVQualifiers = QualNone;
2505 FunctionRefQual ReferenceQualifier = FrefQualNone;
2506 size_t ForwardTemplateRefsBegin;
2507
Pavel Labathba825192018-10-16 14:29:14 +00002508 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002509 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2510 };
2511
2512 bool resolveForwardTemplateRefs(NameState &State) {
2513 size_t I = State.ForwardTemplateRefsBegin;
2514 size_t E = ForwardTemplateRefs.size();
2515 for (; I < E; ++I) {
2516 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002517 if (TemplateParams.empty() || !TemplateParams[0] ||
2518 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002519 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002520 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002521 }
2522 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2523 return false;
2524 }
2525
2526 /// Parse the <name> production>
2527 Node *parseName(NameState *State = nullptr);
2528 Node *parseLocalName(NameState *State);
2529 Node *parseOperatorName(NameState *State);
2530 Node *parseUnqualifiedName(NameState *State);
2531 Node *parseUnnamedTypeName(NameState *State);
2532 Node *parseSourceName(NameState *State);
2533 Node *parseUnscopedName(NameState *State);
2534 Node *parseNestedName(NameState *State);
2535 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2536
2537 Node *parseAbiTags(Node *N);
2538
2539 /// Parse the <unresolved-name> production.
2540 Node *parseUnresolvedName();
2541 Node *parseSimpleId();
2542 Node *parseBaseUnresolvedName();
2543 Node *parseUnresolvedType();
2544 Node *parseDestructorName();
2545
2546 /// Top-level entry point into the parser.
2547 Node *parse();
2548};
2549
2550const char* parse_discriminator(const char* first, const char* last);
2551
2552// <name> ::= <nested-name> // N
2553// ::= <local-name> # See Scope Encoding below // Z
2554// ::= <unscoped-template-name> <template-args>
2555// ::= <unscoped-name>
2556//
2557// <unscoped-template-name> ::= <unscoped-name>
2558// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002559template <typename Derived, typename Alloc>
2560Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002561 consumeIf('L'); // extension
2562
2563 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002564 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002565 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002566 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002567
2568 // ::= <unscoped-template-name> <template-args>
2569 if (look() == 'S' && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00002570 Node *S = getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00002571 if (S == nullptr)
2572 return nullptr;
2573 if (look() != 'I')
2574 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002575 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002576 if (TA == nullptr)
2577 return nullptr;
2578 if (State) State->EndsWithTemplateArgs = true;
2579 return make<NameWithTemplateArgs>(S, TA);
2580 }
2581
Pavel Labathba825192018-10-16 14:29:14 +00002582 Node *N = getDerived().parseUnscopedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002583 if (N == nullptr)
2584 return nullptr;
2585 // ::= <unscoped-template-name> <template-args>
2586 if (look() == 'I') {
2587 Subs.push_back(N);
Pavel Labathba825192018-10-16 14:29:14 +00002588 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002589 if (TA == nullptr)
2590 return nullptr;
2591 if (State) State->EndsWithTemplateArgs = true;
2592 return make<NameWithTemplateArgs>(N, TA);
2593 }
2594 // ::= <unscoped-name>
2595 return N;
2596}
2597
2598// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2599// := Z <function encoding> E s [<discriminator>]
2600// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002601template <typename Derived, typename Alloc>
2602Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002603 if (!consumeIf('Z'))
2604 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002605 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002606 if (Encoding == nullptr || !consumeIf('E'))
2607 return nullptr;
2608
2609 if (consumeIf('s')) {
2610 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002611 auto *StringLitName = make<NameType>("string literal");
2612 if (!StringLitName)
2613 return nullptr;
2614 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002615 }
2616
2617 if (consumeIf('d')) {
2618 parseNumber(true);
2619 if (!consumeIf('_'))
2620 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002621 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002622 if (N == nullptr)
2623 return nullptr;
2624 return make<LocalName>(Encoding, N);
2625 }
2626
Pavel Labathba825192018-10-16 14:29:14 +00002627 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002628 if (Entity == nullptr)
2629 return nullptr;
2630 First = parse_discriminator(First, Last);
2631 return make<LocalName>(Encoding, Entity);
2632}
2633
2634// <unscoped-name> ::= <unqualified-name>
2635// ::= St <unqualified-name> # ::std::
2636// extension ::= StL<unqualified-name>
Pavel Labathba825192018-10-16 14:29:14 +00002637template <typename Derived, typename Alloc>
2638Node *
2639AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {
2640 if (consumeIf("StL") || consumeIf("St")) {
2641 Node *R = getDerived().parseUnqualifiedName(State);
2642 if (R == nullptr)
2643 return nullptr;
2644 return make<StdQualifiedName>(R);
2645 }
2646 return getDerived().parseUnqualifiedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002647}
2648
2649// <unqualified-name> ::= <operator-name> [abi-tags]
2650// ::= <ctor-dtor-name>
2651// ::= <source-name>
2652// ::= <unnamed-type-name>
2653// ::= DC <source-name>+ E # structured binding declaration
Pavel Labathba825192018-10-16 14:29:14 +00002654template <typename Derived, typename Alloc>
2655Node *
2656AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002657 // <ctor-dtor-name>s are special-cased in parseNestedName().
2658 Node *Result;
2659 if (look() == 'U')
Pavel Labathba825192018-10-16 14:29:14 +00002660 Result = getDerived().parseUnnamedTypeName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002661 else if (look() >= '1' && look() <= '9')
Pavel Labathba825192018-10-16 14:29:14 +00002662 Result = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002663 else if (consumeIf("DC")) {
2664 size_t BindingsBegin = Names.size();
2665 do {
Pavel Labathba825192018-10-16 14:29:14 +00002666 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002667 if (Binding == nullptr)
2668 return nullptr;
2669 Names.push_back(Binding);
2670 } while (!consumeIf('E'));
2671 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
2672 } else
Pavel Labathba825192018-10-16 14:29:14 +00002673 Result = getDerived().parseOperatorName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002674 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002675 Result = getDerived().parseAbiTags(Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002676 return Result;
2677}
2678
2679// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2680// ::= <closure-type-name>
2681//
2682// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2683//
2684// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002685template <typename Derived, typename Alloc>
2686Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002687AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2688 // <template-params> refer to the innermost <template-args>. Clear out any
2689 // outer args that we may have inserted into TemplateParams.
2690 if (State != nullptr)
2691 TemplateParams.clear();
2692
Richard Smithc20d1442018-08-20 20:14:49 +00002693 if (consumeIf("Ut")) {
2694 StringView Count = parseNumber();
2695 if (!consumeIf('_'))
2696 return nullptr;
2697 return make<UnnamedTypeName>(Count);
2698 }
2699 if (consumeIf("Ul")) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002700 SwapAndRestore<size_t> SwapParams(ParsingLambdaParamsAtLevel,
2701 TemplateParams.size());
2702 ScopedTemplateParamList LambdaTemplateParams(this);
2703
2704 size_t ParamsBegin = Names.size();
2705 while (look() == 'T' &&
2706 StringView("yptn").find(look(1)) != StringView::npos) {
2707 Node *T = parseTemplateParamDecl();
2708 if (!T)
2709 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002710 Names.push_back(T);
2711 }
2712 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2713
2714 // FIXME: If TempParams is empty and none of the function parameters
2715 // includes 'auto', we should remove LambdaTemplateParams from the
2716 // TemplateParams list. Unfortunately, we don't find out whether there are
2717 // any 'auto' parameters until too late in an example such as:
2718 //
2719 // template<typename T> void f(
2720 // decltype([](decltype([]<typename T>(T v) {}),
2721 // auto) {})) {}
2722 // template<typename T> void f(
2723 // decltype([](decltype([]<typename T>(T w) {}),
2724 // int) {})) {}
2725 //
2726 // Here, the type of v is at level 2 but the type of w is at level 1. We
2727 // don't find this out until we encounter the type of the next parameter.
2728 //
2729 // However, compilers can't actually cope with the former example in
2730 // practice, and it's likely to be made ill-formed in future, so we don't
2731 // need to support it here.
2732 //
2733 // If we encounter an 'auto' in the function parameter types, we will
2734 // recreate a template parameter scope for it, but any intervening lambdas
2735 // will be parsed in the 'wrong' template parameter depth.
2736 if (TempParams.empty())
2737 TemplateParams.pop_back();
2738
Richard Smithc20d1442018-08-20 20:14:49 +00002739 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002740 do {
Pavel Labathba825192018-10-16 14:29:14 +00002741 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002742 if (P == nullptr)
2743 return nullptr;
2744 Names.push_back(P);
2745 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002746 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002747 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2748
Richard Smithc20d1442018-08-20 20:14:49 +00002749 StringView Count = parseNumber();
2750 if (!consumeIf('_'))
2751 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002752 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002753 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002754 if (consumeIf("Ub")) {
2755 (void)parseNumber();
2756 if (!consumeIf('_'))
2757 return nullptr;
2758 return make<NameType>("'block-literal'");
2759 }
Richard Smithc20d1442018-08-20 20:14:49 +00002760 return nullptr;
2761}
2762
2763// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002764template <typename Derived, typename Alloc>
2765Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002766 size_t Length = 0;
2767 if (parsePositiveInteger(&Length))
2768 return nullptr;
2769 if (numLeft() < Length || Length == 0)
2770 return nullptr;
2771 StringView Name(First, First + Length);
2772 First += Length;
2773 if (Name.startsWith("_GLOBAL__N"))
2774 return make<NameType>("(anonymous namespace)");
2775 return make<NameType>(Name);
2776}
2777
2778// <operator-name> ::= aa # &&
2779// ::= ad # & (unary)
2780// ::= an # &
2781// ::= aN # &=
2782// ::= aS # =
2783// ::= cl # ()
2784// ::= cm # ,
2785// ::= co # ~
2786// ::= cv <type> # (cast)
2787// ::= da # delete[]
2788// ::= de # * (unary)
2789// ::= dl # delete
2790// ::= dv # /
2791// ::= dV # /=
2792// ::= eo # ^
2793// ::= eO # ^=
2794// ::= eq # ==
2795// ::= ge # >=
2796// ::= gt # >
2797// ::= ix # []
2798// ::= le # <=
2799// ::= li <source-name> # operator ""
2800// ::= ls # <<
2801// ::= lS # <<=
2802// ::= lt # <
2803// ::= mi # -
2804// ::= mI # -=
2805// ::= ml # *
2806// ::= mL # *=
2807// ::= mm # -- (postfix in <expression> context)
2808// ::= na # new[]
2809// ::= ne # !=
2810// ::= ng # - (unary)
2811// ::= nt # !
2812// ::= nw # new
2813// ::= oo # ||
2814// ::= or # |
2815// ::= oR # |=
2816// ::= pm # ->*
2817// ::= pl # +
2818// ::= pL # +=
2819// ::= pp # ++ (postfix in <expression> context)
2820// ::= ps # + (unary)
2821// ::= pt # ->
2822// ::= qu # ?
2823// ::= rm # %
2824// ::= rM # %=
2825// ::= rs # >>
2826// ::= rS # >>=
2827// ::= ss # <=> C++2a
2828// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00002829template <typename Derived, typename Alloc>
2830Node *
2831AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002832 switch (look()) {
2833 case 'a':
2834 switch (look(1)) {
2835 case 'a':
2836 First += 2;
2837 return make<NameType>("operator&&");
2838 case 'd':
2839 case 'n':
2840 First += 2;
2841 return make<NameType>("operator&");
2842 case 'N':
2843 First += 2;
2844 return make<NameType>("operator&=");
2845 case 'S':
2846 First += 2;
2847 return make<NameType>("operator=");
2848 }
2849 return nullptr;
2850 case 'c':
2851 switch (look(1)) {
2852 case 'l':
2853 First += 2;
2854 return make<NameType>("operator()");
2855 case 'm':
2856 First += 2;
2857 return make<NameType>("operator,");
2858 case 'o':
2859 First += 2;
2860 return make<NameType>("operator~");
2861 // ::= cv <type> # (cast)
2862 case 'v': {
2863 First += 2;
2864 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
2865 // If we're parsing an encoding, State != nullptr and the conversion
2866 // operators' <type> could have a <template-param> that refers to some
2867 // <template-arg>s further ahead in the mangled name.
2868 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
2869 PermitForwardTemplateReferences ||
2870 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00002871 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002872 if (Ty == nullptr)
2873 return nullptr;
2874 if (State) State->CtorDtorConversion = true;
2875 return make<ConversionOperatorType>(Ty);
2876 }
2877 }
2878 return nullptr;
2879 case 'd':
2880 switch (look(1)) {
2881 case 'a':
2882 First += 2;
2883 return make<NameType>("operator delete[]");
2884 case 'e':
2885 First += 2;
2886 return make<NameType>("operator*");
2887 case 'l':
2888 First += 2;
2889 return make<NameType>("operator delete");
2890 case 'v':
2891 First += 2;
2892 return make<NameType>("operator/");
2893 case 'V':
2894 First += 2;
2895 return make<NameType>("operator/=");
2896 }
2897 return nullptr;
2898 case 'e':
2899 switch (look(1)) {
2900 case 'o':
2901 First += 2;
2902 return make<NameType>("operator^");
2903 case 'O':
2904 First += 2;
2905 return make<NameType>("operator^=");
2906 case 'q':
2907 First += 2;
2908 return make<NameType>("operator==");
2909 }
2910 return nullptr;
2911 case 'g':
2912 switch (look(1)) {
2913 case 'e':
2914 First += 2;
2915 return make<NameType>("operator>=");
2916 case 't':
2917 First += 2;
2918 return make<NameType>("operator>");
2919 }
2920 return nullptr;
2921 case 'i':
2922 if (look(1) == 'x') {
2923 First += 2;
2924 return make<NameType>("operator[]");
2925 }
2926 return nullptr;
2927 case 'l':
2928 switch (look(1)) {
2929 case 'e':
2930 First += 2;
2931 return make<NameType>("operator<=");
2932 // ::= li <source-name> # operator ""
2933 case 'i': {
2934 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00002935 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002936 if (SN == nullptr)
2937 return nullptr;
2938 return make<LiteralOperator>(SN);
2939 }
2940 case 's':
2941 First += 2;
2942 return make<NameType>("operator<<");
2943 case 'S':
2944 First += 2;
2945 return make<NameType>("operator<<=");
2946 case 't':
2947 First += 2;
2948 return make<NameType>("operator<");
2949 }
2950 return nullptr;
2951 case 'm':
2952 switch (look(1)) {
2953 case 'i':
2954 First += 2;
2955 return make<NameType>("operator-");
2956 case 'I':
2957 First += 2;
2958 return make<NameType>("operator-=");
2959 case 'l':
2960 First += 2;
2961 return make<NameType>("operator*");
2962 case 'L':
2963 First += 2;
2964 return make<NameType>("operator*=");
2965 case 'm':
2966 First += 2;
2967 return make<NameType>("operator--");
2968 }
2969 return nullptr;
2970 case 'n':
2971 switch (look(1)) {
2972 case 'a':
2973 First += 2;
2974 return make<NameType>("operator new[]");
2975 case 'e':
2976 First += 2;
2977 return make<NameType>("operator!=");
2978 case 'g':
2979 First += 2;
2980 return make<NameType>("operator-");
2981 case 't':
2982 First += 2;
2983 return make<NameType>("operator!");
2984 case 'w':
2985 First += 2;
2986 return make<NameType>("operator new");
2987 }
2988 return nullptr;
2989 case 'o':
2990 switch (look(1)) {
2991 case 'o':
2992 First += 2;
2993 return make<NameType>("operator||");
2994 case 'r':
2995 First += 2;
2996 return make<NameType>("operator|");
2997 case 'R':
2998 First += 2;
2999 return make<NameType>("operator|=");
3000 }
3001 return nullptr;
3002 case 'p':
3003 switch (look(1)) {
3004 case 'm':
3005 First += 2;
3006 return make<NameType>("operator->*");
3007 case 'l':
3008 First += 2;
3009 return make<NameType>("operator+");
3010 case 'L':
3011 First += 2;
3012 return make<NameType>("operator+=");
3013 case 'p':
3014 First += 2;
3015 return make<NameType>("operator++");
3016 case 's':
3017 First += 2;
3018 return make<NameType>("operator+");
3019 case 't':
3020 First += 2;
3021 return make<NameType>("operator->");
3022 }
3023 return nullptr;
3024 case 'q':
3025 if (look(1) == 'u') {
3026 First += 2;
3027 return make<NameType>("operator?");
3028 }
3029 return nullptr;
3030 case 'r':
3031 switch (look(1)) {
3032 case 'm':
3033 First += 2;
3034 return make<NameType>("operator%");
3035 case 'M':
3036 First += 2;
3037 return make<NameType>("operator%=");
3038 case 's':
3039 First += 2;
3040 return make<NameType>("operator>>");
3041 case 'S':
3042 First += 2;
3043 return make<NameType>("operator>>=");
3044 }
3045 return nullptr;
3046 case 's':
3047 if (look(1) == 's') {
3048 First += 2;
3049 return make<NameType>("operator<=>");
3050 }
3051 return nullptr;
3052 // ::= v <digit> <source-name> # vendor extended operator
3053 case 'v':
3054 if (std::isdigit(look(1))) {
3055 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003056 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003057 if (SN == nullptr)
3058 return nullptr;
3059 return make<ConversionOperatorType>(SN);
3060 }
3061 return nullptr;
3062 }
3063 return nullptr;
3064}
3065
3066// <ctor-dtor-name> ::= C1 # complete object constructor
3067// ::= C2 # base object constructor
3068// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003069// extension ::= C4 # gcc old-style "[unified]" constructor
3070// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003071// ::= D0 # deleting destructor
3072// ::= D1 # complete object destructor
3073// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003074// extension ::= D4 # gcc old-style "[unified]" destructor
3075// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003076template <typename Derived, typename Alloc>
3077Node *
3078AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3079 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003080 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3081 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3082 switch (SSK) {
3083 case SpecialSubKind::string:
3084 case SpecialSubKind::istream:
3085 case SpecialSubKind::ostream:
3086 case SpecialSubKind::iostream:
3087 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00003088 if (!SoFar)
3089 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00003090 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003091 default:
3092 break;
3093 }
3094 }
3095
3096 if (consumeIf('C')) {
3097 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003098 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3099 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003100 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003101 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003102 ++First;
3103 if (State) State->CtorDtorConversion = true;
3104 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003105 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003106 return nullptr;
3107 }
Nico Weber29294792019-04-03 23:14:33 +00003108 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003109 }
3110
Nico Weber29294792019-04-03 23:14:33 +00003111 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3112 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003113 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003114 First += 2;
3115 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003116 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003117 }
3118
3119 return nullptr;
3120}
3121
3122// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3123// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3124//
3125// <prefix> ::= <prefix> <unqualified-name>
3126// ::= <template-prefix> <template-args>
3127// ::= <template-param>
3128// ::= <decltype>
3129// ::= # empty
3130// ::= <substitution>
3131// ::= <prefix> <data-member-prefix>
3132// extension ::= L
3133//
3134// <data-member-prefix> := <member source-name> [<template-args>] M
3135//
3136// <template-prefix> ::= <prefix> <template unqualified-name>
3137// ::= <template-param>
3138// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003139template <typename Derived, typename Alloc>
3140Node *
3141AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003142 if (!consumeIf('N'))
3143 return nullptr;
3144
3145 Qualifiers CVTmp = parseCVQualifiers();
3146 if (State) State->CVQualifiers = CVTmp;
3147
3148 if (consumeIf('O')) {
3149 if (State) State->ReferenceQualifier = FrefQualRValue;
3150 } else if (consumeIf('R')) {
3151 if (State) State->ReferenceQualifier = FrefQualLValue;
3152 } else
3153 if (State) State->ReferenceQualifier = FrefQualNone;
3154
3155 Node *SoFar = nullptr;
3156 auto PushComponent = [&](Node *Comp) {
Richard Smithb485b352018-08-24 23:30:26 +00003157 if (!Comp) return false;
Richard Smithc20d1442018-08-20 20:14:49 +00003158 if (SoFar) SoFar = make<NestedName>(SoFar, Comp);
3159 else SoFar = Comp;
3160 if (State) State->EndsWithTemplateArgs = false;
Richard Smithb485b352018-08-24 23:30:26 +00003161 return SoFar != nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003162 };
3163
Richard Smithb485b352018-08-24 23:30:26 +00003164 if (consumeIf("St")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003165 SoFar = make<NameType>("std");
Richard Smithb485b352018-08-24 23:30:26 +00003166 if (!SoFar)
3167 return nullptr;
3168 }
Richard Smithc20d1442018-08-20 20:14:49 +00003169
3170 while (!consumeIf('E')) {
3171 consumeIf('L'); // extension
3172
3173 // <data-member-prefix> := <member source-name> [<template-args>] M
3174 if (consumeIf('M')) {
3175 if (SoFar == nullptr)
3176 return nullptr;
3177 continue;
3178 }
3179
3180 // ::= <template-param>
3181 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003182 if (!PushComponent(getDerived().parseTemplateParam()))
Richard Smithc20d1442018-08-20 20:14:49 +00003183 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003184 Subs.push_back(SoFar);
3185 continue;
3186 }
3187
3188 // ::= <template-prefix> <template-args>
3189 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003190 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003191 if (TA == nullptr || SoFar == nullptr)
3192 return nullptr;
3193 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003194 if (!SoFar)
3195 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003196 if (State) State->EndsWithTemplateArgs = true;
3197 Subs.push_back(SoFar);
3198 continue;
3199 }
3200
3201 // ::= <decltype>
3202 if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
Pavel Labathba825192018-10-16 14:29:14 +00003203 if (!PushComponent(getDerived().parseDecltype()))
Richard Smithc20d1442018-08-20 20:14:49 +00003204 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003205 Subs.push_back(SoFar);
3206 continue;
3207 }
3208
3209 // ::= <substitution>
3210 if (look() == 'S' && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00003211 Node *S = getDerived().parseSubstitution();
Richard Smithb485b352018-08-24 23:30:26 +00003212 if (!PushComponent(S))
Richard Smithc20d1442018-08-20 20:14:49 +00003213 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003214 if (SoFar != S)
3215 Subs.push_back(S);
3216 continue;
3217 }
3218
3219 // Parse an <unqualified-name> thats actually a <ctor-dtor-name>.
3220 if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {
3221 if (SoFar == nullptr)
3222 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003223 if (!PushComponent(getDerived().parseCtorDtorName(SoFar, State)))
Richard Smithc20d1442018-08-20 20:14:49 +00003224 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003225 SoFar = getDerived().parseAbiTags(SoFar);
Richard Smithc20d1442018-08-20 20:14:49 +00003226 if (SoFar == nullptr)
3227 return nullptr;
3228 Subs.push_back(SoFar);
3229 continue;
3230 }
3231
3232 // ::= <prefix> <unqualified-name>
Pavel Labathba825192018-10-16 14:29:14 +00003233 if (!PushComponent(getDerived().parseUnqualifiedName(State)))
Richard Smithc20d1442018-08-20 20:14:49 +00003234 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003235 Subs.push_back(SoFar);
3236 }
3237
3238 if (SoFar == nullptr || Subs.empty())
3239 return nullptr;
3240
3241 Subs.pop_back();
3242 return SoFar;
3243}
3244
3245// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003246template <typename Derived, typename Alloc>
3247Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3248 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003249 if (SN == nullptr)
3250 return nullptr;
3251 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003252 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003253 if (TA == nullptr)
3254 return nullptr;
3255 return make<NameWithTemplateArgs>(SN, TA);
3256 }
3257 return SN;
3258}
3259
3260// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3261// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003262template <typename Derived, typename Alloc>
3263Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003264 Node *Result;
3265 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003266 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003267 else
Pavel Labathba825192018-10-16 14:29:14 +00003268 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003269 if (Result == nullptr)
3270 return nullptr;
3271 return make<DtorName>(Result);
3272}
3273
3274// <unresolved-type> ::= <template-param>
3275// ::= <decltype>
3276// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003277template <typename Derived, typename Alloc>
3278Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003279 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003280 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003281 if (TP == nullptr)
3282 return nullptr;
3283 Subs.push_back(TP);
3284 return TP;
3285 }
3286 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003287 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003288 if (DT == nullptr)
3289 return nullptr;
3290 Subs.push_back(DT);
3291 return DT;
3292 }
Pavel Labathba825192018-10-16 14:29:14 +00003293 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003294}
3295
3296// <base-unresolved-name> ::= <simple-id> # unresolved name
3297// extension ::= <operator-name> # unresolved operator-function-id
3298// extension ::= <operator-name> <template-args> # unresolved operator template-id
3299// ::= on <operator-name> # unresolved operator-function-id
3300// ::= on <operator-name> <template-args> # unresolved operator template-id
3301// ::= dn <destructor-name> # destructor or pseudo-destructor;
3302// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003303template <typename Derived, typename Alloc>
3304Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003305 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003306 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003307
3308 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003309 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003310
3311 consumeIf("on");
3312
Pavel Labathba825192018-10-16 14:29:14 +00003313 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003314 if (Oper == nullptr)
3315 return nullptr;
3316 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003317 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003318 if (TA == nullptr)
3319 return nullptr;
3320 return make<NameWithTemplateArgs>(Oper, TA);
3321 }
3322 return Oper;
3323}
3324
3325// <unresolved-name>
3326// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3327// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3328// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3329// # A::x, N::y, A<T>::z; "gs" means leading "::"
3330// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3331// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3332// # T::N::x /decltype(p)::N::x
3333// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3334//
3335// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003336template <typename Derived, typename Alloc>
3337Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003338 Node *SoFar = nullptr;
3339
3340 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3341 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3342 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003343 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003344 if (SoFar == nullptr)
3345 return nullptr;
3346
3347 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003348 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003349 if (TA == nullptr)
3350 return nullptr;
3351 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003352 if (!SoFar)
3353 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003354 }
3355
3356 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003357 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003358 if (Qual == nullptr)
3359 return nullptr;
3360 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003361 if (!SoFar)
3362 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003363 }
3364
Pavel Labathba825192018-10-16 14:29:14 +00003365 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003366 if (Base == nullptr)
3367 return nullptr;
3368 return make<QualifiedName>(SoFar, Base);
3369 }
3370
3371 bool Global = consumeIf("gs");
3372
3373 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3374 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003375 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003376 if (SoFar == nullptr)
3377 return nullptr;
3378 if (Global)
3379 SoFar = make<GlobalQualifiedName>(SoFar);
3380 return SoFar;
3381 }
3382
3383 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3384 if (std::isdigit(look())) {
3385 do {
Pavel Labathba825192018-10-16 14:29:14 +00003386 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003387 if (Qual == nullptr)
3388 return nullptr;
3389 if (SoFar)
3390 SoFar = make<QualifiedName>(SoFar, Qual);
3391 else if (Global)
3392 SoFar = make<GlobalQualifiedName>(Qual);
3393 else
3394 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003395 if (!SoFar)
3396 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003397 } while (!consumeIf('E'));
3398 }
3399 // sr <unresolved-type> <base-unresolved-name>
3400 // sr <unresolved-type> <template-args> <base-unresolved-name>
3401 else {
Pavel Labathba825192018-10-16 14:29:14 +00003402 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003403 if (SoFar == nullptr)
3404 return nullptr;
3405
3406 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003407 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003408 if (TA == nullptr)
3409 return nullptr;
3410 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003411 if (!SoFar)
3412 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003413 }
3414 }
3415
3416 assert(SoFar != nullptr);
3417
Pavel Labathba825192018-10-16 14:29:14 +00003418 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003419 if (Base == nullptr)
3420 return nullptr;
3421 return make<QualifiedName>(SoFar, Base);
3422}
3423
3424// <abi-tags> ::= <abi-tag> [<abi-tags>]
3425// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003426template <typename Derived, typename Alloc>
3427Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003428 while (consumeIf('B')) {
3429 StringView SN = parseBareSourceName();
3430 if (SN.empty())
3431 return nullptr;
3432 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003433 if (!N)
3434 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003435 }
3436 return N;
3437}
3438
3439// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003440template <typename Alloc, typename Derived>
3441StringView
3442AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003443 const char *Tmp = First;
3444 if (AllowNegative)
3445 consumeIf('n');
3446 if (numLeft() == 0 || !std::isdigit(*First))
3447 return StringView();
3448 while (numLeft() != 0 && std::isdigit(*First))
3449 ++First;
3450 return StringView(Tmp, First);
3451}
3452
3453// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003454template <typename Alloc, typename Derived>
3455bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003456 *Out = 0;
3457 if (look() < '0' || look() > '9')
3458 return true;
3459 while (look() >= '0' && look() <= '9') {
3460 *Out *= 10;
3461 *Out += static_cast<size_t>(consume() - '0');
3462 }
3463 return false;
3464}
3465
Pavel Labathba825192018-10-16 14:29:14 +00003466template <typename Alloc, typename Derived>
3467StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003468 size_t Int = 0;
3469 if (parsePositiveInteger(&Int) || numLeft() < Int)
3470 return StringView();
3471 StringView R(First, First + Int);
3472 First += Int;
3473 return R;
3474}
3475
3476// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3477//
3478// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3479// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3480// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3481//
3482// <ref-qualifier> ::= R # & ref-qualifier
3483// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003484template <typename Derived, typename Alloc>
3485Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003486 Qualifiers CVQuals = parseCVQualifiers();
3487
3488 Node *ExceptionSpec = nullptr;
3489 if (consumeIf("Do")) {
3490 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003491 if (!ExceptionSpec)
3492 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003493 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003494 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003495 if (E == nullptr || !consumeIf('E'))
3496 return nullptr;
3497 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003498 if (!ExceptionSpec)
3499 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003500 } else if (consumeIf("Dw")) {
3501 size_t SpecsBegin = Names.size();
3502 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003503 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003504 if (T == nullptr)
3505 return nullptr;
3506 Names.push_back(T);
3507 }
3508 ExceptionSpec =
3509 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003510 if (!ExceptionSpec)
3511 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003512 }
3513
3514 consumeIf("Dx"); // transaction safe
3515
3516 if (!consumeIf('F'))
3517 return nullptr;
3518 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003519 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003520 if (ReturnType == nullptr)
3521 return nullptr;
3522
3523 FunctionRefQual ReferenceQualifier = FrefQualNone;
3524 size_t ParamsBegin = Names.size();
3525 while (true) {
3526 if (consumeIf('E'))
3527 break;
3528 if (consumeIf('v'))
3529 continue;
3530 if (consumeIf("RE")) {
3531 ReferenceQualifier = FrefQualLValue;
3532 break;
3533 }
3534 if (consumeIf("OE")) {
3535 ReferenceQualifier = FrefQualRValue;
3536 break;
3537 }
Pavel Labathba825192018-10-16 14:29:14 +00003538 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003539 if (T == nullptr)
3540 return nullptr;
3541 Names.push_back(T);
3542 }
3543
3544 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3545 return make<FunctionType>(ReturnType, Params, CVQuals,
3546 ReferenceQualifier, ExceptionSpec);
3547}
3548
3549// extension:
3550// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3551// ::= Dv [<dimension expression>] _ <element type>
3552// <extended element type> ::= <element type>
3553// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003554template <typename Derived, typename Alloc>
3555Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003556 if (!consumeIf("Dv"))
3557 return nullptr;
3558 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003559 Node *DimensionNumber = make<NameType>(parseNumber());
3560 if (!DimensionNumber)
3561 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003562 if (!consumeIf('_'))
3563 return nullptr;
3564 if (consumeIf('p'))
3565 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003566 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003567 if (ElemType == nullptr)
3568 return nullptr;
3569 return make<VectorType>(ElemType, DimensionNumber);
3570 }
3571
3572 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003573 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003574 if (!DimExpr)
3575 return nullptr;
3576 if (!consumeIf('_'))
3577 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003578 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003579 if (!ElemType)
3580 return nullptr;
3581 return make<VectorType>(ElemType, DimExpr);
3582 }
Pavel Labathba825192018-10-16 14:29:14 +00003583 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003584 if (!ElemType)
3585 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003586 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003587}
3588
3589// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3590// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003591template <typename Derived, typename Alloc>
3592Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003593 if (!consumeIf('D'))
3594 return nullptr;
3595 if (!consumeIf('t') && !consumeIf('T'))
3596 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003597 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003598 if (E == nullptr)
3599 return nullptr;
3600 if (!consumeIf('E'))
3601 return nullptr;
3602 return make<EnclosingExpr>("decltype(", E, ")");
3603}
3604
3605// <array-type> ::= A <positive dimension number> _ <element type>
3606// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003607template <typename Derived, typename Alloc>
3608Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003609 if (!consumeIf('A'))
3610 return nullptr;
3611
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003612 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003613
Richard Smithc20d1442018-08-20 20:14:49 +00003614 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003615 Dimension = make<NameType>(parseNumber());
3616 if (!Dimension)
3617 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003618 if (!consumeIf('_'))
3619 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003620 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003621 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003622 if (DimExpr == nullptr)
3623 return nullptr;
3624 if (!consumeIf('_'))
3625 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003626 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003627 }
3628
Pavel Labathba825192018-10-16 14:29:14 +00003629 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003630 if (Ty == nullptr)
3631 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003632 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003633}
3634
3635// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003636template <typename Derived, typename Alloc>
3637Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003638 if (!consumeIf('M'))
3639 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003640 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003641 if (ClassType == nullptr)
3642 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003643 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003644 if (MemberType == nullptr)
3645 return nullptr;
3646 return make<PointerToMemberType>(ClassType, MemberType);
3647}
3648
3649// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3650// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3651// ::= Tu <name> # dependent elaborated type specifier using 'union'
3652// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003653template <typename Derived, typename Alloc>
3654Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003655 StringView ElabSpef;
3656 if (consumeIf("Ts"))
3657 ElabSpef = "struct";
3658 else if (consumeIf("Tu"))
3659 ElabSpef = "union";
3660 else if (consumeIf("Te"))
3661 ElabSpef = "enum";
3662
Pavel Labathba825192018-10-16 14:29:14 +00003663 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003664 if (Name == nullptr)
3665 return nullptr;
3666
3667 if (!ElabSpef.empty())
3668 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3669
3670 return Name;
3671}
3672
3673// <qualified-type> ::= <qualifiers> <type>
3674// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3675// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003676template <typename Derived, typename Alloc>
3677Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003678 if (consumeIf('U')) {
3679 StringView Qual = parseBareSourceName();
3680 if (Qual.empty())
3681 return nullptr;
3682
3683 // FIXME parse the optional <template-args> here!
3684
3685 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3686 if (Qual.startsWith("objcproto")) {
3687 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3688 StringView Proto;
3689 {
3690 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3691 SaveLast(Last, ProtoSourceName.end());
3692 Proto = parseBareSourceName();
3693 }
3694 if (Proto.empty())
3695 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003696 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003697 if (Child == nullptr)
3698 return nullptr;
3699 return make<ObjCProtoName>(Child, Proto);
3700 }
3701
Pavel Labathba825192018-10-16 14:29:14 +00003702 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003703 if (Child == nullptr)
3704 return nullptr;
3705 return make<VendorExtQualType>(Child, Qual);
3706 }
3707
3708 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003709 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003710 if (Ty == nullptr)
3711 return nullptr;
3712 if (Quals != QualNone)
3713 Ty = make<QualType>(Ty, Quals);
3714 return Ty;
3715}
3716
3717// <type> ::= <builtin-type>
3718// ::= <qualified-type>
3719// ::= <function-type>
3720// ::= <class-enum-type>
3721// ::= <array-type>
3722// ::= <pointer-to-member-type>
3723// ::= <template-param>
3724// ::= <template-template-param> <template-args>
3725// ::= <decltype>
3726// ::= P <type> # pointer
3727// ::= R <type> # l-value reference
3728// ::= O <type> # r-value reference (C++11)
3729// ::= C <type> # complex pair (C99)
3730// ::= G <type> # imaginary (C99)
3731// ::= <substitution> # See Compression below
3732// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3733// extension ::= <vector-type> # <vector-type> starts with Dv
3734//
3735// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3736// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003737template <typename Derived, typename Alloc>
3738Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003739 Node *Result = nullptr;
3740
Richard Smithc20d1442018-08-20 20:14:49 +00003741 switch (look()) {
3742 // ::= <qualified-type>
3743 case 'r':
3744 case 'V':
3745 case 'K': {
3746 unsigned AfterQuals = 0;
3747 if (look(AfterQuals) == 'r') ++AfterQuals;
3748 if (look(AfterQuals) == 'V') ++AfterQuals;
3749 if (look(AfterQuals) == 'K') ++AfterQuals;
3750
3751 if (look(AfterQuals) == 'F' ||
3752 (look(AfterQuals) == 'D' &&
3753 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3754 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003755 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003756 break;
3757 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003758 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003759 }
3760 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003761 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003762 break;
3763 }
3764 // <builtin-type> ::= v # void
3765 case 'v':
3766 ++First;
3767 return make<NameType>("void");
3768 // ::= w # wchar_t
3769 case 'w':
3770 ++First;
3771 return make<NameType>("wchar_t");
3772 // ::= b # bool
3773 case 'b':
3774 ++First;
3775 return make<NameType>("bool");
3776 // ::= c # char
3777 case 'c':
3778 ++First;
3779 return make<NameType>("char");
3780 // ::= a # signed char
3781 case 'a':
3782 ++First;
3783 return make<NameType>("signed char");
3784 // ::= h # unsigned char
3785 case 'h':
3786 ++First;
3787 return make<NameType>("unsigned char");
3788 // ::= s # short
3789 case 's':
3790 ++First;
3791 return make<NameType>("short");
3792 // ::= t # unsigned short
3793 case 't':
3794 ++First;
3795 return make<NameType>("unsigned short");
3796 // ::= i # int
3797 case 'i':
3798 ++First;
3799 return make<NameType>("int");
3800 // ::= j # unsigned int
3801 case 'j':
3802 ++First;
3803 return make<NameType>("unsigned int");
3804 // ::= l # long
3805 case 'l':
3806 ++First;
3807 return make<NameType>("long");
3808 // ::= m # unsigned long
3809 case 'm':
3810 ++First;
3811 return make<NameType>("unsigned long");
3812 // ::= x # long long, __int64
3813 case 'x':
3814 ++First;
3815 return make<NameType>("long long");
3816 // ::= y # unsigned long long, __int64
3817 case 'y':
3818 ++First;
3819 return make<NameType>("unsigned long long");
3820 // ::= n # __int128
3821 case 'n':
3822 ++First;
3823 return make<NameType>("__int128");
3824 // ::= o # unsigned __int128
3825 case 'o':
3826 ++First;
3827 return make<NameType>("unsigned __int128");
3828 // ::= f # float
3829 case 'f':
3830 ++First;
3831 return make<NameType>("float");
3832 // ::= d # double
3833 case 'd':
3834 ++First;
3835 return make<NameType>("double");
3836 // ::= e # long double, __float80
3837 case 'e':
3838 ++First;
3839 return make<NameType>("long double");
3840 // ::= g # __float128
3841 case 'g':
3842 ++First;
3843 return make<NameType>("__float128");
3844 // ::= z # ellipsis
3845 case 'z':
3846 ++First;
3847 return make<NameType>("...");
3848
3849 // <builtin-type> ::= u <source-name> # vendor extended type
3850 case 'u': {
3851 ++First;
3852 StringView Res = parseBareSourceName();
3853 if (Res.empty())
3854 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003855 // Typically, <builtin-type>s are not considered substitution candidates,
3856 // but the exception to that exception is vendor extended types (Itanium C++
3857 // ABI 5.9.1).
3858 Result = make<NameType>(Res);
3859 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003860 }
3861 case 'D':
3862 switch (look(1)) {
3863 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3864 case 'd':
3865 First += 2;
3866 return make<NameType>("decimal64");
3867 // ::= De # IEEE 754r decimal floating point (128 bits)
3868 case 'e':
3869 First += 2;
3870 return make<NameType>("decimal128");
3871 // ::= Df # IEEE 754r decimal floating point (32 bits)
3872 case 'f':
3873 First += 2;
3874 return make<NameType>("decimal32");
3875 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3876 case 'h':
3877 First += 2;
3878 return make<NameType>("decimal16");
3879 // ::= Di # char32_t
3880 case 'i':
3881 First += 2;
3882 return make<NameType>("char32_t");
3883 // ::= Ds # char16_t
3884 case 's':
3885 First += 2;
3886 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003887 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3888 case 'u':
3889 First += 2;
3890 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003891 // ::= Da # auto (in dependent new-expressions)
3892 case 'a':
3893 First += 2;
3894 return make<NameType>("auto");
3895 // ::= Dc # decltype(auto)
3896 case 'c':
3897 First += 2;
3898 return make<NameType>("decltype(auto)");
3899 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3900 case 'n':
3901 First += 2;
3902 return make<NameType>("std::nullptr_t");
3903
3904 // ::= <decltype>
3905 case 't':
3906 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003907 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003908 break;
3909 }
3910 // extension ::= <vector-type> # <vector-type> starts with Dv
3911 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003912 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003913 break;
3914 }
3915 // ::= Dp <type> # pack expansion (C++0x)
3916 case 'p': {
3917 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003918 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003919 if (!Child)
3920 return nullptr;
3921 Result = make<ParameterPackExpansion>(Child);
3922 break;
3923 }
3924 // Exception specifier on a function type.
3925 case 'o':
3926 case 'O':
3927 case 'w':
3928 // Transaction safe function type.
3929 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003930 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003931 break;
3932 }
3933 break;
3934 // ::= <function-type>
3935 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003936 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003937 break;
3938 }
3939 // ::= <array-type>
3940 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003941 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003942 break;
3943 }
3944 // ::= <pointer-to-member-type>
3945 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003946 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003947 break;
3948 }
3949 // ::= <template-param>
3950 case 'T': {
3951 // This could be an elaborate type specifier on a <class-enum-type>.
3952 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00003953 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003954 break;
3955 }
3956
Pavel Labathba825192018-10-16 14:29:14 +00003957 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003958 if (Result == nullptr)
3959 return nullptr;
3960
3961 // Result could be either of:
3962 // <type> ::= <template-param>
3963 // <type> ::= <template-template-param> <template-args>
3964 //
3965 // <template-template-param> ::= <template-param>
3966 // ::= <substitution>
3967 //
3968 // If this is followed by some <template-args>, and we're permitted to
3969 // parse them, take the second production.
3970
3971 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003972 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003973 if (TA == nullptr)
3974 return nullptr;
3975 Result = make<NameWithTemplateArgs>(Result, TA);
3976 }
3977 break;
3978 }
3979 // ::= P <type> # pointer
3980 case 'P': {
3981 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003982 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003983 if (Ptr == nullptr)
3984 return nullptr;
3985 Result = make<PointerType>(Ptr);
3986 break;
3987 }
3988 // ::= R <type> # l-value reference
3989 case 'R': {
3990 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003991 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003992 if (Ref == nullptr)
3993 return nullptr;
3994 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
3995 break;
3996 }
3997 // ::= O <type> # r-value reference (C++11)
3998 case 'O': {
3999 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004000 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004001 if (Ref == nullptr)
4002 return nullptr;
4003 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4004 break;
4005 }
4006 // ::= C <type> # complex pair (C99)
4007 case 'C': {
4008 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004009 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004010 if (P == nullptr)
4011 return nullptr;
4012 Result = make<PostfixQualifiedType>(P, " complex");
4013 break;
4014 }
4015 // ::= G <type> # imaginary (C99)
4016 case 'G': {
4017 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004018 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004019 if (P == nullptr)
4020 return P;
4021 Result = make<PostfixQualifiedType>(P, " imaginary");
4022 break;
4023 }
4024 // ::= <substitution> # See Compression below
4025 case 'S': {
4026 if (look(1) && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00004027 Node *Sub = getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00004028 if (Sub == nullptr)
4029 return nullptr;
4030
4031 // Sub could be either of:
4032 // <type> ::= <substitution>
4033 // <type> ::= <template-template-param> <template-args>
4034 //
4035 // <template-template-param> ::= <template-param>
4036 // ::= <substitution>
4037 //
4038 // If this is followed by some <template-args>, and we're permitted to
4039 // parse them, take the second production.
4040
4041 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004042 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004043 if (TA == nullptr)
4044 return nullptr;
4045 Result = make<NameWithTemplateArgs>(Sub, TA);
4046 break;
4047 }
4048
4049 // If all we parsed was a substitution, don't re-insert into the
4050 // substitution table.
4051 return Sub;
4052 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004053 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004054 }
4055 // ::= <class-enum-type>
4056 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004057 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004058 break;
4059 }
4060 }
4061
4062 // If we parsed a type, insert it into the substitution table. Note that all
4063 // <builtin-type>s and <substitution>s have already bailed out, because they
4064 // don't get substitutions.
4065 if (Result != nullptr)
4066 Subs.push_back(Result);
4067 return Result;
4068}
4069
Pavel Labathba825192018-10-16 14:29:14 +00004070template <typename Derived, typename Alloc>
4071Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) {
4072 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004073 if (E == nullptr)
4074 return nullptr;
4075 return make<PrefixExpr>(Kind, E);
4076}
4077
Pavel Labathba825192018-10-16 14:29:14 +00004078template <typename Derived, typename Alloc>
4079Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) {
4080 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004081 if (LHS == nullptr)
4082 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004083 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004084 if (RHS == nullptr)
4085 return nullptr;
4086 return make<BinaryExpr>(LHS, Kind, RHS);
4087}
4088
Pavel Labathba825192018-10-16 14:29:14 +00004089template <typename Derived, typename Alloc>
4090Node *
4091AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004092 StringView Tmp = parseNumber(true);
4093 if (!Tmp.empty() && consumeIf('E'))
4094 return make<IntegerLiteral>(Lit, Tmp);
4095 return nullptr;
4096}
4097
4098// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004099template <typename Alloc, typename Derived>
4100Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004101 Qualifiers CVR = QualNone;
4102 if (consumeIf('r'))
4103 CVR |= QualRestrict;
4104 if (consumeIf('V'))
4105 CVR |= QualVolatile;
4106 if (consumeIf('K'))
4107 CVR |= QualConst;
4108 return CVR;
4109}
4110
4111// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4112// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4113// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4114// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
Erik Pilkington91c24af2020-05-13 22:19:45 -04004115// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004116template <typename Derived, typename Alloc>
4117Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004118 if (consumeIf("fpT"))
4119 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004120 if (consumeIf("fp")) {
4121 parseCVQualifiers();
4122 StringView Num = parseNumber();
4123 if (!consumeIf('_'))
4124 return nullptr;
4125 return make<FunctionParam>(Num);
4126 }
4127 if (consumeIf("fL")) {
4128 if (parseNumber().empty())
4129 return nullptr;
4130 if (!consumeIf('p'))
4131 return nullptr;
4132 parseCVQualifiers();
4133 StringView Num = parseNumber();
4134 if (!consumeIf('_'))
4135 return nullptr;
4136 return make<FunctionParam>(Num);
4137 }
4138 return nullptr;
4139}
4140
4141// [gs] nw <expression>* _ <type> E # new (expr-list) type
4142// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4143// [gs] na <expression>* _ <type> E # new[] (expr-list) type
4144// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4145// <initializer> ::= pi <expression>* E # parenthesized initialization
Pavel Labathba825192018-10-16 14:29:14 +00004146template <typename Derived, typename Alloc>
4147Node *AbstractManglingParser<Derived, Alloc>::parseNewExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004148 bool Global = consumeIf("gs");
4149 bool IsArray = look(1) == 'a';
4150 if (!consumeIf("nw") && !consumeIf("na"))
4151 return nullptr;
4152 size_t Exprs = Names.size();
4153 while (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00004154 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004155 if (Ex == nullptr)
4156 return nullptr;
4157 Names.push_back(Ex);
4158 }
4159 NodeArray ExprList = popTrailingNodeArray(Exprs);
Pavel Labathba825192018-10-16 14:29:14 +00004160 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004161 if (Ty == nullptr)
4162 return Ty;
4163 if (consumeIf("pi")) {
4164 size_t InitsBegin = Names.size();
4165 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004166 Node *Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004167 if (Init == nullptr)
4168 return Init;
4169 Names.push_back(Init);
4170 }
4171 NodeArray Inits = popTrailingNodeArray(InitsBegin);
4172 return make<NewExpr>(ExprList, Ty, Inits, Global, IsArray);
4173 } else if (!consumeIf('E'))
4174 return nullptr;
4175 return make<NewExpr>(ExprList, Ty, NodeArray(), Global, IsArray);
4176}
4177
4178// cv <type> <expression> # conversion with one argument
4179// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004180template <typename Derived, typename Alloc>
4181Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004182 if (!consumeIf("cv"))
4183 return nullptr;
4184 Node *Ty;
4185 {
4186 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004187 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004188 }
4189
4190 if (Ty == nullptr)
4191 return nullptr;
4192
4193 if (consumeIf('_')) {
4194 size_t ExprsBegin = Names.size();
4195 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004196 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004197 if (E == nullptr)
4198 return E;
4199 Names.push_back(E);
4200 }
4201 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4202 return make<ConversionExpr>(Ty, Exprs);
4203 }
4204
Pavel Labathba825192018-10-16 14:29:14 +00004205 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004206 if (E[0] == nullptr)
4207 return nullptr;
4208 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4209}
4210
4211// <expr-primary> ::= L <type> <value number> E # integer literal
4212// ::= L <type> <value float> E # floating literal
4213// ::= L <string type> E # string literal
4214// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004215// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004216// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4217// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004218template <typename Derived, typename Alloc>
4219Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004220 if (!consumeIf('L'))
4221 return nullptr;
4222 switch (look()) {
4223 case 'w':
4224 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004225 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004226 case 'b':
4227 if (consumeIf("b0E"))
4228 return make<BoolExpr>(0);
4229 if (consumeIf("b1E"))
4230 return make<BoolExpr>(1);
4231 return nullptr;
4232 case 'c':
4233 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004234 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004235 case 'a':
4236 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004237 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004238 case 'h':
4239 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004240 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004241 case 's':
4242 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004243 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004244 case 't':
4245 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004246 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004247 case 'i':
4248 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004249 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004250 case 'j':
4251 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004252 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004253 case 'l':
4254 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004255 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004256 case 'm':
4257 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004258 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004259 case 'x':
4260 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004261 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004262 case 'y':
4263 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004264 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004265 case 'n':
4266 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004267 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004268 case 'o':
4269 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004270 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004271 case 'f':
4272 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004273 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004274 case 'd':
4275 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004276 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004277 case 'e':
4278 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004279#if defined(__powerpc__) || defined(__s390__)
4280 // Handle cases where long doubles encoded with e have the same size
4281 // and representation as doubles.
4282 return getDerived().template parseFloatingLiteral<double>();
4283#else
Pavel Labathba825192018-10-16 14:29:14 +00004284 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004285#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004286 case '_':
4287 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004288 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004289 if (R != nullptr && consumeIf('E'))
4290 return R;
4291 }
4292 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004293 case 'A': {
4294 Node *T = getDerived().parseType();
4295 if (T == nullptr)
4296 return nullptr;
4297 // FIXME: We need to include the string contents in the mangling.
4298 if (consumeIf('E'))
4299 return make<StringLiteral>(T);
4300 return nullptr;
4301 }
4302 case 'D':
4303 if (consumeIf("DnE"))
4304 return make<NameType>("nullptr");
4305 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004306 case 'T':
4307 // Invalid mangled name per
4308 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4309 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004310 case 'U': {
4311 // FIXME: Should we support LUb... for block literals?
4312 if (look(1) != 'l')
4313 return nullptr;
4314 Node *T = parseUnnamedTypeName(nullptr);
4315 if (!T || !consumeIf('E'))
4316 return nullptr;
4317 return make<LambdaExpr>(T);
4318 }
Richard Smithc20d1442018-08-20 20:14:49 +00004319 default: {
4320 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004321 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004322 if (T == nullptr)
4323 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004324 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004325 if (N.empty())
4326 return nullptr;
4327 if (!consumeIf('E'))
4328 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004329 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004330 }
4331 }
4332}
4333
4334// <braced-expression> ::= <expression>
4335// ::= di <field source-name> <braced-expression> # .name = expr
4336// ::= dx <index expression> <braced-expression> # [expr] = expr
4337// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004338template <typename Derived, typename Alloc>
4339Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004340 if (look() == 'd') {
4341 switch (look(1)) {
4342 case 'i': {
4343 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004344 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004345 if (Field == nullptr)
4346 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004347 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004348 if (Init == nullptr)
4349 return nullptr;
4350 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4351 }
4352 case 'x': {
4353 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004354 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004355 if (Index == nullptr)
4356 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004357 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004358 if (Init == nullptr)
4359 return nullptr;
4360 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4361 }
4362 case 'X': {
4363 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004364 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004365 if (RangeBegin == nullptr)
4366 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004367 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004368 if (RangeEnd == nullptr)
4369 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004370 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004371 if (Init == nullptr)
4372 return nullptr;
4373 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4374 }
4375 }
4376 }
Pavel Labathba825192018-10-16 14:29:14 +00004377 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004378}
4379
4380// (not yet in the spec)
4381// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4382// ::= fR <binary-operator-name> <expression> <expression>
4383// ::= fl <binary-operator-name> <expression>
4384// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004385template <typename Derived, typename Alloc>
4386Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004387 if (!consumeIf('f'))
4388 return nullptr;
4389
4390 char FoldKind = look();
4391 bool IsLeftFold, HasInitializer;
4392 HasInitializer = FoldKind == 'L' || FoldKind == 'R';
4393 if (FoldKind == 'l' || FoldKind == 'L')
4394 IsLeftFold = true;
4395 else if (FoldKind == 'r' || FoldKind == 'R')
4396 IsLeftFold = false;
4397 else
4398 return nullptr;
4399 ++First;
4400
4401 // FIXME: This map is duplicated in parseOperatorName and parseExpr.
4402 StringView OperatorName;
4403 if (consumeIf("aa")) OperatorName = "&&";
4404 else if (consumeIf("an")) OperatorName = "&";
4405 else if (consumeIf("aN")) OperatorName = "&=";
4406 else if (consumeIf("aS")) OperatorName = "=";
4407 else if (consumeIf("cm")) OperatorName = ",";
4408 else if (consumeIf("ds")) OperatorName = ".*";
4409 else if (consumeIf("dv")) OperatorName = "/";
4410 else if (consumeIf("dV")) OperatorName = "/=";
4411 else if (consumeIf("eo")) OperatorName = "^";
4412 else if (consumeIf("eO")) OperatorName = "^=";
4413 else if (consumeIf("eq")) OperatorName = "==";
4414 else if (consumeIf("ge")) OperatorName = ">=";
4415 else if (consumeIf("gt")) OperatorName = ">";
4416 else if (consumeIf("le")) OperatorName = "<=";
4417 else if (consumeIf("ls")) OperatorName = "<<";
4418 else if (consumeIf("lS")) OperatorName = "<<=";
4419 else if (consumeIf("lt")) OperatorName = "<";
4420 else if (consumeIf("mi")) OperatorName = "-";
4421 else if (consumeIf("mI")) OperatorName = "-=";
4422 else if (consumeIf("ml")) OperatorName = "*";
4423 else if (consumeIf("mL")) OperatorName = "*=";
4424 else if (consumeIf("ne")) OperatorName = "!=";
4425 else if (consumeIf("oo")) OperatorName = "||";
4426 else if (consumeIf("or")) OperatorName = "|";
4427 else if (consumeIf("oR")) OperatorName = "|=";
4428 else if (consumeIf("pl")) OperatorName = "+";
4429 else if (consumeIf("pL")) OperatorName = "+=";
4430 else if (consumeIf("rm")) OperatorName = "%";
4431 else if (consumeIf("rM")) OperatorName = "%=";
4432 else if (consumeIf("rs")) OperatorName = ">>";
4433 else if (consumeIf("rS")) OperatorName = ">>=";
4434 else return nullptr;
4435
Pavel Labathba825192018-10-16 14:29:14 +00004436 Node *Pack = getDerived().parseExpr(), *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004437 if (Pack == nullptr)
4438 return nullptr;
4439 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004440 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004441 if (Init == nullptr)
4442 return nullptr;
4443 }
4444
4445 if (IsLeftFold && Init)
4446 std::swap(Pack, Init);
4447
4448 return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
4449}
4450
Richard Smith1865d2f2020-10-22 19:29:36 -07004451// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4452//
4453// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4454template <typename Derived, typename Alloc>
4455Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr() {
4456 Node *Ty = getDerived().parseType();
4457 if (!Ty)
4458 return nullptr;
4459 Node *Expr = getDerived().parseExpr();
4460 if (!Expr)
4461 return nullptr;
4462 StringView Offset = getDerived().parseNumber(true);
4463 if (!consumeIf('E'))
4464 return nullptr;
4465 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset);
4466}
4467
4468// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4469// <union-selector> ::= _ [<number>]
4470//
4471// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4472template <typename Derived, typename Alloc>
4473Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4474 Node *Ty = getDerived().parseType();
4475 if (!Ty)
4476 return nullptr;
4477 Node *Expr = getDerived().parseExpr();
4478 if (!Expr)
4479 return nullptr;
4480 StringView Offset = getDerived().parseNumber(true);
4481 size_t SelectorsBegin = Names.size();
4482 while (consumeIf('_')) {
4483 Node *Selector = make<NameType>(parseNumber());
4484 if (!Selector)
4485 return nullptr;
4486 Names.push_back(Selector);
4487 }
4488 bool OnePastTheEnd = consumeIf('p');
4489 if (!consumeIf('E'))
4490 return nullptr;
4491 return make<SubobjectExpr>(
4492 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4493}
4494
Richard Smithc20d1442018-08-20 20:14:49 +00004495// <expression> ::= <unary operator-name> <expression>
4496// ::= <binary operator-name> <expression> <expression>
4497// ::= <ternary operator-name> <expression> <expression> <expression>
4498// ::= cl <expression>+ E # call
4499// ::= cv <type> <expression> # conversion with one argument
4500// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4501// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4502// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4503// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4504// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4505// ::= [gs] dl <expression> # delete expression
4506// ::= [gs] da <expression> # delete[] expression
4507// ::= pp_ <expression> # prefix ++
4508// ::= mm_ <expression> # prefix --
4509// ::= ti <type> # typeid (type)
4510// ::= te <expression> # typeid (expression)
4511// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4512// ::= sc <type> <expression> # static_cast<type> (expression)
4513// ::= cc <type> <expression> # const_cast<type> (expression)
4514// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4515// ::= st <type> # sizeof (a type)
4516// ::= sz <expression> # sizeof (an expression)
4517// ::= at <type> # alignof (a type)
4518// ::= az <expression> # alignof (an expression)
4519// ::= nx <expression> # noexcept (expression)
4520// ::= <template-param>
4521// ::= <function-param>
4522// ::= dt <expression> <unresolved-name> # expr.name
4523// ::= pt <expression> <unresolved-name> # expr->name
4524// ::= ds <expression> <expression> # expr.*expr
4525// ::= sZ <template-param> # size of a parameter pack
4526// ::= sZ <function-param> # size of a function parameter pack
4527// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4528// ::= sp <expression> # pack expansion
4529// ::= tw <expression> # throw expression
4530// ::= tr # throw with no operand (rethrow)
4531// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4532// # freestanding dependent name (e.g., T::x),
4533// # objectless nonstatic member reference
4534// ::= fL <binary-operator-name> <expression> <expression>
4535// ::= fR <binary-operator-name> <expression> <expression>
4536// ::= fl <binary-operator-name> <expression>
4537// ::= fr <binary-operator-name> <expression>
4538// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004539template <typename Derived, typename Alloc>
4540Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004541 bool Global = consumeIf("gs");
4542 if (numLeft() < 2)
4543 return nullptr;
4544
4545 switch (*First) {
4546 case 'L':
Pavel Labathba825192018-10-16 14:29:14 +00004547 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00004548 case 'T':
Pavel Labathba825192018-10-16 14:29:14 +00004549 return getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004550 case 'f': {
4551 // Disambiguate a fold expression from a <function-param>.
4552 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
Pavel Labathba825192018-10-16 14:29:14 +00004553 return getDerived().parseFunctionParam();
4554 return getDerived().parseFoldExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004555 }
4556 case 'a':
4557 switch (First[1]) {
4558 case 'a':
4559 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004560 return getDerived().parseBinaryExpr("&&");
Richard Smithc20d1442018-08-20 20:14:49 +00004561 case 'd':
4562 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004563 return getDerived().parsePrefixExpr("&");
Richard Smithc20d1442018-08-20 20:14:49 +00004564 case 'n':
4565 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004566 return getDerived().parseBinaryExpr("&");
Richard Smithc20d1442018-08-20 20:14:49 +00004567 case 'N':
4568 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004569 return getDerived().parseBinaryExpr("&=");
Richard Smithc20d1442018-08-20 20:14:49 +00004570 case 'S':
4571 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004572 return getDerived().parseBinaryExpr("=");
Richard Smithc20d1442018-08-20 20:14:49 +00004573 case 't': {
4574 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004575 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004576 if (Ty == nullptr)
4577 return nullptr;
4578 return make<EnclosingExpr>("alignof (", Ty, ")");
4579 }
4580 case 'z': {
4581 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004582 Node *Ty = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004583 if (Ty == nullptr)
4584 return nullptr;
4585 return make<EnclosingExpr>("alignof (", Ty, ")");
4586 }
4587 }
4588 return nullptr;
4589 case 'c':
4590 switch (First[1]) {
4591 // cc <type> <expression> # const_cast<type>(expression)
4592 case 'c': {
4593 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004594 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004595 if (Ty == nullptr)
4596 return Ty;
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<CastExpr>("const_cast", Ty, Ex);
4601 }
4602 // cl <expression>+ E # call
4603 case 'l': {
4604 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004605 Node *Callee = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004606 if (Callee == nullptr)
4607 return Callee;
4608 size_t ExprsBegin = Names.size();
4609 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004610 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004611 if (E == nullptr)
4612 return E;
4613 Names.push_back(E);
4614 }
4615 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin));
4616 }
4617 case 'm':
4618 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004619 return getDerived().parseBinaryExpr(",");
Richard Smithc20d1442018-08-20 20:14:49 +00004620 case 'o':
4621 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004622 return getDerived().parsePrefixExpr("~");
Richard Smithc20d1442018-08-20 20:14:49 +00004623 case 'v':
Pavel Labathba825192018-10-16 14:29:14 +00004624 return getDerived().parseConversionExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004625 }
4626 return nullptr;
4627 case 'd':
4628 switch (First[1]) {
4629 case 'a': {
4630 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004631 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004632 if (Ex == nullptr)
4633 return Ex;
4634 return make<DeleteExpr>(Ex, Global, /*is_array=*/true);
4635 }
4636 case 'c': {
4637 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004638 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004639 if (T == nullptr)
4640 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004641 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004642 if (Ex == nullptr)
4643 return Ex;
4644 return make<CastExpr>("dynamic_cast", T, Ex);
4645 }
4646 case 'e':
4647 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004648 return getDerived().parsePrefixExpr("*");
Richard Smithc20d1442018-08-20 20:14:49 +00004649 case 'l': {
4650 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004651 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004652 if (E == nullptr)
4653 return E;
4654 return make<DeleteExpr>(E, Global, /*is_array=*/false);
4655 }
4656 case 'n':
Pavel Labathba825192018-10-16 14:29:14 +00004657 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004658 case 's': {
4659 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004660 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004661 if (LHS == nullptr)
4662 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004663 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004664 if (RHS == nullptr)
4665 return nullptr;
4666 return make<MemberExpr>(LHS, ".*", RHS);
4667 }
4668 case 't': {
4669 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004670 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004671 if (LHS == nullptr)
4672 return LHS;
Pavel Labathba825192018-10-16 14:29:14 +00004673 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004674 if (RHS == nullptr)
4675 return nullptr;
4676 return make<MemberExpr>(LHS, ".", RHS);
4677 }
4678 case 'v':
4679 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004680 return getDerived().parseBinaryExpr("/");
Richard Smithc20d1442018-08-20 20:14:49 +00004681 case 'V':
4682 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004683 return getDerived().parseBinaryExpr("/=");
Richard Smithc20d1442018-08-20 20:14:49 +00004684 }
4685 return nullptr;
4686 case 'e':
4687 switch (First[1]) {
4688 case 'o':
4689 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004690 return getDerived().parseBinaryExpr("^");
Richard Smithc20d1442018-08-20 20:14:49 +00004691 case 'O':
4692 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004693 return getDerived().parseBinaryExpr("^=");
Richard Smithc20d1442018-08-20 20:14:49 +00004694 case 'q':
4695 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004696 return getDerived().parseBinaryExpr("==");
Richard Smithc20d1442018-08-20 20:14:49 +00004697 }
4698 return nullptr;
4699 case 'g':
4700 switch (First[1]) {
4701 case 'e':
4702 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004703 return getDerived().parseBinaryExpr(">=");
Richard Smithc20d1442018-08-20 20:14:49 +00004704 case 't':
4705 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004706 return getDerived().parseBinaryExpr(">");
Richard Smithc20d1442018-08-20 20:14:49 +00004707 }
4708 return nullptr;
4709 case 'i':
4710 switch (First[1]) {
4711 case 'x': {
4712 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004713 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004714 if (Base == nullptr)
4715 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004716 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004717 if (Index == nullptr)
4718 return Index;
4719 return make<ArraySubscriptExpr>(Base, Index);
4720 }
4721 case 'l': {
4722 First += 2;
4723 size_t InitsBegin = Names.size();
4724 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004725 Node *E = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004726 if (E == nullptr)
4727 return nullptr;
4728 Names.push_back(E);
4729 }
4730 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4731 }
4732 }
4733 return nullptr;
4734 case 'l':
4735 switch (First[1]) {
4736 case 'e':
4737 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004738 return getDerived().parseBinaryExpr("<=");
Richard Smithc20d1442018-08-20 20:14:49 +00004739 case 's':
4740 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004741 return getDerived().parseBinaryExpr("<<");
Richard Smithc20d1442018-08-20 20:14:49 +00004742 case 'S':
4743 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004744 return getDerived().parseBinaryExpr("<<=");
Richard Smithc20d1442018-08-20 20:14:49 +00004745 case 't':
4746 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004747 return getDerived().parseBinaryExpr("<");
Richard Smithc20d1442018-08-20 20:14:49 +00004748 }
4749 return nullptr;
4750 case 'm':
4751 switch (First[1]) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004752 case 'c':
4753 First += 2;
4754 return parsePointerToMemberConversionExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004755 case 'i':
4756 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004757 return getDerived().parseBinaryExpr("-");
Richard Smithc20d1442018-08-20 20:14:49 +00004758 case 'I':
4759 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004760 return getDerived().parseBinaryExpr("-=");
Richard Smithc20d1442018-08-20 20:14:49 +00004761 case 'l':
4762 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004763 return getDerived().parseBinaryExpr("*");
Richard Smithc20d1442018-08-20 20:14:49 +00004764 case 'L':
4765 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004766 return getDerived().parseBinaryExpr("*=");
Richard Smithc20d1442018-08-20 20:14:49 +00004767 case 'm':
4768 First += 2;
4769 if (consumeIf('_'))
Pavel Labathba825192018-10-16 14:29:14 +00004770 return getDerived().parsePrefixExpr("--");
4771 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004772 if (Ex == nullptr)
4773 return nullptr;
4774 return make<PostfixExpr>(Ex, "--");
4775 }
4776 return nullptr;
4777 case 'n':
4778 switch (First[1]) {
4779 case 'a':
4780 case 'w':
Pavel Labathba825192018-10-16 14:29:14 +00004781 return getDerived().parseNewExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004782 case 'e':
4783 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004784 return getDerived().parseBinaryExpr("!=");
Richard Smithc20d1442018-08-20 20:14:49 +00004785 case 'g':
4786 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004787 return getDerived().parsePrefixExpr("-");
Richard Smithc20d1442018-08-20 20:14:49 +00004788 case 't':
4789 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004790 return getDerived().parsePrefixExpr("!");
Richard Smithc20d1442018-08-20 20:14:49 +00004791 case 'x':
4792 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004793 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004794 if (Ex == nullptr)
4795 return Ex;
4796 return make<EnclosingExpr>("noexcept (", Ex, ")");
4797 }
4798 return nullptr;
4799 case 'o':
4800 switch (First[1]) {
4801 case 'n':
Pavel Labathba825192018-10-16 14:29:14 +00004802 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004803 case 'o':
4804 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004805 return getDerived().parseBinaryExpr("||");
Richard Smithc20d1442018-08-20 20:14:49 +00004806 case 'r':
4807 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004808 return getDerived().parseBinaryExpr("|");
Richard Smithc20d1442018-08-20 20:14:49 +00004809 case 'R':
4810 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004811 return getDerived().parseBinaryExpr("|=");
Richard Smithc20d1442018-08-20 20:14:49 +00004812 }
4813 return nullptr;
4814 case 'p':
4815 switch (First[1]) {
4816 case 'm':
4817 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004818 return getDerived().parseBinaryExpr("->*");
Richard Smithc20d1442018-08-20 20:14:49 +00004819 case 'l':
4820 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004821 return getDerived().parseBinaryExpr("+");
Richard Smithc20d1442018-08-20 20:14:49 +00004822 case 'L':
4823 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004824 return getDerived().parseBinaryExpr("+=");
Richard Smithc20d1442018-08-20 20:14:49 +00004825 case 'p': {
4826 First += 2;
4827 if (consumeIf('_'))
Pavel Labathba825192018-10-16 14:29:14 +00004828 return getDerived().parsePrefixExpr("++");
4829 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004830 if (Ex == nullptr)
4831 return Ex;
4832 return make<PostfixExpr>(Ex, "++");
4833 }
4834 case 's':
4835 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004836 return getDerived().parsePrefixExpr("+");
Richard Smithc20d1442018-08-20 20:14:49 +00004837 case 't': {
4838 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004839 Node *L = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004840 if (L == nullptr)
4841 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004842 Node *R = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004843 if (R == nullptr)
4844 return nullptr;
4845 return make<MemberExpr>(L, "->", R);
4846 }
4847 }
4848 return nullptr;
4849 case 'q':
4850 if (First[1] == 'u') {
4851 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004852 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004853 if (Cond == nullptr)
4854 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004855 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004856 if (LHS == nullptr)
4857 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004858 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004859 if (RHS == nullptr)
4860 return nullptr;
4861 return make<ConditionalExpr>(Cond, LHS, RHS);
4862 }
4863 return nullptr;
4864 case 'r':
4865 switch (First[1]) {
4866 case 'c': {
4867 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004868 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004869 if (T == nullptr)
4870 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004871 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004872 if (Ex == nullptr)
4873 return Ex;
4874 return make<CastExpr>("reinterpret_cast", T, Ex);
4875 }
4876 case 'm':
4877 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004878 return getDerived().parseBinaryExpr("%");
Richard Smithc20d1442018-08-20 20:14:49 +00004879 case 'M':
4880 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004881 return getDerived().parseBinaryExpr("%=");
Richard Smithc20d1442018-08-20 20:14:49 +00004882 case 's':
4883 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004884 return getDerived().parseBinaryExpr(">>");
Richard Smithc20d1442018-08-20 20:14:49 +00004885 case 'S':
4886 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004887 return getDerived().parseBinaryExpr(">>=");
Richard Smithc20d1442018-08-20 20:14:49 +00004888 }
4889 return nullptr;
4890 case 's':
4891 switch (First[1]) {
4892 case 'c': {
4893 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004894 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004895 if (T == nullptr)
4896 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004897 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004898 if (Ex == nullptr)
4899 return Ex;
4900 return make<CastExpr>("static_cast", T, Ex);
4901 }
Richard Smith1865d2f2020-10-22 19:29:36 -07004902 case 'o':
4903 First += 2;
4904 return parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004905 case 'p': {
4906 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004907 Node *Child = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004908 if (Child == nullptr)
4909 return nullptr;
4910 return make<ParameterPackExpansion>(Child);
4911 }
4912 case 'r':
Pavel Labathba825192018-10-16 14:29:14 +00004913 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004914 case 't': {
4915 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004916 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004917 if (Ty == nullptr)
4918 return Ty;
4919 return make<EnclosingExpr>("sizeof (", Ty, ")");
4920 }
4921 case 'z': {
4922 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004923 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004924 if (Ex == nullptr)
4925 return Ex;
4926 return make<EnclosingExpr>("sizeof (", Ex, ")");
4927 }
4928 case 'Z':
4929 First += 2;
4930 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00004931 Node *R = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004932 if (R == nullptr)
4933 return nullptr;
4934 return make<SizeofParamPackExpr>(R);
4935 } else if (look() == 'f') {
Pavel Labathba825192018-10-16 14:29:14 +00004936 Node *FP = getDerived().parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004937 if (FP == nullptr)
4938 return nullptr;
4939 return make<EnclosingExpr>("sizeof... (", FP, ")");
4940 }
4941 return nullptr;
4942 case 'P': {
4943 First += 2;
4944 size_t ArgsBegin = Names.size();
4945 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004946 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00004947 if (Arg == nullptr)
4948 return nullptr;
4949 Names.push_back(Arg);
4950 }
Richard Smithb485b352018-08-24 23:30:26 +00004951 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4952 if (!Pack)
4953 return nullptr;
4954 return make<EnclosingExpr>("sizeof... (", Pack, ")");
Richard Smithc20d1442018-08-20 20:14:49 +00004955 }
4956 }
4957 return nullptr;
4958 case 't':
4959 switch (First[1]) {
4960 case 'e': {
4961 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004962 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004963 if (Ex == nullptr)
4964 return Ex;
4965 return make<EnclosingExpr>("typeid (", Ex, ")");
4966 }
4967 case 'i': {
4968 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004969 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004970 if (Ty == nullptr)
4971 return Ty;
4972 return make<EnclosingExpr>("typeid (", Ty, ")");
4973 }
4974 case 'l': {
4975 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004976 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004977 if (Ty == nullptr)
4978 return nullptr;
4979 size_t InitsBegin = Names.size();
4980 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004981 Node *E = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004982 if (E == nullptr)
4983 return nullptr;
4984 Names.push_back(E);
4985 }
4986 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4987 }
4988 case 'r':
4989 First += 2;
4990 return make<NameType>("throw");
4991 case 'w': {
4992 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004993 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004994 if (Ex == nullptr)
4995 return nullptr;
4996 return make<ThrowExpr>(Ex);
4997 }
4998 }
4999 return nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05005000 case 'u': {
5001 ++First;
5002 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
5003 if (!Name)
5004 return nullptr;
5005 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
5006 // standard encoding expects a <template-arg>, and would be otherwise be
5007 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
5008 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
5009 // actual conflict here.
5010 if (Name->getBaseName() == "__uuidof") {
5011 if (numLeft() < 2)
5012 return nullptr;
5013 if (*First == 't') {
5014 ++First;
5015 Node *Ty = getDerived().parseType();
5016 if (!Ty)
5017 return nullptr;
5018 return make<CallExpr>(Name, makeNodeArray(&Ty, &Ty + 1));
5019 }
5020 if (*First == 'z') {
5021 ++First;
5022 Node *Ex = getDerived().parseExpr();
5023 if (!Ex)
5024 return nullptr;
5025 return make<CallExpr>(Name, makeNodeArray(&Ex, &Ex + 1));
5026 }
5027 }
5028 size_t ExprsBegin = Names.size();
5029 while (!consumeIf('E')) {
5030 Node *E = getDerived().parseTemplateArg();
5031 if (E == nullptr)
5032 return E;
5033 Names.push_back(E);
5034 }
5035 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin));
5036 }
Richard Smithc20d1442018-08-20 20:14:49 +00005037 case '1':
5038 case '2':
5039 case '3':
5040 case '4':
5041 case '5':
5042 case '6':
5043 case '7':
5044 case '8':
5045 case '9':
Pavel Labathba825192018-10-16 14:29:14 +00005046 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00005047 }
5048 return nullptr;
5049}
5050
5051// <call-offset> ::= h <nv-offset> _
5052// ::= v <v-offset> _
5053//
5054// <nv-offset> ::= <offset number>
5055// # non-virtual base override
5056//
5057// <v-offset> ::= <offset number> _ <virtual offset number>
5058// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00005059template <typename Alloc, typename Derived>
5060bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00005061 // Just scan through the call offset, we never add this information into the
5062 // output.
5063 if (consumeIf('h'))
5064 return parseNumber(true).empty() || !consumeIf('_');
5065 if (consumeIf('v'))
5066 return parseNumber(true).empty() || !consumeIf('_') ||
5067 parseNumber(true).empty() || !consumeIf('_');
5068 return true;
5069}
5070
5071// <special-name> ::= TV <type> # virtual table
5072// ::= TT <type> # VTT structure (construction vtable index)
5073// ::= TI <type> # typeinfo structure
5074// ::= TS <type> # typeinfo name (null-terminated byte string)
5075// ::= Tc <call-offset> <call-offset> <base encoding>
5076// # base is the nominal target function of thunk
5077// # first call-offset is 'this' adjustment
5078// # second call-offset is result adjustment
5079// ::= T <call-offset> <base encoding>
5080// # base is the nominal target function of thunk
5081// ::= GV <object name> # Guard variable for one-time initialization
5082// # No <type>
5083// ::= TW <object name> # Thread-local wrapper
5084// ::= TH <object name> # Thread-local initialization
5085// ::= GR <object name> _ # First temporary
5086// ::= GR <object name> <seq-id> _ # Subsequent temporaries
5087// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
5088// extension ::= GR <object name> # reference temporary for object
Pavel Labathba825192018-10-16 14:29:14 +00005089template <typename Derived, typename Alloc>
5090Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00005091 switch (look()) {
5092 case 'T':
5093 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07005094 // TA <template-arg> # template parameter object
5095 //
5096 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
5097 case 'A': {
5098 First += 2;
5099 Node *Arg = getDerived().parseTemplateArg();
5100 if (Arg == nullptr)
5101 return nullptr;
5102 return make<SpecialName>("template parameter object for ", Arg);
5103 }
Richard Smithc20d1442018-08-20 20:14:49 +00005104 // TV <type> # virtual table
5105 case 'V': {
5106 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005107 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005108 if (Ty == nullptr)
5109 return nullptr;
5110 return make<SpecialName>("vtable for ", Ty);
5111 }
5112 // TT <type> # VTT structure (construction vtable index)
5113 case 'T': {
5114 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005115 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005116 if (Ty == nullptr)
5117 return nullptr;
5118 return make<SpecialName>("VTT for ", Ty);
5119 }
5120 // TI <type> # typeinfo structure
5121 case 'I': {
5122 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005123 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005124 if (Ty == nullptr)
5125 return nullptr;
5126 return make<SpecialName>("typeinfo for ", Ty);
5127 }
5128 // TS <type> # typeinfo name (null-terminated byte string)
5129 case 'S': {
5130 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005131 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005132 if (Ty == nullptr)
5133 return nullptr;
5134 return make<SpecialName>("typeinfo name for ", Ty);
5135 }
5136 // Tc <call-offset> <call-offset> <base encoding>
5137 case 'c': {
5138 First += 2;
5139 if (parseCallOffset() || parseCallOffset())
5140 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00005141 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005142 if (Encoding == nullptr)
5143 return nullptr;
5144 return make<SpecialName>("covariant return thunk to ", Encoding);
5145 }
5146 // extension ::= TC <first type> <number> _ <second type>
5147 // # construction vtable for second-in-first
5148 case 'C': {
5149 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005150 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005151 if (FirstType == nullptr)
5152 return nullptr;
5153 if (parseNumber(true).empty() || !consumeIf('_'))
5154 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00005155 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005156 if (SecondType == nullptr)
5157 return nullptr;
5158 return make<CtorVtableSpecialName>(SecondType, FirstType);
5159 }
5160 // TW <object name> # Thread-local wrapper
5161 case 'W': {
5162 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005163 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005164 if (Name == nullptr)
5165 return nullptr;
5166 return make<SpecialName>("thread-local wrapper routine for ", Name);
5167 }
5168 // TH <object name> # Thread-local initialization
5169 case 'H': {
5170 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005171 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005172 if (Name == nullptr)
5173 return nullptr;
5174 return make<SpecialName>("thread-local initialization routine for ", Name);
5175 }
5176 // T <call-offset> <base encoding>
5177 default: {
5178 ++First;
5179 bool IsVirt = look() == 'v';
5180 if (parseCallOffset())
5181 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00005182 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005183 if (BaseEncoding == nullptr)
5184 return nullptr;
5185 if (IsVirt)
5186 return make<SpecialName>("virtual thunk to ", BaseEncoding);
5187 else
5188 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
5189 }
5190 }
5191 case 'G':
5192 switch (look(1)) {
5193 // GV <object name> # Guard variable for one-time initialization
5194 case 'V': {
5195 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005196 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005197 if (Name == nullptr)
5198 return nullptr;
5199 return make<SpecialName>("guard variable for ", Name);
5200 }
5201 // GR <object name> # reference temporary for object
5202 // GR <object name> _ # First temporary
5203 // GR <object name> <seq-id> _ # Subsequent temporaries
5204 case 'R': {
5205 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005206 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005207 if (Name == nullptr)
5208 return nullptr;
5209 size_t Count;
5210 bool ParsedSeqId = !parseSeqId(&Count);
5211 if (!consumeIf('_') && ParsedSeqId)
5212 return nullptr;
5213 return make<SpecialName>("reference temporary for ", Name);
5214 }
5215 }
5216 }
5217 return nullptr;
5218}
5219
5220// <encoding> ::= <function name> <bare-function-type>
5221// ::= <data name>
5222// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005223template <typename Derived, typename Alloc>
5224Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005225 // The template parameters of an encoding are unrelated to those of the
5226 // enclosing context.
5227 class SaveTemplateParams {
5228 AbstractManglingParser *Parser;
5229 decltype(TemplateParams) OldParams;
5230
5231 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005232 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005233 OldParams = std::move(Parser->TemplateParams);
5234 Parser->TemplateParams.clear();
5235 }
5236 ~SaveTemplateParams() {
5237 Parser->TemplateParams = std::move(OldParams);
5238 }
5239 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005240
Richard Smithc20d1442018-08-20 20:14:49 +00005241 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005242 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005243
5244 auto IsEndOfEncoding = [&] {
5245 // The set of chars that can potentially follow an <encoding> (none of which
5246 // can start a <type>). Enumerating these allows us to avoid speculative
5247 // parsing.
5248 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5249 };
5250
5251 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005252 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005253 if (Name == nullptr)
5254 return nullptr;
5255
5256 if (resolveForwardTemplateRefs(NameInfo))
5257 return nullptr;
5258
5259 if (IsEndOfEncoding())
5260 return Name;
5261
5262 Node *Attrs = nullptr;
5263 if (consumeIf("Ua9enable_ifI")) {
5264 size_t BeforeArgs = Names.size();
5265 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005266 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005267 if (Arg == nullptr)
5268 return nullptr;
5269 Names.push_back(Arg);
5270 }
5271 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005272 if (!Attrs)
5273 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005274 }
5275
5276 Node *ReturnType = nullptr;
5277 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005278 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005279 if (ReturnType == nullptr)
5280 return nullptr;
5281 }
5282
5283 if (consumeIf('v'))
5284 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5285 Attrs, NameInfo.CVQualifiers,
5286 NameInfo.ReferenceQualifier);
5287
5288 size_t ParamsBegin = Names.size();
5289 do {
Pavel Labathba825192018-10-16 14:29:14 +00005290 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005291 if (Ty == nullptr)
5292 return nullptr;
5293 Names.push_back(Ty);
5294 } while (!IsEndOfEncoding());
5295
5296 return make<FunctionEncoding>(ReturnType, Name,
5297 popTrailingNodeArray(ParamsBegin),
5298 Attrs, NameInfo.CVQualifiers,
5299 NameInfo.ReferenceQualifier);
5300}
5301
5302template <class Float>
5303struct FloatData;
5304
5305template <>
5306struct FloatData<float>
5307{
5308 static const size_t mangled_size = 8;
5309 static const size_t max_demangled_size = 24;
5310 static constexpr const char* spec = "%af";
5311};
5312
5313template <>
5314struct FloatData<double>
5315{
5316 static const size_t mangled_size = 16;
5317 static const size_t max_demangled_size = 32;
5318 static constexpr const char* spec = "%a";
5319};
5320
5321template <>
5322struct FloatData<long double>
5323{
5324#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5325 defined(__wasm__)
5326 static const size_t mangled_size = 32;
5327#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5328 static const size_t mangled_size = 16;
5329#else
5330 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5331#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005332 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5333 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5334 // Negatives are one character longer than positives.
5335 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5336 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5337 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005338 static constexpr const char *spec = "%LaL";
5339};
5340
Pavel Labathba825192018-10-16 14:29:14 +00005341template <typename Alloc, typename Derived>
5342template <class Float>
5343Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005344 const size_t N = FloatData<Float>::mangled_size;
5345 if (numLeft() <= N)
5346 return nullptr;
5347 StringView Data(First, First + N);
5348 for (char C : Data)
5349 if (!std::isxdigit(C))
5350 return nullptr;
5351 First += N;
5352 if (!consumeIf('E'))
5353 return nullptr;
5354 return make<FloatLiteralImpl<Float>>(Data);
5355}
5356
5357// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005358template <typename Alloc, typename Derived>
5359bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005360 if (!(look() >= '0' && look() <= '9') &&
5361 !(look() >= 'A' && look() <= 'Z'))
5362 return true;
5363
5364 size_t Id = 0;
5365 while (true) {
5366 if (look() >= '0' && look() <= '9') {
5367 Id *= 36;
5368 Id += static_cast<size_t>(look() - '0');
5369 } else if (look() >= 'A' && look() <= 'Z') {
5370 Id *= 36;
5371 Id += static_cast<size_t>(look() - 'A') + 10;
5372 } else {
5373 *Out = Id;
5374 return false;
5375 }
5376 ++First;
5377 }
5378}
5379
5380// <substitution> ::= S <seq-id> _
5381// ::= S_
5382// <substitution> ::= Sa # ::std::allocator
5383// <substitution> ::= Sb # ::std::basic_string
5384// <substitution> ::= Ss # ::std::basic_string < char,
5385// ::std::char_traits<char>,
5386// ::std::allocator<char> >
5387// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5388// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5389// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Pavel Labathba825192018-10-16 14:29:14 +00005390template <typename Derived, typename Alloc>
5391Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005392 if (!consumeIf('S'))
5393 return nullptr;
5394
5395 if (std::islower(look())) {
5396 Node *SpecialSub;
5397 switch (look()) {
5398 case 'a':
5399 ++First;
5400 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::allocator);
5401 break;
5402 case 'b':
5403 ++First;
5404 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::basic_string);
5405 break;
5406 case 's':
5407 ++First;
5408 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::string);
5409 break;
5410 case 'i':
5411 ++First;
5412 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::istream);
5413 break;
5414 case 'o':
5415 ++First;
5416 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::ostream);
5417 break;
5418 case 'd':
5419 ++First;
5420 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::iostream);
5421 break;
5422 default:
5423 return nullptr;
5424 }
Richard Smithb485b352018-08-24 23:30:26 +00005425 if (!SpecialSub)
5426 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005427 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5428 // has ABI tags, the tags are appended to the substitution; the result is a
5429 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005430 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005431 if (WithTags != SpecialSub) {
5432 Subs.push_back(WithTags);
5433 SpecialSub = WithTags;
5434 }
5435 return SpecialSub;
5436 }
5437
5438 // ::= S_
5439 if (consumeIf('_')) {
5440 if (Subs.empty())
5441 return nullptr;
5442 return Subs[0];
5443 }
5444
5445 // ::= S <seq-id> _
5446 size_t Index = 0;
5447 if (parseSeqId(&Index))
5448 return nullptr;
5449 ++Index;
5450 if (!consumeIf('_') || Index >= Subs.size())
5451 return nullptr;
5452 return Subs[Index];
5453}
5454
5455// <template-param> ::= T_ # first template parameter
5456// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005457// ::= TL <level-1> __
5458// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005459template <typename Derived, typename Alloc>
5460Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005461 if (!consumeIf('T'))
5462 return nullptr;
5463
Richard Smithdf1c14c2019-09-06 23:53:21 +00005464 size_t Level = 0;
5465 if (consumeIf('L')) {
5466 if (parsePositiveInteger(&Level))
5467 return nullptr;
5468 ++Level;
5469 if (!consumeIf('_'))
5470 return nullptr;
5471 }
5472
Richard Smithc20d1442018-08-20 20:14:49 +00005473 size_t Index = 0;
5474 if (!consumeIf('_')) {
5475 if (parsePositiveInteger(&Index))
5476 return nullptr;
5477 ++Index;
5478 if (!consumeIf('_'))
5479 return nullptr;
5480 }
5481
Richard Smithc20d1442018-08-20 20:14:49 +00005482 // If we're in a context where this <template-param> refers to a
5483 // <template-arg> further ahead in the mangled name (currently just conversion
5484 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005485 // This can only happen at the outermost level.
5486 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005487 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5488 if (!ForwardRef)
5489 return nullptr;
5490 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5491 ForwardTemplateRefs.push_back(
5492 static_cast<ForwardTemplateReference *>(ForwardRef));
5493 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005494 }
5495
Richard Smithdf1c14c2019-09-06 23:53:21 +00005496 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5497 Index >= TemplateParams[Level]->size()) {
5498 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5499 // list are mangled as the corresponding artificial template type parameter.
5500 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5501 // This will be popped by the ScopedTemplateParamList in
5502 // parseUnnamedTypeName.
5503 if (Level == TemplateParams.size())
5504 TemplateParams.push_back(nullptr);
5505 return make<NameType>("auto");
5506 }
5507
Richard Smithc20d1442018-08-20 20:14:49 +00005508 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005509 }
5510
5511 return (*TemplateParams[Level])[Index];
5512}
5513
5514// <template-param-decl> ::= Ty # type parameter
5515// ::= Tn <type> # non-type parameter
5516// ::= Tt <template-param-decl>* E # template parameter
5517// ::= Tp <template-param-decl> # parameter pack
5518template <typename Derived, typename Alloc>
5519Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5520 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5521 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5522 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5523 if (N) TemplateParams.back()->push_back(N);
5524 return N;
5525 };
5526
5527 if (consumeIf("Ty")) {
5528 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5529 if (!Name)
5530 return nullptr;
5531 return make<TypeTemplateParamDecl>(Name);
5532 }
5533
5534 if (consumeIf("Tn")) {
5535 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5536 if (!Name)
5537 return nullptr;
5538 Node *Type = parseType();
5539 if (!Type)
5540 return nullptr;
5541 return make<NonTypeTemplateParamDecl>(Name, Type);
5542 }
5543
5544 if (consumeIf("Tt")) {
5545 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5546 if (!Name)
5547 return nullptr;
5548 size_t ParamsBegin = Names.size();
5549 ScopedTemplateParamList TemplateTemplateParamParams(this);
5550 while (!consumeIf("E")) {
5551 Node *P = parseTemplateParamDecl();
5552 if (!P)
5553 return nullptr;
5554 Names.push_back(P);
5555 }
5556 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5557 return make<TemplateTemplateParamDecl>(Name, Params);
5558 }
5559
5560 if (consumeIf("Tp")) {
5561 Node *P = parseTemplateParamDecl();
5562 if (!P)
5563 return nullptr;
5564 return make<TemplateParamPackDecl>(P);
5565 }
5566
5567 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005568}
5569
5570// <template-arg> ::= <type> # type or template
5571// ::= X <expression> E # expression
5572// ::= <expr-primary> # simple expressions
5573// ::= J <template-arg>* E # argument pack
5574// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005575template <typename Derived, typename Alloc>
5576Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005577 switch (look()) {
5578 case 'X': {
5579 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005580 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005581 if (Arg == nullptr || !consumeIf('E'))
5582 return nullptr;
5583 return Arg;
5584 }
5585 case 'J': {
5586 ++First;
5587 size_t ArgsBegin = Names.size();
5588 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005589 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005590 if (Arg == nullptr)
5591 return nullptr;
5592 Names.push_back(Arg);
5593 }
5594 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5595 return make<TemplateArgumentPack>(Args);
5596 }
5597 case 'L': {
5598 // ::= LZ <encoding> E # extension
5599 if (look(1) == 'Z') {
5600 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005601 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005602 if (Arg == nullptr || !consumeIf('E'))
5603 return nullptr;
5604 return Arg;
5605 }
5606 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005607 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005608 }
5609 default:
Pavel Labathba825192018-10-16 14:29:14 +00005610 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005611 }
5612}
5613
5614// <template-args> ::= I <template-arg>* E
5615// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005616template <typename Derived, typename Alloc>
5617Node *
5618AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005619 if (!consumeIf('I'))
5620 return nullptr;
5621
5622 // <template-params> refer to the innermost <template-args>. Clear out any
5623 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005624 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005625 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005626 TemplateParams.push_back(&OuterTemplateParams);
5627 OuterTemplateParams.clear();
5628 }
Richard Smithc20d1442018-08-20 20:14:49 +00005629
5630 size_t ArgsBegin = Names.size();
5631 while (!consumeIf('E')) {
5632 if (TagTemplates) {
5633 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005634 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005635 TemplateParams = std::move(OldParams);
5636 if (Arg == nullptr)
5637 return nullptr;
5638 Names.push_back(Arg);
5639 Node *TableEntry = Arg;
5640 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5641 TableEntry = make<ParameterPack>(
5642 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005643 if (!TableEntry)
5644 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005645 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005646 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005647 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005648 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005649 if (Arg == nullptr)
5650 return nullptr;
5651 Names.push_back(Arg);
5652 }
5653 }
5654 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5655}
5656
5657// <mangled-name> ::= _Z <encoding>
5658// ::= <type>
5659// extension ::= ___Z <encoding> _block_invoke
5660// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5661// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005662template <typename Derived, typename Alloc>
5663Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005664 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005665 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005666 if (Encoding == nullptr)
5667 return nullptr;
5668 if (look() == '.') {
5669 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5670 First = Last;
5671 }
5672 if (numLeft() != 0)
5673 return nullptr;
5674 return Encoding;
5675 }
5676
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005677 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005678 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005679 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5680 return nullptr;
5681 bool RequireNumber = consumeIf('_');
5682 if (parseNumber().empty() && RequireNumber)
5683 return nullptr;
5684 if (look() == '.')
5685 First = Last;
5686 if (numLeft() != 0)
5687 return nullptr;
5688 return make<SpecialName>("invocation function for block in ", Encoding);
5689 }
5690
Pavel Labathba825192018-10-16 14:29:14 +00005691 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005692 if (numLeft() != 0)
5693 return nullptr;
5694 return Ty;
5695}
5696
Pavel Labathba825192018-10-16 14:29:14 +00005697template <typename Alloc>
5698struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5699 using AbstractManglingParser<ManglingParser<Alloc>,
5700 Alloc>::AbstractManglingParser;
5701};
5702
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005703DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005704
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005705#endif // DEMANGLE_ITANIUMDEMANGLE_H