blob: 6bfc02d1537966b5d94695dfc0c434a64b9fb5fb [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) \
Erik Pilkingtone8457c62019-06-18 23:34:09 +000099 X(UUIDOfExpr) \
Richard Smithc20d1442018-08-20 20:14:49 +0000100 X(BoolExpr) \
Richard Smithdf1c14c2019-09-06 23:53:21 +0000101 X(StringLiteral) \
102 X(LambdaExpr) \
Erik Pilkington0a170f12020-05-13 14:13:37 -0400103 X(EnumLiteral) \
Richard Smithc20d1442018-08-20 20:14:49 +0000104 X(IntegerLiteral) \
105 X(FloatLiteral) \
106 X(DoubleLiteral) \
107 X(LongDoubleLiteral) \
108 X(BracedExpr) \
109 X(BracedRangeExpr)
110
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000111DEMANGLE_NAMESPACE_BEGIN
112
Richard Smithc20d1442018-08-20 20:14:49 +0000113// Base class of all AST nodes. The AST is built by the parser, then is
114// traversed by the printLeft/Right functions to produce a demangled string.
115class Node {
116public:
117 enum Kind : unsigned char {
118#define ENUMERATOR(NodeKind) K ## NodeKind,
119 FOR_EACH_NODE_KIND(ENUMERATOR)
120#undef ENUMERATOR
121 };
122
123 /// Three-way bool to track a cached value. Unknown is possible if this node
124 /// has an unexpanded parameter pack below it that may affect this cache.
125 enum class Cache : unsigned char { Yes, No, Unknown, };
126
127private:
128 Kind K;
129
130 // FIXME: Make these protected.
131public:
132 /// Tracks if this node has a component on its right side, in which case we
133 /// need to call printRight.
134 Cache RHSComponentCache;
135
136 /// Track if this node is a (possibly qualified) array type. This can affect
137 /// how we format the output string.
138 Cache ArrayCache;
139
140 /// Track if this node is a (possibly qualified) function type. This can
141 /// affect how we format the output string.
142 Cache FunctionCache;
143
144public:
145 Node(Kind K_, Cache RHSComponentCache_ = Cache::No,
146 Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No)
147 : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),
148 FunctionCache(FunctionCache_) {}
149
150 /// Visit the most-derived object corresponding to this object.
151 template<typename Fn> void visit(Fn F) const;
152
153 // The following function is provided by all derived classes:
154 //
155 // Call F with arguments that, when passed to the constructor of this node,
156 // would construct an equivalent node.
157 //template<typename Fn> void match(Fn F) const;
158
159 bool hasRHSComponent(OutputStream &S) const {
160 if (RHSComponentCache != Cache::Unknown)
161 return RHSComponentCache == Cache::Yes;
162 return hasRHSComponentSlow(S);
163 }
164
165 bool hasArray(OutputStream &S) const {
166 if (ArrayCache != Cache::Unknown)
167 return ArrayCache == Cache::Yes;
168 return hasArraySlow(S);
169 }
170
171 bool hasFunction(OutputStream &S) const {
172 if (FunctionCache != Cache::Unknown)
173 return FunctionCache == Cache::Yes;
174 return hasFunctionSlow(S);
175 }
176
177 Kind getKind() const { return K; }
178
179 virtual bool hasRHSComponentSlow(OutputStream &) const { return false; }
180 virtual bool hasArraySlow(OutputStream &) const { return false; }
181 virtual bool hasFunctionSlow(OutputStream &) const { return false; }
182
183 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
184 // get at a node that actually represents some concrete syntax.
185 virtual const Node *getSyntaxNode(OutputStream &) const {
186 return this;
187 }
188
189 void print(OutputStream &S) const {
190 printLeft(S);
191 if (RHSComponentCache != Cache::No)
192 printRight(S);
193 }
194
195 // Print the "left" side of this Node into OutputStream.
196 virtual void printLeft(OutputStream &) const = 0;
197
198 // Print the "right". This distinction is necessary to represent C++ types
199 // that appear on the RHS of their subtype, such as arrays or functions.
200 // Since most types don't have such a component, provide a default
201 // implementation.
202 virtual void printRight(OutputStream &) const {}
203
204 virtual StringView getBaseName() const { return StringView(); }
205
206 // Silence compiler warnings, this dtor will never be called.
207 virtual ~Node() = default;
208
209#ifndef NDEBUG
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000210 DEMANGLE_DUMP_METHOD void dump() const;
Richard Smithc20d1442018-08-20 20:14:49 +0000211#endif
212};
213
214class NodeArray {
215 Node **Elements;
216 size_t NumElements;
217
218public:
219 NodeArray() : Elements(nullptr), NumElements(0) {}
220 NodeArray(Node **Elements_, size_t NumElements_)
221 : Elements(Elements_), NumElements(NumElements_) {}
222
223 bool empty() const { return NumElements == 0; }
224 size_t size() const { return NumElements; }
225
226 Node **begin() const { return Elements; }
227 Node **end() const { return Elements + NumElements; }
228
229 Node *operator[](size_t Idx) const { return Elements[Idx]; }
230
231 void printWithComma(OutputStream &S) const {
232 bool FirstElement = true;
233 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
234 size_t BeforeComma = S.getCurrentPosition();
235 if (!FirstElement)
236 S += ", ";
237 size_t AfterComma = S.getCurrentPosition();
238 Elements[Idx]->print(S);
239
240 // Elements[Idx] is an empty parameter pack expansion, we should erase the
241 // comma we just printed.
242 if (AfterComma == S.getCurrentPosition()) {
243 S.setCurrentPosition(BeforeComma);
244 continue;
245 }
246
247 FirstElement = false;
248 }
249 }
250};
251
252struct NodeArrayNode : Node {
253 NodeArray Array;
254 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
255
256 template<typename Fn> void match(Fn F) const { F(Array); }
257
258 void printLeft(OutputStream &S) const override {
259 Array.printWithComma(S);
260 }
261};
262
263class DotSuffix final : public Node {
264 const Node *Prefix;
265 const StringView Suffix;
266
267public:
268 DotSuffix(const Node *Prefix_, StringView Suffix_)
269 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
270
271 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
272
273 void printLeft(OutputStream &s) const override {
274 Prefix->print(s);
275 s += " (";
276 s += Suffix;
277 s += ")";
278 }
279};
280
281class VendorExtQualType final : public Node {
282 const Node *Ty;
283 StringView Ext;
284
285public:
286 VendorExtQualType(const Node *Ty_, StringView Ext_)
287 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {}
288
289 template<typename Fn> void match(Fn F) const { F(Ty, Ext); }
290
291 void printLeft(OutputStream &S) const override {
292 Ty->print(S);
293 S += " ";
294 S += Ext;
295 }
296};
297
298enum FunctionRefQual : unsigned char {
299 FrefQualNone,
300 FrefQualLValue,
301 FrefQualRValue,
302};
303
304enum Qualifiers {
305 QualNone = 0,
306 QualConst = 0x1,
307 QualVolatile = 0x2,
308 QualRestrict = 0x4,
309};
310
311inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
312 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
313}
314
Richard Smithdf1c14c2019-09-06 23:53:21 +0000315class QualType final : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +0000316protected:
317 const Qualifiers Quals;
318 const Node *Child;
319
320 void printQuals(OutputStream &S) const {
321 if (Quals & QualConst)
322 S += " const";
323 if (Quals & QualVolatile)
324 S += " volatile";
325 if (Quals & QualRestrict)
326 S += " restrict";
327 }
328
329public:
330 QualType(const Node *Child_, Qualifiers Quals_)
331 : Node(KQualType, Child_->RHSComponentCache,
332 Child_->ArrayCache, Child_->FunctionCache),
333 Quals(Quals_), Child(Child_) {}
334
335 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
336
337 bool hasRHSComponentSlow(OutputStream &S) const override {
338 return Child->hasRHSComponent(S);
339 }
340 bool hasArraySlow(OutputStream &S) const override {
341 return Child->hasArray(S);
342 }
343 bool hasFunctionSlow(OutputStream &S) const override {
344 return Child->hasFunction(S);
345 }
346
347 void printLeft(OutputStream &S) const override {
348 Child->printLeft(S);
349 printQuals(S);
350 }
351
352 void printRight(OutputStream &S) const override { Child->printRight(S); }
353};
354
355class ConversionOperatorType final : public Node {
356 const Node *Ty;
357
358public:
359 ConversionOperatorType(const Node *Ty_)
360 : Node(KConversionOperatorType), Ty(Ty_) {}
361
362 template<typename Fn> void match(Fn F) const { F(Ty); }
363
364 void printLeft(OutputStream &S) const override {
365 S += "operator ";
366 Ty->print(S);
367 }
368};
369
370class PostfixQualifiedType final : public Node {
371 const Node *Ty;
372 const StringView Postfix;
373
374public:
375 PostfixQualifiedType(Node *Ty_, StringView Postfix_)
376 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
377
378 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
379
380 void printLeft(OutputStream &s) const override {
381 Ty->printLeft(s);
382 s += Postfix;
383 }
384};
385
386class NameType final : public Node {
387 const StringView Name;
388
389public:
390 NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
391
392 template<typename Fn> void match(Fn F) const { F(Name); }
393
394 StringView getName() const { return Name; }
395 StringView getBaseName() const override { return Name; }
396
397 void printLeft(OutputStream &s) const override { s += Name; }
398};
399
400class ElaboratedTypeSpefType : public Node {
401 StringView Kind;
402 Node *Child;
403public:
404 ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
405 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
406
407 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
408
409 void printLeft(OutputStream &S) const override {
410 S += Kind;
411 S += ' ';
412 Child->print(S);
413 }
414};
415
416struct AbiTagAttr : Node {
417 Node *Base;
418 StringView Tag;
419
420 AbiTagAttr(Node* Base_, StringView Tag_)
421 : Node(KAbiTagAttr, Base_->RHSComponentCache,
422 Base_->ArrayCache, Base_->FunctionCache),
423 Base(Base_), Tag(Tag_) {}
424
425 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
426
427 void printLeft(OutputStream &S) const override {
428 Base->printLeft(S);
429 S += "[abi:";
430 S += Tag;
431 S += "]";
432 }
433};
434
435class EnableIfAttr : public Node {
436 NodeArray Conditions;
437public:
438 EnableIfAttr(NodeArray Conditions_)
439 : Node(KEnableIfAttr), Conditions(Conditions_) {}
440
441 template<typename Fn> void match(Fn F) const { F(Conditions); }
442
443 void printLeft(OutputStream &S) const override {
444 S += " [enable_if:";
445 Conditions.printWithComma(S);
446 S += ']';
447 }
448};
449
450class ObjCProtoName : public Node {
451 const Node *Ty;
452 StringView Protocol;
453
454 friend class PointerType;
455
456public:
457 ObjCProtoName(const Node *Ty_, StringView Protocol_)
458 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
459
460 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
461
462 bool isObjCObject() const {
463 return Ty->getKind() == KNameType &&
464 static_cast<const NameType *>(Ty)->getName() == "objc_object";
465 }
466
467 void printLeft(OutputStream &S) const override {
468 Ty->print(S);
469 S += "<";
470 S += Protocol;
471 S += ">";
472 }
473};
474
475class PointerType final : public Node {
476 const Node *Pointee;
477
478public:
479 PointerType(const Node *Pointee_)
480 : Node(KPointerType, Pointee_->RHSComponentCache),
481 Pointee(Pointee_) {}
482
483 template<typename Fn> void match(Fn F) const { F(Pointee); }
484
485 bool hasRHSComponentSlow(OutputStream &S) const override {
486 return Pointee->hasRHSComponent(S);
487 }
488
489 void printLeft(OutputStream &s) const override {
490 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
491 if (Pointee->getKind() != KObjCProtoName ||
492 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
493 Pointee->printLeft(s);
494 if (Pointee->hasArray(s))
495 s += " ";
496 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
497 s += "(";
498 s += "*";
499 } else {
500 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
501 s += "id<";
502 s += objcProto->Protocol;
503 s += ">";
504 }
505 }
506
507 void printRight(OutputStream &s) const override {
508 if (Pointee->getKind() != KObjCProtoName ||
509 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
510 if (Pointee->hasArray(s) || Pointee->hasFunction(s))
511 s += ")";
512 Pointee->printRight(s);
513 }
514 }
515};
516
517enum class ReferenceKind {
518 LValue,
519 RValue,
520};
521
522// Represents either a LValue or an RValue reference type.
523class ReferenceType : public Node {
524 const Node *Pointee;
525 ReferenceKind RK;
526
527 mutable bool Printing = false;
528
529 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
530 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
531 // other combination collapses to a lvalue ref.
532 std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const {
533 auto SoFar = std::make_pair(RK, Pointee);
534 for (;;) {
535 const Node *SN = SoFar.second->getSyntaxNode(S);
536 if (SN->getKind() != KReferenceType)
537 break;
538 auto *RT = static_cast<const ReferenceType *>(SN);
539 SoFar.second = RT->Pointee;
540 SoFar.first = std::min(SoFar.first, RT->RK);
541 }
542 return SoFar;
543 }
544
545public:
546 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
547 : Node(KReferenceType, Pointee_->RHSComponentCache),
548 Pointee(Pointee_), RK(RK_) {}
549
550 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
551
552 bool hasRHSComponentSlow(OutputStream &S) const override {
553 return Pointee->hasRHSComponent(S);
554 }
555
556 void printLeft(OutputStream &s) const override {
557 if (Printing)
558 return;
559 SwapAndRestore<bool> SavePrinting(Printing, true);
560 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
561 Collapsed.second->printLeft(s);
562 if (Collapsed.second->hasArray(s))
563 s += " ";
564 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
565 s += "(";
566
567 s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
568 }
569 void printRight(OutputStream &s) const override {
570 if (Printing)
571 return;
572 SwapAndRestore<bool> SavePrinting(Printing, true);
573 std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);
574 if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))
575 s += ")";
576 Collapsed.second->printRight(s);
577 }
578};
579
580class PointerToMemberType final : public Node {
581 const Node *ClassType;
582 const Node *MemberType;
583
584public:
585 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
586 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
587 ClassType(ClassType_), MemberType(MemberType_) {}
588
589 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
590
591 bool hasRHSComponentSlow(OutputStream &S) const override {
592 return MemberType->hasRHSComponent(S);
593 }
594
595 void printLeft(OutputStream &s) const override {
596 MemberType->printLeft(s);
597 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
598 s += "(";
599 else
600 s += " ";
601 ClassType->print(s);
602 s += "::*";
603 }
604
605 void printRight(OutputStream &s) const override {
606 if (MemberType->hasArray(s) || MemberType->hasFunction(s))
607 s += ")";
608 MemberType->printRight(s);
609 }
610};
611
Richard Smithc20d1442018-08-20 20:14:49 +0000612class ArrayType final : public Node {
613 const Node *Base;
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800614 Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000615
616public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800617 ArrayType(const Node *Base_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000618 : Node(KArrayType,
619 /*RHSComponentCache=*/Cache::Yes,
620 /*ArrayCache=*/Cache::Yes),
621 Base(Base_), Dimension(Dimension_) {}
622
623 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
624
625 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
626 bool hasArraySlow(OutputStream &) const override { return true; }
627
628 void printLeft(OutputStream &S) const override { Base->printLeft(S); }
629
630 void printRight(OutputStream &S) const override {
631 if (S.back() != ']')
632 S += " ";
633 S += "[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800634 if (Dimension)
635 Dimension->print(S);
Richard Smithc20d1442018-08-20 20:14:49 +0000636 S += "]";
637 Base->printRight(S);
638 }
639};
640
641class FunctionType final : public Node {
642 const Node *Ret;
643 NodeArray Params;
644 Qualifiers CVQuals;
645 FunctionRefQual RefQual;
646 const Node *ExceptionSpec;
647
648public:
649 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
650 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
651 : Node(KFunctionType,
652 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
653 /*FunctionCache=*/Cache::Yes),
654 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
655 ExceptionSpec(ExceptionSpec_) {}
656
657 template<typename Fn> void match(Fn F) const {
658 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
659 }
660
661 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
662 bool hasFunctionSlow(OutputStream &) const override { return true; }
663
664 // Handle C++'s ... quirky decl grammar by using the left & right
665 // distinction. Consider:
666 // int (*f(float))(char) {}
667 // f is a function that takes a float and returns a pointer to a function
668 // that takes a char and returns an int. If we're trying to print f, start
669 // by printing out the return types's left, then print our parameters, then
670 // finally print right of the return type.
671 void printLeft(OutputStream &S) const override {
672 Ret->printLeft(S);
673 S += " ";
674 }
675
676 void printRight(OutputStream &S) const override {
677 S += "(";
678 Params.printWithComma(S);
679 S += ")";
680 Ret->printRight(S);
681
682 if (CVQuals & QualConst)
683 S += " const";
684 if (CVQuals & QualVolatile)
685 S += " volatile";
686 if (CVQuals & QualRestrict)
687 S += " restrict";
688
689 if (RefQual == FrefQualLValue)
690 S += " &";
691 else if (RefQual == FrefQualRValue)
692 S += " &&";
693
694 if (ExceptionSpec != nullptr) {
695 S += ' ';
696 ExceptionSpec->print(S);
697 }
698 }
699};
700
701class NoexceptSpec : public Node {
702 const Node *E;
703public:
704 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
705
706 template<typename Fn> void match(Fn F) const { F(E); }
707
708 void printLeft(OutputStream &S) const override {
709 S += "noexcept(";
710 E->print(S);
711 S += ")";
712 }
713};
714
715class DynamicExceptionSpec : public Node {
716 NodeArray Types;
717public:
718 DynamicExceptionSpec(NodeArray Types_)
719 : Node(KDynamicExceptionSpec), Types(Types_) {}
720
721 template<typename Fn> void match(Fn F) const { F(Types); }
722
723 void printLeft(OutputStream &S) const override {
724 S += "throw(";
725 Types.printWithComma(S);
726 S += ')';
727 }
728};
729
730class FunctionEncoding final : public Node {
731 const Node *Ret;
732 const Node *Name;
733 NodeArray Params;
734 const Node *Attrs;
735 Qualifiers CVQuals;
736 FunctionRefQual RefQual;
737
738public:
739 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
740 const Node *Attrs_, Qualifiers CVQuals_,
741 FunctionRefQual RefQual_)
742 : Node(KFunctionEncoding,
743 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
744 /*FunctionCache=*/Cache::Yes),
745 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
746 CVQuals(CVQuals_), RefQual(RefQual_) {}
747
748 template<typename Fn> void match(Fn F) const {
749 F(Ret, Name, Params, Attrs, CVQuals, RefQual);
750 }
751
752 Qualifiers getCVQuals() const { return CVQuals; }
753 FunctionRefQual getRefQual() const { return RefQual; }
754 NodeArray getParams() const { return Params; }
755 const Node *getReturnType() const { return Ret; }
756
757 bool hasRHSComponentSlow(OutputStream &) const override { return true; }
758 bool hasFunctionSlow(OutputStream &) const override { return true; }
759
760 const Node *getName() const { return Name; }
761
762 void printLeft(OutputStream &S) const override {
763 if (Ret) {
764 Ret->printLeft(S);
765 if (!Ret->hasRHSComponent(S))
766 S += " ";
767 }
768 Name->print(S);
769 }
770
771 void printRight(OutputStream &S) const override {
772 S += "(";
773 Params.printWithComma(S);
774 S += ")";
775 if (Ret)
776 Ret->printRight(S);
777
778 if (CVQuals & QualConst)
779 S += " const";
780 if (CVQuals & QualVolatile)
781 S += " volatile";
782 if (CVQuals & QualRestrict)
783 S += " restrict";
784
785 if (RefQual == FrefQualLValue)
786 S += " &";
787 else if (RefQual == FrefQualRValue)
788 S += " &&";
789
790 if (Attrs != nullptr)
791 Attrs->print(S);
792 }
793};
794
795class LiteralOperator : public Node {
796 const Node *OpName;
797
798public:
799 LiteralOperator(const Node *OpName_)
800 : Node(KLiteralOperator), OpName(OpName_) {}
801
802 template<typename Fn> void match(Fn F) const { F(OpName); }
803
804 void printLeft(OutputStream &S) const override {
805 S += "operator\"\" ";
806 OpName->print(S);
807 }
808};
809
810class SpecialName final : public Node {
811 const StringView Special;
812 const Node *Child;
813
814public:
815 SpecialName(StringView Special_, const Node *Child_)
816 : Node(KSpecialName), Special(Special_), Child(Child_) {}
817
818 template<typename Fn> void match(Fn F) const { F(Special, Child); }
819
820 void printLeft(OutputStream &S) const override {
821 S += Special;
822 Child->print(S);
823 }
824};
825
826class CtorVtableSpecialName final : public Node {
827 const Node *FirstType;
828 const Node *SecondType;
829
830public:
831 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
832 : Node(KCtorVtableSpecialName),
833 FirstType(FirstType_), SecondType(SecondType_) {}
834
835 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
836
837 void printLeft(OutputStream &S) const override {
838 S += "construction vtable for ";
839 FirstType->print(S);
840 S += "-in-";
841 SecondType->print(S);
842 }
843};
844
845struct NestedName : Node {
846 Node *Qual;
847 Node *Name;
848
849 NestedName(Node *Qual_, Node *Name_)
850 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
851
852 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
853
854 StringView getBaseName() const override { return Name->getBaseName(); }
855
856 void printLeft(OutputStream &S) const override {
857 Qual->print(S);
858 S += "::";
859 Name->print(S);
860 }
861};
862
863struct LocalName : Node {
864 Node *Encoding;
865 Node *Entity;
866
867 LocalName(Node *Encoding_, Node *Entity_)
868 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
869
870 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
871
872 void printLeft(OutputStream &S) const override {
873 Encoding->print(S);
874 S += "::";
875 Entity->print(S);
876 }
877};
878
879class QualifiedName final : public Node {
880 // qualifier::name
881 const Node *Qualifier;
882 const Node *Name;
883
884public:
885 QualifiedName(const Node *Qualifier_, const Node *Name_)
886 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
887
888 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
889
890 StringView getBaseName() const override { return Name->getBaseName(); }
891
892 void printLeft(OutputStream &S) const override {
893 Qualifier->print(S);
894 S += "::";
895 Name->print(S);
896 }
897};
898
899class VectorType final : public Node {
900 const Node *BaseType;
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800901 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000902
903public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800904 VectorType(const Node *BaseType_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000905 : Node(KVectorType), BaseType(BaseType_),
906 Dimension(Dimension_) {}
907
908 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
909
910 void printLeft(OutputStream &S) const override {
911 BaseType->print(S);
912 S += " vector[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800913 if (Dimension)
914 Dimension->print(S);
Richard Smithc20d1442018-08-20 20:14:49 +0000915 S += "]";
916 }
917};
918
919class PixelVectorType final : public Node {
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800920 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000921
922public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800923 PixelVectorType(const Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000924 : Node(KPixelVectorType), Dimension(Dimension_) {}
925
926 template<typename Fn> void match(Fn F) const { F(Dimension); }
927
928 void printLeft(OutputStream &S) const override {
929 // FIXME: This should demangle as "vector pixel".
930 S += "pixel vector[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800931 Dimension->print(S);
Richard Smithc20d1442018-08-20 20:14:49 +0000932 S += "]";
933 }
934};
935
Richard Smithdf1c14c2019-09-06 23:53:21 +0000936enum class TemplateParamKind { Type, NonType, Template };
937
938/// An invented name for a template parameter for which we don't have a
939/// corresponding template argument.
940///
941/// This node is created when parsing the <lambda-sig> for a lambda with
942/// explicit template arguments, which might be referenced in the parameter
943/// types appearing later in the <lambda-sig>.
944class SyntheticTemplateParamName final : public Node {
945 TemplateParamKind Kind;
946 unsigned Index;
947
948public:
949 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
950 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
951
952 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
953
954 void printLeft(OutputStream &S) const override {
955 switch (Kind) {
956 case TemplateParamKind::Type:
957 S += "$T";
958 break;
959 case TemplateParamKind::NonType:
960 S += "$N";
961 break;
962 case TemplateParamKind::Template:
963 S += "$TT";
964 break;
965 }
966 if (Index > 0)
967 S << Index - 1;
968 }
969};
970
971/// A template type parameter declaration, 'typename T'.
972class TypeTemplateParamDecl final : public Node {
973 Node *Name;
974
975public:
976 TypeTemplateParamDecl(Node *Name_)
977 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
978
979 template<typename Fn> void match(Fn F) const { F(Name); }
980
981 void printLeft(OutputStream &S) const override {
982 S += "typename ";
983 }
984
985 void printRight(OutputStream &S) const override {
986 Name->print(S);
987 }
988};
989
990/// A non-type template parameter declaration, 'int N'.
991class NonTypeTemplateParamDecl final : public Node {
992 Node *Name;
993 Node *Type;
994
995public:
996 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
997 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
998
999 template<typename Fn> void match(Fn F) const { F(Name, Type); }
1000
1001 void printLeft(OutputStream &S) const override {
1002 Type->printLeft(S);
1003 if (!Type->hasRHSComponent(S))
1004 S += " ";
1005 }
1006
1007 void printRight(OutputStream &S) const override {
1008 Name->print(S);
1009 Type->printRight(S);
1010 }
1011};
1012
1013/// A template template parameter declaration,
1014/// 'template<typename T> typename N'.
1015class TemplateTemplateParamDecl final : public Node {
1016 Node *Name;
1017 NodeArray Params;
1018
1019public:
1020 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
1021 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1022 Params(Params_) {}
1023
1024 template<typename Fn> void match(Fn F) const { F(Name, Params); }
1025
1026 void printLeft(OutputStream &S) const override {
1027 S += "template<";
1028 Params.printWithComma(S);
1029 S += "> typename ";
1030 }
1031
1032 void printRight(OutputStream &S) const override {
1033 Name->print(S);
1034 }
1035};
1036
1037/// A template parameter pack declaration, 'typename ...T'.
1038class TemplateParamPackDecl final : public Node {
1039 Node *Param;
1040
1041public:
1042 TemplateParamPackDecl(Node *Param_)
1043 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1044
1045 template<typename Fn> void match(Fn F) const { F(Param); }
1046
1047 void printLeft(OutputStream &S) const override {
1048 Param->printLeft(S);
1049 S += "...";
1050 }
1051
1052 void printRight(OutputStream &S) const override {
1053 Param->printRight(S);
1054 }
1055};
1056
Richard Smithc20d1442018-08-20 20:14:49 +00001057/// An unexpanded parameter pack (either in the expression or type context). If
1058/// this AST is correct, this node will have a ParameterPackExpansion node above
1059/// it.
1060///
1061/// This node is created when some <template-args> are found that apply to an
1062/// <encoding>, and is stored in the TemplateParams table. In order for this to
1063/// appear in the final AST, it has to referenced via a <template-param> (ie,
1064/// T_).
1065class ParameterPack final : public Node {
1066 NodeArray Data;
1067
1068 // Setup OutputStream for a pack expansion unless we're already expanding one.
1069 void initializePackExpansion(OutputStream &S) const {
1070 if (S.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1071 S.CurrentPackMax = static_cast<unsigned>(Data.size());
1072 S.CurrentPackIndex = 0;
1073 }
1074 }
1075
1076public:
1077 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1078 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
1079 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1080 return P->ArrayCache == Cache::No;
1081 }))
1082 ArrayCache = Cache::No;
1083 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1084 return P->FunctionCache == Cache::No;
1085 }))
1086 FunctionCache = Cache::No;
1087 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1088 return P->RHSComponentCache == Cache::No;
1089 }))
1090 RHSComponentCache = Cache::No;
1091 }
1092
1093 template<typename Fn> void match(Fn F) const { F(Data); }
1094
1095 bool hasRHSComponentSlow(OutputStream &S) const override {
1096 initializePackExpansion(S);
1097 size_t Idx = S.CurrentPackIndex;
1098 return Idx < Data.size() && Data[Idx]->hasRHSComponent(S);
1099 }
1100 bool hasArraySlow(OutputStream &S) const override {
1101 initializePackExpansion(S);
1102 size_t Idx = S.CurrentPackIndex;
1103 return Idx < Data.size() && Data[Idx]->hasArray(S);
1104 }
1105 bool hasFunctionSlow(OutputStream &S) const override {
1106 initializePackExpansion(S);
1107 size_t Idx = S.CurrentPackIndex;
1108 return Idx < Data.size() && Data[Idx]->hasFunction(S);
1109 }
1110 const Node *getSyntaxNode(OutputStream &S) const override {
1111 initializePackExpansion(S);
1112 size_t Idx = S.CurrentPackIndex;
1113 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this;
1114 }
1115
1116 void printLeft(OutputStream &S) const override {
1117 initializePackExpansion(S);
1118 size_t Idx = S.CurrentPackIndex;
1119 if (Idx < Data.size())
1120 Data[Idx]->printLeft(S);
1121 }
1122 void printRight(OutputStream &S) const override {
1123 initializePackExpansion(S);
1124 size_t Idx = S.CurrentPackIndex;
1125 if (Idx < Data.size())
1126 Data[Idx]->printRight(S);
1127 }
1128};
1129
1130/// A variadic template argument. This node represents an occurrence of
1131/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1132/// one of it's Elements is. The parser inserts a ParameterPack into the
1133/// TemplateParams table if the <template-args> this pack belongs to apply to an
1134/// <encoding>.
1135class TemplateArgumentPack final : public Node {
1136 NodeArray Elements;
1137public:
1138 TemplateArgumentPack(NodeArray Elements_)
1139 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1140
1141 template<typename Fn> void match(Fn F) const { F(Elements); }
1142
1143 NodeArray getElements() const { return Elements; }
1144
1145 void printLeft(OutputStream &S) const override {
1146 Elements.printWithComma(S);
1147 }
1148};
1149
1150/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1151/// which each have Child->ParameterPackSize elements.
1152class ParameterPackExpansion final : public Node {
1153 const Node *Child;
1154
1155public:
1156 ParameterPackExpansion(const Node *Child_)
1157 : Node(KParameterPackExpansion), Child(Child_) {}
1158
1159 template<typename Fn> void match(Fn F) const { F(Child); }
1160
1161 const Node *getChild() const { return Child; }
1162
1163 void printLeft(OutputStream &S) const override {
1164 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
1165 SwapAndRestore<unsigned> SavePackIdx(S.CurrentPackIndex, Max);
1166 SwapAndRestore<unsigned> SavePackMax(S.CurrentPackMax, Max);
1167 size_t StreamPos = S.getCurrentPosition();
1168
1169 // Print the first element in the pack. If Child contains a ParameterPack,
1170 // it will set up S.CurrentPackMax and print the first element.
1171 Child->print(S);
1172
1173 // No ParameterPack was found in Child. This can occur if we've found a pack
1174 // expansion on a <function-param>.
1175 if (S.CurrentPackMax == Max) {
1176 S += "...";
1177 return;
1178 }
1179
1180 // We found a ParameterPack, but it has no elements. Erase whatever we may
1181 // of printed.
1182 if (S.CurrentPackMax == 0) {
1183 S.setCurrentPosition(StreamPos);
1184 return;
1185 }
1186
1187 // Else, iterate through the rest of the elements in the pack.
1188 for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) {
1189 S += ", ";
1190 S.CurrentPackIndex = I;
1191 Child->print(S);
1192 }
1193 }
1194};
1195
1196class TemplateArgs final : public Node {
1197 NodeArray Params;
1198
1199public:
1200 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1201
1202 template<typename Fn> void match(Fn F) const { F(Params); }
1203
1204 NodeArray getParams() { return Params; }
1205
1206 void printLeft(OutputStream &S) const override {
1207 S += "<";
1208 Params.printWithComma(S);
1209 if (S.back() == '>')
1210 S += " ";
1211 S += ">";
1212 }
1213};
1214
Richard Smithb485b352018-08-24 23:30:26 +00001215/// A forward-reference to a template argument that was not known at the point
1216/// where the template parameter name was parsed in a mangling.
1217///
1218/// This is created when demangling the name of a specialization of a
1219/// conversion function template:
1220///
1221/// \code
1222/// struct A {
1223/// template<typename T> operator T*();
1224/// };
1225/// \endcode
1226///
1227/// When demangling a specialization of the conversion function template, we
1228/// encounter the name of the template (including the \c T) before we reach
1229/// the template argument list, so we cannot substitute the parameter name
1230/// for the corresponding argument while parsing. Instead, we create a
1231/// \c ForwardTemplateReference node that is resolved after we parse the
1232/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001233struct ForwardTemplateReference : Node {
1234 size_t Index;
1235 Node *Ref = nullptr;
1236
1237 // If we're currently printing this node. It is possible (though invalid) for
1238 // a forward template reference to refer to itself via a substitution. This
1239 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1240 // out if more than one print* function is active.
1241 mutable bool Printing = false;
1242
1243 ForwardTemplateReference(size_t Index_)
1244 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1245 Cache::Unknown),
1246 Index(Index_) {}
1247
1248 // We don't provide a matcher for these, because the value of the node is
1249 // not determined by its construction parameters, and it generally needs
1250 // special handling.
1251 template<typename Fn> void match(Fn F) const = delete;
1252
1253 bool hasRHSComponentSlow(OutputStream &S) const override {
1254 if (Printing)
1255 return false;
1256 SwapAndRestore<bool> SavePrinting(Printing, true);
1257 return Ref->hasRHSComponent(S);
1258 }
1259 bool hasArraySlow(OutputStream &S) const override {
1260 if (Printing)
1261 return false;
1262 SwapAndRestore<bool> SavePrinting(Printing, true);
1263 return Ref->hasArray(S);
1264 }
1265 bool hasFunctionSlow(OutputStream &S) const override {
1266 if (Printing)
1267 return false;
1268 SwapAndRestore<bool> SavePrinting(Printing, true);
1269 return Ref->hasFunction(S);
1270 }
1271 const Node *getSyntaxNode(OutputStream &S) const override {
1272 if (Printing)
1273 return this;
1274 SwapAndRestore<bool> SavePrinting(Printing, true);
1275 return Ref->getSyntaxNode(S);
1276 }
1277
1278 void printLeft(OutputStream &S) const override {
1279 if (Printing)
1280 return;
1281 SwapAndRestore<bool> SavePrinting(Printing, true);
1282 Ref->printLeft(S);
1283 }
1284 void printRight(OutputStream &S) const override {
1285 if (Printing)
1286 return;
1287 SwapAndRestore<bool> SavePrinting(Printing, true);
1288 Ref->printRight(S);
1289 }
1290};
1291
1292struct NameWithTemplateArgs : Node {
1293 // name<template_args>
1294 Node *Name;
1295 Node *TemplateArgs;
1296
1297 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1298 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1299
1300 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1301
1302 StringView getBaseName() const override { return Name->getBaseName(); }
1303
1304 void printLeft(OutputStream &S) const override {
1305 Name->print(S);
1306 TemplateArgs->print(S);
1307 }
1308};
1309
1310class GlobalQualifiedName final : public Node {
1311 Node *Child;
1312
1313public:
1314 GlobalQualifiedName(Node* Child_)
1315 : Node(KGlobalQualifiedName), Child(Child_) {}
1316
1317 template<typename Fn> void match(Fn F) const { F(Child); }
1318
1319 StringView getBaseName() const override { return Child->getBaseName(); }
1320
1321 void printLeft(OutputStream &S) const override {
1322 S += "::";
1323 Child->print(S);
1324 }
1325};
1326
1327struct StdQualifiedName : Node {
1328 Node *Child;
1329
1330 StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {}
1331
1332 template<typename Fn> void match(Fn F) const { F(Child); }
1333
1334 StringView getBaseName() const override { return Child->getBaseName(); }
1335
1336 void printLeft(OutputStream &S) const override {
1337 S += "std::";
1338 Child->print(S);
1339 }
1340};
1341
1342enum class SpecialSubKind {
1343 allocator,
1344 basic_string,
1345 string,
1346 istream,
1347 ostream,
1348 iostream,
1349};
1350
1351class ExpandedSpecialSubstitution final : public Node {
1352 SpecialSubKind SSK;
1353
1354public:
1355 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1356 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1357
1358 template<typename Fn> void match(Fn F) const { F(SSK); }
1359
1360 StringView getBaseName() const override {
1361 switch (SSK) {
1362 case SpecialSubKind::allocator:
1363 return StringView("allocator");
1364 case SpecialSubKind::basic_string:
1365 return StringView("basic_string");
1366 case SpecialSubKind::string:
1367 return StringView("basic_string");
1368 case SpecialSubKind::istream:
1369 return StringView("basic_istream");
1370 case SpecialSubKind::ostream:
1371 return StringView("basic_ostream");
1372 case SpecialSubKind::iostream:
1373 return StringView("basic_iostream");
1374 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001375 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001376 }
1377
1378 void printLeft(OutputStream &S) const override {
1379 switch (SSK) {
1380 case SpecialSubKind::allocator:
Richard Smithb485b352018-08-24 23:30:26 +00001381 S += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001382 break;
1383 case SpecialSubKind::basic_string:
Richard Smithb485b352018-08-24 23:30:26 +00001384 S += "std::basic_string";
1385 break;
Richard Smithc20d1442018-08-20 20:14:49 +00001386 case SpecialSubKind::string:
1387 S += "std::basic_string<char, std::char_traits<char>, "
1388 "std::allocator<char> >";
1389 break;
1390 case SpecialSubKind::istream:
1391 S += "std::basic_istream<char, std::char_traits<char> >";
1392 break;
1393 case SpecialSubKind::ostream:
1394 S += "std::basic_ostream<char, std::char_traits<char> >";
1395 break;
1396 case SpecialSubKind::iostream:
1397 S += "std::basic_iostream<char, std::char_traits<char> >";
1398 break;
1399 }
1400 }
1401};
1402
1403class SpecialSubstitution final : public Node {
1404public:
1405 SpecialSubKind SSK;
1406
1407 SpecialSubstitution(SpecialSubKind SSK_)
1408 : Node(KSpecialSubstitution), SSK(SSK_) {}
1409
1410 template<typename Fn> void match(Fn F) const { F(SSK); }
1411
1412 StringView getBaseName() const override {
1413 switch (SSK) {
1414 case SpecialSubKind::allocator:
1415 return StringView("allocator");
1416 case SpecialSubKind::basic_string:
1417 return StringView("basic_string");
1418 case SpecialSubKind::string:
1419 return StringView("string");
1420 case SpecialSubKind::istream:
1421 return StringView("istream");
1422 case SpecialSubKind::ostream:
1423 return StringView("ostream");
1424 case SpecialSubKind::iostream:
1425 return StringView("iostream");
1426 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001427 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001428 }
1429
1430 void printLeft(OutputStream &S) const override {
1431 switch (SSK) {
1432 case SpecialSubKind::allocator:
1433 S += "std::allocator";
1434 break;
1435 case SpecialSubKind::basic_string:
1436 S += "std::basic_string";
1437 break;
1438 case SpecialSubKind::string:
1439 S += "std::string";
1440 break;
1441 case SpecialSubKind::istream:
1442 S += "std::istream";
1443 break;
1444 case SpecialSubKind::ostream:
1445 S += "std::ostream";
1446 break;
1447 case SpecialSubKind::iostream:
1448 S += "std::iostream";
1449 break;
1450 }
1451 }
1452};
1453
1454class CtorDtorName final : public Node {
1455 const Node *Basename;
1456 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001457 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001458
1459public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001460 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1461 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1462 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001463
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001464 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001465
1466 void printLeft(OutputStream &S) const override {
1467 if (IsDtor)
1468 S += "~";
1469 S += Basename->getBaseName();
1470 }
1471};
1472
1473class DtorName : public Node {
1474 const Node *Base;
1475
1476public:
1477 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1478
1479 template<typename Fn> void match(Fn F) const { F(Base); }
1480
1481 void printLeft(OutputStream &S) const override {
1482 S += "~";
1483 Base->printLeft(S);
1484 }
1485};
1486
1487class UnnamedTypeName : public Node {
1488 const StringView Count;
1489
1490public:
1491 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1492
1493 template<typename Fn> void match(Fn F) const { F(Count); }
1494
1495 void printLeft(OutputStream &S) const override {
1496 S += "'unnamed";
1497 S += Count;
1498 S += "\'";
1499 }
1500};
1501
1502class ClosureTypeName : public Node {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001503 NodeArray TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00001504 NodeArray Params;
1505 StringView Count;
1506
1507public:
Richard Smithdf1c14c2019-09-06 23:53:21 +00001508 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1509 StringView Count_)
1510 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1511 Params(Params_), Count(Count_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001512
Richard Smithdf1c14c2019-09-06 23:53:21 +00001513 template<typename Fn> void match(Fn F) const {
1514 F(TemplateParams, Params, Count);
1515 }
1516
1517 void printDeclarator(OutputStream &S) const {
1518 if (!TemplateParams.empty()) {
1519 S += "<";
1520 TemplateParams.printWithComma(S);
1521 S += ">";
1522 }
1523 S += "(";
1524 Params.printWithComma(S);
1525 S += ")";
1526 }
Richard Smithc20d1442018-08-20 20:14:49 +00001527
1528 void printLeft(OutputStream &S) const override {
1529 S += "\'lambda";
1530 S += Count;
Richard Smithdf1c14c2019-09-06 23:53:21 +00001531 S += "\'";
1532 printDeclarator(S);
Richard Smithc20d1442018-08-20 20:14:49 +00001533 }
1534};
1535
1536class StructuredBindingName : public Node {
1537 NodeArray Bindings;
1538public:
1539 StructuredBindingName(NodeArray Bindings_)
1540 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1541
1542 template<typename Fn> void match(Fn F) const { F(Bindings); }
1543
1544 void printLeft(OutputStream &S) const override {
1545 S += '[';
1546 Bindings.printWithComma(S);
1547 S += ']';
1548 }
1549};
1550
1551// -- Expression Nodes --
1552
1553class BinaryExpr : public Node {
1554 const Node *LHS;
1555 const StringView InfixOperator;
1556 const Node *RHS;
1557
1558public:
1559 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_)
1560 : Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {
1561 }
1562
1563 template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }
1564
1565 void printLeft(OutputStream &S) const override {
1566 // might be a template argument expression, then we need to disambiguate
1567 // with parens.
1568 if (InfixOperator == ">")
1569 S += "(";
1570
1571 S += "(";
1572 LHS->print(S);
1573 S += ") ";
1574 S += InfixOperator;
1575 S += " (";
1576 RHS->print(S);
1577 S += ")";
1578
1579 if (InfixOperator == ">")
1580 S += ")";
1581 }
1582};
1583
1584class ArraySubscriptExpr : public Node {
1585 const Node *Op1;
1586 const Node *Op2;
1587
1588public:
1589 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_)
1590 : Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {}
1591
1592 template<typename Fn> void match(Fn F) const { F(Op1, Op2); }
1593
1594 void printLeft(OutputStream &S) const override {
1595 S += "(";
1596 Op1->print(S);
1597 S += ")[";
1598 Op2->print(S);
1599 S += "]";
1600 }
1601};
1602
1603class PostfixExpr : public Node {
1604 const Node *Child;
1605 const StringView Operator;
1606
1607public:
1608 PostfixExpr(const Node *Child_, StringView Operator_)
1609 : Node(KPostfixExpr), Child(Child_), Operator(Operator_) {}
1610
1611 template<typename Fn> void match(Fn F) const { F(Child, Operator); }
1612
1613 void printLeft(OutputStream &S) const override {
1614 S += "(";
1615 Child->print(S);
1616 S += ")";
1617 S += Operator;
1618 }
1619};
1620
1621class ConditionalExpr : public Node {
1622 const Node *Cond;
1623 const Node *Then;
1624 const Node *Else;
1625
1626public:
1627 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_)
1628 : Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {}
1629
1630 template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }
1631
1632 void printLeft(OutputStream &S) const override {
1633 S += "(";
1634 Cond->print(S);
1635 S += ") ? (";
1636 Then->print(S);
1637 S += ") : (";
1638 Else->print(S);
1639 S += ")";
1640 }
1641};
1642
1643class MemberExpr : public Node {
1644 const Node *LHS;
1645 const StringView Kind;
1646 const Node *RHS;
1647
1648public:
1649 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_)
1650 : Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
1651
1652 template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }
1653
1654 void printLeft(OutputStream &S) const override {
1655 LHS->print(S);
1656 S += Kind;
1657 RHS->print(S);
1658 }
1659};
1660
Richard Smith1865d2f2020-10-22 19:29:36 -07001661class SubobjectExpr : public Node {
1662 const Node *Type;
1663 const Node *SubExpr;
1664 StringView Offset;
1665 NodeArray UnionSelectors;
1666 bool OnePastTheEnd;
1667
1668public:
1669 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1670 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1671 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1672 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1673
1674 template<typename Fn> void match(Fn F) const {
1675 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1676 }
1677
1678 void printLeft(OutputStream &S) const override {
1679 SubExpr->print(S);
1680 S += ".<";
1681 Type->print(S);
1682 S += " at offset ";
1683 if (Offset.empty()) {
1684 S += "0";
1685 } else if (Offset[0] == 'n') {
1686 S += "-";
1687 S += Offset.dropFront();
1688 } else {
1689 S += Offset;
1690 }
1691 S += ">";
1692 }
1693};
1694
Richard Smithc20d1442018-08-20 20:14:49 +00001695class EnclosingExpr : public Node {
1696 const StringView Prefix;
1697 const Node *Infix;
1698 const StringView Postfix;
1699
1700public:
1701 EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_)
1702 : Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_),
1703 Postfix(Postfix_) {}
1704
1705 template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); }
1706
1707 void printLeft(OutputStream &S) const override {
1708 S += Prefix;
1709 Infix->print(S);
1710 S += Postfix;
1711 }
1712};
1713
1714class CastExpr : public Node {
1715 // cast_kind<to>(from)
1716 const StringView CastKind;
1717 const Node *To;
1718 const Node *From;
1719
1720public:
1721 CastExpr(StringView CastKind_, const Node *To_, const Node *From_)
1722 : Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {}
1723
1724 template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }
1725
1726 void printLeft(OutputStream &S) const override {
1727 S += CastKind;
1728 S += "<";
1729 To->printLeft(S);
1730 S += ">(";
1731 From->printLeft(S);
1732 S += ")";
1733 }
1734};
1735
1736class SizeofParamPackExpr : public Node {
1737 const Node *Pack;
1738
1739public:
1740 SizeofParamPackExpr(const Node *Pack_)
1741 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1742
1743 template<typename Fn> void match(Fn F) const { F(Pack); }
1744
1745 void printLeft(OutputStream &S) const override {
1746 S += "sizeof...(";
1747 ParameterPackExpansion PPE(Pack);
1748 PPE.printLeft(S);
1749 S += ")";
1750 }
1751};
1752
1753class CallExpr : public Node {
1754 const Node *Callee;
1755 NodeArray Args;
1756
1757public:
1758 CallExpr(const Node *Callee_, NodeArray Args_)
1759 : Node(KCallExpr), Callee(Callee_), Args(Args_) {}
1760
1761 template<typename Fn> void match(Fn F) const { F(Callee, Args); }
1762
1763 void printLeft(OutputStream &S) const override {
1764 Callee->print(S);
1765 S += "(";
1766 Args.printWithComma(S);
1767 S += ")";
1768 }
1769};
1770
1771class NewExpr : public Node {
1772 // new (expr_list) type(init_list)
1773 NodeArray ExprList;
1774 Node *Type;
1775 NodeArray InitList;
1776 bool IsGlobal; // ::operator new ?
1777 bool IsArray; // new[] ?
1778public:
1779 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
1780 bool IsArray_)
1781 : Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_),
1782 IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1783
1784 template<typename Fn> void match(Fn F) const {
1785 F(ExprList, Type, InitList, IsGlobal, IsArray);
1786 }
1787
1788 void printLeft(OutputStream &S) const override {
1789 if (IsGlobal)
1790 S += "::operator ";
1791 S += "new";
1792 if (IsArray)
1793 S += "[]";
1794 S += ' ';
1795 if (!ExprList.empty()) {
1796 S += "(";
1797 ExprList.printWithComma(S);
1798 S += ")";
1799 }
1800 Type->print(S);
1801 if (!InitList.empty()) {
1802 S += "(";
1803 InitList.printWithComma(S);
1804 S += ")";
1805 }
1806
1807 }
1808};
1809
1810class DeleteExpr : public Node {
1811 Node *Op;
1812 bool IsGlobal;
1813 bool IsArray;
1814
1815public:
1816 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_)
1817 : Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
1818
1819 template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }
1820
1821 void printLeft(OutputStream &S) const override {
1822 if (IsGlobal)
1823 S += "::";
1824 S += "delete";
1825 if (IsArray)
1826 S += "[] ";
1827 Op->print(S);
1828 }
1829};
1830
1831class PrefixExpr : public Node {
1832 StringView Prefix;
1833 Node *Child;
1834
1835public:
1836 PrefixExpr(StringView Prefix_, Node *Child_)
1837 : Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {}
1838
1839 template<typename Fn> void match(Fn F) const { F(Prefix, Child); }
1840
1841 void printLeft(OutputStream &S) const override {
1842 S += Prefix;
1843 S += "(";
1844 Child->print(S);
1845 S += ")";
1846 }
1847};
1848
1849class FunctionParam : public Node {
1850 StringView Number;
1851
1852public:
1853 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
1854
1855 template<typename Fn> void match(Fn F) const { F(Number); }
1856
1857 void printLeft(OutputStream &S) const override {
1858 S += "fp";
1859 S += Number;
1860 }
1861};
1862
1863class ConversionExpr : public Node {
1864 const Node *Type;
1865 NodeArray Expressions;
1866
1867public:
1868 ConversionExpr(const Node *Type_, NodeArray Expressions_)
1869 : Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {}
1870
1871 template<typename Fn> void match(Fn F) const { F(Type, Expressions); }
1872
1873 void printLeft(OutputStream &S) const override {
1874 S += "(";
1875 Type->print(S);
1876 S += ")(";
1877 Expressions.printWithComma(S);
1878 S += ")";
1879 }
1880};
1881
Richard Smith1865d2f2020-10-22 19:29:36 -07001882class PointerToMemberConversionExpr : public Node {
1883 const Node *Type;
1884 const Node *SubExpr;
1885 StringView Offset;
1886
1887public:
1888 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
1889 StringView Offset_)
1890 : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_),
1891 Offset(Offset_) {}
1892
1893 template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }
1894
1895 void printLeft(OutputStream &S) const override {
1896 S += "(";
1897 Type->print(S);
1898 S += ")(";
1899 SubExpr->print(S);
1900 S += ")";
1901 }
1902};
1903
Richard Smithc20d1442018-08-20 20:14:49 +00001904class InitListExpr : public Node {
1905 const Node *Ty;
1906 NodeArray Inits;
1907public:
1908 InitListExpr(const Node *Ty_, NodeArray Inits_)
1909 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
1910
1911 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
1912
1913 void printLeft(OutputStream &S) const override {
1914 if (Ty)
1915 Ty->print(S);
1916 S += '{';
1917 Inits.printWithComma(S);
1918 S += '}';
1919 }
1920};
1921
1922class BracedExpr : public Node {
1923 const Node *Elem;
1924 const Node *Init;
1925 bool IsArray;
1926public:
1927 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
1928 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
1929
1930 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
1931
1932 void printLeft(OutputStream &S) const override {
1933 if (IsArray) {
1934 S += '[';
1935 Elem->print(S);
1936 S += ']';
1937 } else {
1938 S += '.';
1939 Elem->print(S);
1940 }
1941 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1942 S += " = ";
1943 Init->print(S);
1944 }
1945};
1946
1947class BracedRangeExpr : public Node {
1948 const Node *First;
1949 const Node *Last;
1950 const Node *Init;
1951public:
1952 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
1953 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
1954
1955 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
1956
1957 void printLeft(OutputStream &S) const override {
1958 S += '[';
1959 First->print(S);
1960 S += " ... ";
1961 Last->print(S);
1962 S += ']';
1963 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
1964 S += " = ";
1965 Init->print(S);
1966 }
1967};
1968
1969class FoldExpr : public Node {
1970 const Node *Pack, *Init;
1971 StringView OperatorName;
1972 bool IsLeftFold;
1973
1974public:
1975 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
1976 const Node *Init_)
1977 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
1978 IsLeftFold(IsLeftFold_) {}
1979
1980 template<typename Fn> void match(Fn F) const {
1981 F(IsLeftFold, OperatorName, Pack, Init);
1982 }
1983
1984 void printLeft(OutputStream &S) const override {
1985 auto PrintPack = [&] {
1986 S += '(';
1987 ParameterPackExpansion(Pack).print(S);
1988 S += ')';
1989 };
1990
1991 S += '(';
1992
1993 if (IsLeftFold) {
1994 // init op ... op pack
1995 if (Init != nullptr) {
1996 Init->print(S);
1997 S += ' ';
1998 S += OperatorName;
1999 S += ' ';
2000 }
2001 // ... op pack
2002 S += "... ";
2003 S += OperatorName;
2004 S += ' ';
2005 PrintPack();
2006 } else { // !IsLeftFold
2007 // pack op ...
2008 PrintPack();
2009 S += ' ';
2010 S += OperatorName;
2011 S += " ...";
2012 // pack op ... op init
2013 if (Init != nullptr) {
2014 S += ' ';
2015 S += OperatorName;
2016 S += ' ';
2017 Init->print(S);
2018 }
2019 }
2020 S += ')';
2021 }
2022};
2023
2024class ThrowExpr : public Node {
2025 const Node *Op;
2026
2027public:
2028 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2029
2030 template<typename Fn> void match(Fn F) const { F(Op); }
2031
2032 void printLeft(OutputStream &S) const override {
2033 S += "throw ";
2034 Op->print(S);
2035 }
2036};
2037
Erik Pilkingtone8457c62019-06-18 23:34:09 +00002038// MSVC __uuidof extension, generated by clang in -fms-extensions mode.
2039class UUIDOfExpr : public Node {
2040 Node *Operand;
2041public:
2042 UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {}
2043
2044 template<typename Fn> void match(Fn F) const { F(Operand); }
2045
2046 void printLeft(OutputStream &S) const override {
2047 S << "__uuidof(";
2048 Operand->print(S);
2049 S << ")";
2050 }
2051};
2052
Richard Smithc20d1442018-08-20 20:14:49 +00002053class BoolExpr : public Node {
2054 bool Value;
2055
2056public:
2057 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2058
2059 template<typename Fn> void match(Fn F) const { F(Value); }
2060
2061 void printLeft(OutputStream &S) const override {
2062 S += Value ? StringView("true") : StringView("false");
2063 }
2064};
2065
Richard Smithdf1c14c2019-09-06 23:53:21 +00002066class StringLiteral : public Node {
2067 const Node *Type;
2068
2069public:
2070 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2071
2072 template<typename Fn> void match(Fn F) const { F(Type); }
2073
2074 void printLeft(OutputStream &S) const override {
2075 S += "\"<";
2076 Type->print(S);
2077 S += ">\"";
2078 }
2079};
2080
2081class LambdaExpr : public Node {
2082 const Node *Type;
2083
Richard Smithdf1c14c2019-09-06 23:53:21 +00002084public:
2085 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2086
2087 template<typename Fn> void match(Fn F) const { F(Type); }
2088
2089 void printLeft(OutputStream &S) const override {
2090 S += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002091 if (Type->getKind() == KClosureTypeName)
2092 static_cast<const ClosureTypeName *>(Type)->printDeclarator(S);
Richard Smithdf1c14c2019-09-06 23:53:21 +00002093 S += "{...}";
2094 }
2095};
2096
Erik Pilkington0a170f12020-05-13 14:13:37 -04002097class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002098 // ty(integer)
2099 const Node *Ty;
2100 StringView Integer;
2101
2102public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002103 EnumLiteral(const Node *Ty_, StringView Integer_)
2104 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002105
2106 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2107
2108 void printLeft(OutputStream &S) const override {
Erik Pilkington0a170f12020-05-13 14:13:37 -04002109 S << "(";
Richard Smithc20d1442018-08-20 20:14:49 +00002110 Ty->print(S);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002111 S << ")";
2112
2113 if (Integer[0] == 'n')
2114 S << "-" << Integer.dropFront(1);
2115 else
2116 S << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002117 }
2118};
2119
2120class IntegerLiteral : public Node {
2121 StringView Type;
2122 StringView Value;
2123
2124public:
2125 IntegerLiteral(StringView Type_, StringView Value_)
2126 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2127
2128 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2129
2130 void printLeft(OutputStream &S) const override {
2131 if (Type.size() > 3) {
2132 S += "(";
2133 S += Type;
2134 S += ")";
2135 }
2136
2137 if (Value[0] == 'n') {
2138 S += "-";
2139 S += Value.dropFront(1);
2140 } else
2141 S += Value;
2142
2143 if (Type.size() <= 3)
2144 S += Type;
2145 }
2146};
2147
2148template <class Float> struct FloatData;
2149
2150namespace float_literal_impl {
2151constexpr Node::Kind getFloatLiteralKind(float *) {
2152 return Node::KFloatLiteral;
2153}
2154constexpr Node::Kind getFloatLiteralKind(double *) {
2155 return Node::KDoubleLiteral;
2156}
2157constexpr Node::Kind getFloatLiteralKind(long double *) {
2158 return Node::KLongDoubleLiteral;
2159}
2160}
2161
2162template <class Float> class FloatLiteralImpl : public Node {
2163 const StringView Contents;
2164
2165 static constexpr Kind KindForClass =
2166 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2167
2168public:
2169 FloatLiteralImpl(StringView Contents_)
2170 : Node(KindForClass), Contents(Contents_) {}
2171
2172 template<typename Fn> void match(Fn F) const { F(Contents); }
2173
2174 void printLeft(OutputStream &s) const override {
2175 const char *first = Contents.begin();
2176 const char *last = Contents.end() + 1;
2177
2178 const size_t N = FloatData<Float>::mangled_size;
2179 if (static_cast<std::size_t>(last - first) > N) {
2180 last = first + N;
2181 union {
2182 Float value;
2183 char buf[sizeof(Float)];
2184 };
2185 const char *t = first;
2186 char *e = buf;
2187 for (; t != last; ++t, ++e) {
2188 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2189 : static_cast<unsigned>(*t - 'a' + 10);
2190 ++t;
2191 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2192 : static_cast<unsigned>(*t - 'a' + 10);
2193 *e = static_cast<char>((d1 << 4) + d0);
2194 }
2195#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2196 std::reverse(buf, e);
2197#endif
2198 char num[FloatData<Float>::max_demangled_size] = {0};
2199 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
2200 s += StringView(num, num + n);
2201 }
2202 }
2203};
2204
2205using FloatLiteral = FloatLiteralImpl<float>;
2206using DoubleLiteral = FloatLiteralImpl<double>;
2207using LongDoubleLiteral = FloatLiteralImpl<long double>;
2208
2209/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2210/// appropriate derived class.
2211template<typename Fn>
2212void Node::visit(Fn F) const {
2213 switch (K) {
2214#define CASE(X) case K ## X: return F(static_cast<const X*>(this));
2215 FOR_EACH_NODE_KIND(CASE)
2216#undef CASE
2217 }
2218 assert(0 && "unknown mangling node kind");
2219}
2220
2221/// Determine the kind of a node from its type.
2222template<typename NodeT> struct NodeKind;
2223#define SPECIALIZATION(X) \
2224 template<> struct NodeKind<X> { \
2225 static constexpr Node::Kind Kind = Node::K##X; \
2226 static constexpr const char *name() { return #X; } \
2227 };
2228FOR_EACH_NODE_KIND(SPECIALIZATION)
2229#undef SPECIALIZATION
2230
2231#undef FOR_EACH_NODE_KIND
2232
2233template <class T, size_t N>
2234class PODSmallVector {
2235 static_assert(std::is_pod<T>::value,
2236 "T is required to be a plain old data type");
2237
Erik Pilkingtond95b7fd2020-01-09 10:24:09 -08002238 T* First = nullptr;
2239 T* Last = nullptr;
2240 T* Cap = nullptr;
2241 T Inline[N] = {0};
Richard Smithc20d1442018-08-20 20:14:49 +00002242
2243 bool isInline() const { return First == Inline; }
2244
2245 void clearInline() {
2246 First = Inline;
2247 Last = Inline;
2248 Cap = Inline + N;
2249 }
2250
2251 void reserve(size_t NewCap) {
2252 size_t S = size();
2253 if (isInline()) {
2254 auto* Tmp = static_cast<T*>(std::malloc(NewCap * sizeof(T)));
2255 if (Tmp == nullptr)
2256 std::terminate();
2257 std::copy(First, Last, Tmp);
2258 First = Tmp;
2259 } else {
2260 First = static_cast<T*>(std::realloc(First, NewCap * sizeof(T)));
2261 if (First == nullptr)
2262 std::terminate();
2263 }
2264 Last = First + S;
2265 Cap = First + NewCap;
2266 }
2267
2268public:
2269 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
2270
2271 PODSmallVector(const PODSmallVector&) = delete;
2272 PODSmallVector& operator=(const PODSmallVector&) = delete;
2273
2274 PODSmallVector(PODSmallVector&& Other) : PODSmallVector() {
2275 if (Other.isInline()) {
2276 std::copy(Other.begin(), Other.end(), First);
2277 Last = First + Other.size();
2278 Other.clear();
2279 return;
2280 }
2281
2282 First = Other.First;
2283 Last = Other.Last;
2284 Cap = Other.Cap;
2285 Other.clearInline();
2286 }
2287
2288 PODSmallVector& operator=(PODSmallVector&& Other) {
2289 if (Other.isInline()) {
2290 if (!isInline()) {
2291 std::free(First);
2292 clearInline();
2293 }
2294 std::copy(Other.begin(), Other.end(), First);
2295 Last = First + Other.size();
2296 Other.clear();
2297 return *this;
2298 }
2299
2300 if (isInline()) {
2301 First = Other.First;
2302 Last = Other.Last;
2303 Cap = Other.Cap;
2304 Other.clearInline();
2305 return *this;
2306 }
2307
2308 std::swap(First, Other.First);
2309 std::swap(Last, Other.Last);
2310 std::swap(Cap, Other.Cap);
2311 Other.clear();
2312 return *this;
2313 }
2314
2315 void push_back(const T& Elem) {
2316 if (Last == Cap)
2317 reserve(size() * 2);
2318 *Last++ = Elem;
2319 }
2320
2321 void pop_back() {
2322 assert(Last != First && "Popping empty vector!");
2323 --Last;
2324 }
2325
2326 void dropBack(size_t Index) {
2327 assert(Index <= size() && "dropBack() can't expand!");
2328 Last = First + Index;
2329 }
2330
2331 T* begin() { return First; }
2332 T* end() { return Last; }
2333
2334 bool empty() const { return First == Last; }
2335 size_t size() const { return static_cast<size_t>(Last - First); }
2336 T& back() {
2337 assert(Last != First && "Calling back() on empty vector!");
2338 return *(Last - 1);
2339 }
2340 T& operator[](size_t Index) {
2341 assert(Index < size() && "Invalid access!");
2342 return *(begin() + Index);
2343 }
2344 void clear() { Last = First; }
2345
2346 ~PODSmallVector() {
2347 if (!isInline())
2348 std::free(First);
2349 }
2350};
2351
Pavel Labathba825192018-10-16 14:29:14 +00002352template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002353 const char *First;
2354 const char *Last;
2355
2356 // Name stack, this is used by the parser to hold temporary names that were
2357 // parsed. The parser collapses multiple names into new nodes to construct
2358 // the AST. Once the parser is finished, names.size() == 1.
2359 PODSmallVector<Node *, 32> Names;
2360
2361 // Substitution table. Itanium supports name substitutions as a means of
2362 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2363 // table.
2364 PODSmallVector<Node *, 32> Subs;
2365
Richard Smithdf1c14c2019-09-06 23:53:21 +00002366 using TemplateParamList = PODSmallVector<Node *, 8>;
2367
2368 class ScopedTemplateParamList {
2369 AbstractManglingParser *Parser;
2370 size_t OldNumTemplateParamLists;
2371 TemplateParamList Params;
2372
2373 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002374 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2375 : Parser(TheParser),
2376 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002377 Parser->TemplateParams.push_back(&Params);
2378 }
2379 ~ScopedTemplateParamList() {
2380 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2381 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2382 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002383 };
2384
Richard Smithc20d1442018-08-20 20:14:49 +00002385 // Template parameter table. Like the above, but referenced like "T42_".
2386 // This has a smaller size compared to Subs and Names because it can be
2387 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002388 TemplateParamList OuterTemplateParams;
2389
2390 // Lists of template parameters indexed by template parameter depth,
2391 // referenced like "TL2_4_". If nonempty, element 0 is always
2392 // OuterTemplateParams; inner elements are always template parameter lists of
2393 // lambda expressions. For a generic lambda with no explicit template
2394 // parameter list, the corresponding parameter list pointer will be null.
2395 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002396
2397 // Set of unresolved forward <template-param> references. These can occur in a
2398 // conversion operator's type, and are resolved in the enclosing <encoding>.
2399 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2400
Richard Smithc20d1442018-08-20 20:14:49 +00002401 bool TryToParseTemplateArgs = true;
2402 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002403 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2404
2405 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002406
2407 Alloc ASTAllocator;
2408
Pavel Labathba825192018-10-16 14:29:14 +00002409 AbstractManglingParser(const char *First_, const char *Last_)
2410 : First(First_), Last(Last_) {}
2411
2412 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002413
2414 void reset(const char *First_, const char *Last_) {
2415 First = First_;
2416 Last = Last_;
2417 Names.clear();
2418 Subs.clear();
2419 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002420 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002421 TryToParseTemplateArgs = true;
2422 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002423 for (int I = 0; I != 3; ++I)
2424 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002425 ASTAllocator.reset();
2426 }
2427
Richard Smithb485b352018-08-24 23:30:26 +00002428 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002429 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2430 }
2431
2432 template <class It> NodeArray makeNodeArray(It begin, It end) {
2433 size_t sz = static_cast<size_t>(end - begin);
2434 void *mem = ASTAllocator.allocateNodeArray(sz);
2435 Node **data = new (mem) Node *[sz];
2436 std::copy(begin, end, data);
2437 return NodeArray(data, sz);
2438 }
2439
2440 NodeArray popTrailingNodeArray(size_t FromPosition) {
2441 assert(FromPosition <= Names.size());
2442 NodeArray res =
2443 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2444 Names.dropBack(FromPosition);
2445 return res;
2446 }
2447
2448 bool consumeIf(StringView S) {
2449 if (StringView(First, Last).startsWith(S)) {
2450 First += S.size();
2451 return true;
2452 }
2453 return false;
2454 }
2455
2456 bool consumeIf(char C) {
2457 if (First != Last && *First == C) {
2458 ++First;
2459 return true;
2460 }
2461 return false;
2462 }
2463
2464 char consume() { return First != Last ? *First++ : '\0'; }
2465
2466 char look(unsigned Lookahead = 0) {
2467 if (static_cast<size_t>(Last - First) <= Lookahead)
2468 return '\0';
2469 return First[Lookahead];
2470 }
2471
2472 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2473
2474 StringView parseNumber(bool AllowNegative = false);
2475 Qualifiers parseCVQualifiers();
2476 bool parsePositiveInteger(size_t *Out);
2477 StringView parseBareSourceName();
2478
2479 bool parseSeqId(size_t *Out);
2480 Node *parseSubstitution();
2481 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002482 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002483 Node *parseTemplateArgs(bool TagTemplates = false);
2484 Node *parseTemplateArg();
2485
2486 /// Parse the <expr> production.
2487 Node *parseExpr();
2488 Node *parsePrefixExpr(StringView Kind);
2489 Node *parseBinaryExpr(StringView Kind);
2490 Node *parseIntegerLiteral(StringView Lit);
2491 Node *parseExprPrimary();
2492 template <class Float> Node *parseFloatingLiteral();
2493 Node *parseFunctionParam();
2494 Node *parseNewExpr();
2495 Node *parseConversionExpr();
2496 Node *parseBracedExpr();
2497 Node *parseFoldExpr();
Richard Smith1865d2f2020-10-22 19:29:36 -07002498 Node *parsePointerToMemberConversionExpr();
2499 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002500
2501 /// Parse the <type> production.
2502 Node *parseType();
2503 Node *parseFunctionType();
2504 Node *parseVectorType();
2505 Node *parseDecltype();
2506 Node *parseArrayType();
2507 Node *parsePointerToMemberType();
2508 Node *parseClassEnumType();
2509 Node *parseQualifiedType();
2510
2511 Node *parseEncoding();
2512 bool parseCallOffset();
2513 Node *parseSpecialName();
2514
2515 /// Holds some extra information about a <name> that is being parsed. This
2516 /// information is only pertinent if the <name> refers to an <encoding>.
2517 struct NameState {
2518 bool CtorDtorConversion = false;
2519 bool EndsWithTemplateArgs = false;
2520 Qualifiers CVQualifiers = QualNone;
2521 FunctionRefQual ReferenceQualifier = FrefQualNone;
2522 size_t ForwardTemplateRefsBegin;
2523
Pavel Labathba825192018-10-16 14:29:14 +00002524 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002525 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2526 };
2527
2528 bool resolveForwardTemplateRefs(NameState &State) {
2529 size_t I = State.ForwardTemplateRefsBegin;
2530 size_t E = ForwardTemplateRefs.size();
2531 for (; I < E; ++I) {
2532 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002533 if (TemplateParams.empty() || !TemplateParams[0] ||
2534 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002535 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002536 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002537 }
2538 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2539 return false;
2540 }
2541
2542 /// Parse the <name> production>
2543 Node *parseName(NameState *State = nullptr);
2544 Node *parseLocalName(NameState *State);
2545 Node *parseOperatorName(NameState *State);
2546 Node *parseUnqualifiedName(NameState *State);
2547 Node *parseUnnamedTypeName(NameState *State);
2548 Node *parseSourceName(NameState *State);
2549 Node *parseUnscopedName(NameState *State);
2550 Node *parseNestedName(NameState *State);
2551 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2552
2553 Node *parseAbiTags(Node *N);
2554
2555 /// Parse the <unresolved-name> production.
2556 Node *parseUnresolvedName();
2557 Node *parseSimpleId();
2558 Node *parseBaseUnresolvedName();
2559 Node *parseUnresolvedType();
2560 Node *parseDestructorName();
2561
2562 /// Top-level entry point into the parser.
2563 Node *parse();
2564};
2565
2566const char* parse_discriminator(const char* first, const char* last);
2567
2568// <name> ::= <nested-name> // N
2569// ::= <local-name> # See Scope Encoding below // Z
2570// ::= <unscoped-template-name> <template-args>
2571// ::= <unscoped-name>
2572//
2573// <unscoped-template-name> ::= <unscoped-name>
2574// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002575template <typename Derived, typename Alloc>
2576Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002577 consumeIf('L'); // extension
2578
2579 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002580 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002581 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002582 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002583
2584 // ::= <unscoped-template-name> <template-args>
2585 if (look() == 'S' && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00002586 Node *S = getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00002587 if (S == nullptr)
2588 return nullptr;
2589 if (look() != 'I')
2590 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002591 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002592 if (TA == nullptr)
2593 return nullptr;
2594 if (State) State->EndsWithTemplateArgs = true;
2595 return make<NameWithTemplateArgs>(S, TA);
2596 }
2597
Pavel Labathba825192018-10-16 14:29:14 +00002598 Node *N = getDerived().parseUnscopedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002599 if (N == nullptr)
2600 return nullptr;
2601 // ::= <unscoped-template-name> <template-args>
2602 if (look() == 'I') {
2603 Subs.push_back(N);
Pavel Labathba825192018-10-16 14:29:14 +00002604 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002605 if (TA == nullptr)
2606 return nullptr;
2607 if (State) State->EndsWithTemplateArgs = true;
2608 return make<NameWithTemplateArgs>(N, TA);
2609 }
2610 // ::= <unscoped-name>
2611 return N;
2612}
2613
2614// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2615// := Z <function encoding> E s [<discriminator>]
2616// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002617template <typename Derived, typename Alloc>
2618Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002619 if (!consumeIf('Z'))
2620 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002621 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002622 if (Encoding == nullptr || !consumeIf('E'))
2623 return nullptr;
2624
2625 if (consumeIf('s')) {
2626 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002627 auto *StringLitName = make<NameType>("string literal");
2628 if (!StringLitName)
2629 return nullptr;
2630 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002631 }
2632
2633 if (consumeIf('d')) {
2634 parseNumber(true);
2635 if (!consumeIf('_'))
2636 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002637 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002638 if (N == nullptr)
2639 return nullptr;
2640 return make<LocalName>(Encoding, N);
2641 }
2642
Pavel Labathba825192018-10-16 14:29:14 +00002643 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002644 if (Entity == nullptr)
2645 return nullptr;
2646 First = parse_discriminator(First, Last);
2647 return make<LocalName>(Encoding, Entity);
2648}
2649
2650// <unscoped-name> ::= <unqualified-name>
2651// ::= St <unqualified-name> # ::std::
2652// extension ::= StL<unqualified-name>
Pavel Labathba825192018-10-16 14:29:14 +00002653template <typename Derived, typename Alloc>
2654Node *
2655AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {
2656 if (consumeIf("StL") || consumeIf("St")) {
2657 Node *R = getDerived().parseUnqualifiedName(State);
2658 if (R == nullptr)
2659 return nullptr;
2660 return make<StdQualifiedName>(R);
2661 }
2662 return getDerived().parseUnqualifiedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002663}
2664
2665// <unqualified-name> ::= <operator-name> [abi-tags]
2666// ::= <ctor-dtor-name>
2667// ::= <source-name>
2668// ::= <unnamed-type-name>
2669// ::= DC <source-name>+ E # structured binding declaration
Pavel Labathba825192018-10-16 14:29:14 +00002670template <typename Derived, typename Alloc>
2671Node *
2672AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002673 // <ctor-dtor-name>s are special-cased in parseNestedName().
2674 Node *Result;
2675 if (look() == 'U')
Pavel Labathba825192018-10-16 14:29:14 +00002676 Result = getDerived().parseUnnamedTypeName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002677 else if (look() >= '1' && look() <= '9')
Pavel Labathba825192018-10-16 14:29:14 +00002678 Result = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002679 else if (consumeIf("DC")) {
2680 size_t BindingsBegin = Names.size();
2681 do {
Pavel Labathba825192018-10-16 14:29:14 +00002682 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002683 if (Binding == nullptr)
2684 return nullptr;
2685 Names.push_back(Binding);
2686 } while (!consumeIf('E'));
2687 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
2688 } else
Pavel Labathba825192018-10-16 14:29:14 +00002689 Result = getDerived().parseOperatorName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002690 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002691 Result = getDerived().parseAbiTags(Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002692 return Result;
2693}
2694
2695// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2696// ::= <closure-type-name>
2697//
2698// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2699//
2700// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002701template <typename Derived, typename Alloc>
2702Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002703AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2704 // <template-params> refer to the innermost <template-args>. Clear out any
2705 // outer args that we may have inserted into TemplateParams.
2706 if (State != nullptr)
2707 TemplateParams.clear();
2708
Richard Smithc20d1442018-08-20 20:14:49 +00002709 if (consumeIf("Ut")) {
2710 StringView Count = parseNumber();
2711 if (!consumeIf('_'))
2712 return nullptr;
2713 return make<UnnamedTypeName>(Count);
2714 }
2715 if (consumeIf("Ul")) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002716 SwapAndRestore<size_t> SwapParams(ParsingLambdaParamsAtLevel,
2717 TemplateParams.size());
2718 ScopedTemplateParamList LambdaTemplateParams(this);
2719
2720 size_t ParamsBegin = Names.size();
2721 while (look() == 'T' &&
2722 StringView("yptn").find(look(1)) != StringView::npos) {
2723 Node *T = parseTemplateParamDecl();
2724 if (!T)
2725 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002726 Names.push_back(T);
2727 }
2728 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2729
2730 // FIXME: If TempParams is empty and none of the function parameters
2731 // includes 'auto', we should remove LambdaTemplateParams from the
2732 // TemplateParams list. Unfortunately, we don't find out whether there are
2733 // any 'auto' parameters until too late in an example such as:
2734 //
2735 // template<typename T> void f(
2736 // decltype([](decltype([]<typename T>(T v) {}),
2737 // auto) {})) {}
2738 // template<typename T> void f(
2739 // decltype([](decltype([]<typename T>(T w) {}),
2740 // int) {})) {}
2741 //
2742 // Here, the type of v is at level 2 but the type of w is at level 1. We
2743 // don't find this out until we encounter the type of the next parameter.
2744 //
2745 // However, compilers can't actually cope with the former example in
2746 // practice, and it's likely to be made ill-formed in future, so we don't
2747 // need to support it here.
2748 //
2749 // If we encounter an 'auto' in the function parameter types, we will
2750 // recreate a template parameter scope for it, but any intervening lambdas
2751 // will be parsed in the 'wrong' template parameter depth.
2752 if (TempParams.empty())
2753 TemplateParams.pop_back();
2754
Richard Smithc20d1442018-08-20 20:14:49 +00002755 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002756 do {
Pavel Labathba825192018-10-16 14:29:14 +00002757 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002758 if (P == nullptr)
2759 return nullptr;
2760 Names.push_back(P);
2761 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002762 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002763 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2764
Richard Smithc20d1442018-08-20 20:14:49 +00002765 StringView Count = parseNumber();
2766 if (!consumeIf('_'))
2767 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002768 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002769 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002770 if (consumeIf("Ub")) {
2771 (void)parseNumber();
2772 if (!consumeIf('_'))
2773 return nullptr;
2774 return make<NameType>("'block-literal'");
2775 }
Richard Smithc20d1442018-08-20 20:14:49 +00002776 return nullptr;
2777}
2778
2779// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002780template <typename Derived, typename Alloc>
2781Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002782 size_t Length = 0;
2783 if (parsePositiveInteger(&Length))
2784 return nullptr;
2785 if (numLeft() < Length || Length == 0)
2786 return nullptr;
2787 StringView Name(First, First + Length);
2788 First += Length;
2789 if (Name.startsWith("_GLOBAL__N"))
2790 return make<NameType>("(anonymous namespace)");
2791 return make<NameType>(Name);
2792}
2793
2794// <operator-name> ::= aa # &&
2795// ::= ad # & (unary)
2796// ::= an # &
2797// ::= aN # &=
2798// ::= aS # =
2799// ::= cl # ()
2800// ::= cm # ,
2801// ::= co # ~
2802// ::= cv <type> # (cast)
2803// ::= da # delete[]
2804// ::= de # * (unary)
2805// ::= dl # delete
2806// ::= dv # /
2807// ::= dV # /=
2808// ::= eo # ^
2809// ::= eO # ^=
2810// ::= eq # ==
2811// ::= ge # >=
2812// ::= gt # >
2813// ::= ix # []
2814// ::= le # <=
2815// ::= li <source-name> # operator ""
2816// ::= ls # <<
2817// ::= lS # <<=
2818// ::= lt # <
2819// ::= mi # -
2820// ::= mI # -=
2821// ::= ml # *
2822// ::= mL # *=
2823// ::= mm # -- (postfix in <expression> context)
2824// ::= na # new[]
2825// ::= ne # !=
2826// ::= ng # - (unary)
2827// ::= nt # !
2828// ::= nw # new
2829// ::= oo # ||
2830// ::= or # |
2831// ::= oR # |=
2832// ::= pm # ->*
2833// ::= pl # +
2834// ::= pL # +=
2835// ::= pp # ++ (postfix in <expression> context)
2836// ::= ps # + (unary)
2837// ::= pt # ->
2838// ::= qu # ?
2839// ::= rm # %
2840// ::= rM # %=
2841// ::= rs # >>
2842// ::= rS # >>=
2843// ::= ss # <=> C++2a
2844// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00002845template <typename Derived, typename Alloc>
2846Node *
2847AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002848 switch (look()) {
2849 case 'a':
2850 switch (look(1)) {
2851 case 'a':
2852 First += 2;
2853 return make<NameType>("operator&&");
2854 case 'd':
2855 case 'n':
2856 First += 2;
2857 return make<NameType>("operator&");
2858 case 'N':
2859 First += 2;
2860 return make<NameType>("operator&=");
2861 case 'S':
2862 First += 2;
2863 return make<NameType>("operator=");
2864 }
2865 return nullptr;
2866 case 'c':
2867 switch (look(1)) {
2868 case 'l':
2869 First += 2;
2870 return make<NameType>("operator()");
2871 case 'm':
2872 First += 2;
2873 return make<NameType>("operator,");
2874 case 'o':
2875 First += 2;
2876 return make<NameType>("operator~");
2877 // ::= cv <type> # (cast)
2878 case 'v': {
2879 First += 2;
2880 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
2881 // If we're parsing an encoding, State != nullptr and the conversion
2882 // operators' <type> could have a <template-param> that refers to some
2883 // <template-arg>s further ahead in the mangled name.
2884 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
2885 PermitForwardTemplateReferences ||
2886 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00002887 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002888 if (Ty == nullptr)
2889 return nullptr;
2890 if (State) State->CtorDtorConversion = true;
2891 return make<ConversionOperatorType>(Ty);
2892 }
2893 }
2894 return nullptr;
2895 case 'd':
2896 switch (look(1)) {
2897 case 'a':
2898 First += 2;
2899 return make<NameType>("operator delete[]");
2900 case 'e':
2901 First += 2;
2902 return make<NameType>("operator*");
2903 case 'l':
2904 First += 2;
2905 return make<NameType>("operator delete");
2906 case 'v':
2907 First += 2;
2908 return make<NameType>("operator/");
2909 case 'V':
2910 First += 2;
2911 return make<NameType>("operator/=");
2912 }
2913 return nullptr;
2914 case 'e':
2915 switch (look(1)) {
2916 case 'o':
2917 First += 2;
2918 return make<NameType>("operator^");
2919 case 'O':
2920 First += 2;
2921 return make<NameType>("operator^=");
2922 case 'q':
2923 First += 2;
2924 return make<NameType>("operator==");
2925 }
2926 return nullptr;
2927 case 'g':
2928 switch (look(1)) {
2929 case 'e':
2930 First += 2;
2931 return make<NameType>("operator>=");
2932 case 't':
2933 First += 2;
2934 return make<NameType>("operator>");
2935 }
2936 return nullptr;
2937 case 'i':
2938 if (look(1) == 'x') {
2939 First += 2;
2940 return make<NameType>("operator[]");
2941 }
2942 return nullptr;
2943 case 'l':
2944 switch (look(1)) {
2945 case 'e':
2946 First += 2;
2947 return make<NameType>("operator<=");
2948 // ::= li <source-name> # operator ""
2949 case 'i': {
2950 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00002951 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002952 if (SN == nullptr)
2953 return nullptr;
2954 return make<LiteralOperator>(SN);
2955 }
2956 case 's':
2957 First += 2;
2958 return make<NameType>("operator<<");
2959 case 'S':
2960 First += 2;
2961 return make<NameType>("operator<<=");
2962 case 't':
2963 First += 2;
2964 return make<NameType>("operator<");
2965 }
2966 return nullptr;
2967 case 'm':
2968 switch (look(1)) {
2969 case 'i':
2970 First += 2;
2971 return make<NameType>("operator-");
2972 case 'I':
2973 First += 2;
2974 return make<NameType>("operator-=");
2975 case 'l':
2976 First += 2;
2977 return make<NameType>("operator*");
2978 case 'L':
2979 First += 2;
2980 return make<NameType>("operator*=");
2981 case 'm':
2982 First += 2;
2983 return make<NameType>("operator--");
2984 }
2985 return nullptr;
2986 case 'n':
2987 switch (look(1)) {
2988 case 'a':
2989 First += 2;
2990 return make<NameType>("operator new[]");
2991 case 'e':
2992 First += 2;
2993 return make<NameType>("operator!=");
2994 case 'g':
2995 First += 2;
2996 return make<NameType>("operator-");
2997 case 't':
2998 First += 2;
2999 return make<NameType>("operator!");
3000 case 'w':
3001 First += 2;
3002 return make<NameType>("operator new");
3003 }
3004 return nullptr;
3005 case 'o':
3006 switch (look(1)) {
3007 case 'o':
3008 First += 2;
3009 return make<NameType>("operator||");
3010 case 'r':
3011 First += 2;
3012 return make<NameType>("operator|");
3013 case 'R':
3014 First += 2;
3015 return make<NameType>("operator|=");
3016 }
3017 return nullptr;
3018 case 'p':
3019 switch (look(1)) {
3020 case 'm':
3021 First += 2;
3022 return make<NameType>("operator->*");
3023 case 'l':
3024 First += 2;
3025 return make<NameType>("operator+");
3026 case 'L':
3027 First += 2;
3028 return make<NameType>("operator+=");
3029 case 'p':
3030 First += 2;
3031 return make<NameType>("operator++");
3032 case 's':
3033 First += 2;
3034 return make<NameType>("operator+");
3035 case 't':
3036 First += 2;
3037 return make<NameType>("operator->");
3038 }
3039 return nullptr;
3040 case 'q':
3041 if (look(1) == 'u') {
3042 First += 2;
3043 return make<NameType>("operator?");
3044 }
3045 return nullptr;
3046 case 'r':
3047 switch (look(1)) {
3048 case 'm':
3049 First += 2;
3050 return make<NameType>("operator%");
3051 case 'M':
3052 First += 2;
3053 return make<NameType>("operator%=");
3054 case 's':
3055 First += 2;
3056 return make<NameType>("operator>>");
3057 case 'S':
3058 First += 2;
3059 return make<NameType>("operator>>=");
3060 }
3061 return nullptr;
3062 case 's':
3063 if (look(1) == 's') {
3064 First += 2;
3065 return make<NameType>("operator<=>");
3066 }
3067 return nullptr;
3068 // ::= v <digit> <source-name> # vendor extended operator
3069 case 'v':
3070 if (std::isdigit(look(1))) {
3071 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003072 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003073 if (SN == nullptr)
3074 return nullptr;
3075 return make<ConversionOperatorType>(SN);
3076 }
3077 return nullptr;
3078 }
3079 return nullptr;
3080}
3081
3082// <ctor-dtor-name> ::= C1 # complete object constructor
3083// ::= C2 # base object constructor
3084// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003085// extension ::= C4 # gcc old-style "[unified]" constructor
3086// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003087// ::= D0 # deleting destructor
3088// ::= D1 # complete object destructor
3089// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003090// extension ::= D4 # gcc old-style "[unified]" destructor
3091// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003092template <typename Derived, typename Alloc>
3093Node *
3094AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3095 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003096 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3097 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3098 switch (SSK) {
3099 case SpecialSubKind::string:
3100 case SpecialSubKind::istream:
3101 case SpecialSubKind::ostream:
3102 case SpecialSubKind::iostream:
3103 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00003104 if (!SoFar)
3105 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00003106 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003107 default:
3108 break;
3109 }
3110 }
3111
3112 if (consumeIf('C')) {
3113 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003114 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3115 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003116 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003117 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003118 ++First;
3119 if (State) State->CtorDtorConversion = true;
3120 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003121 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003122 return nullptr;
3123 }
Nico Weber29294792019-04-03 23:14:33 +00003124 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003125 }
3126
Nico Weber29294792019-04-03 23:14:33 +00003127 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3128 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003129 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003130 First += 2;
3131 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003132 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003133 }
3134
3135 return nullptr;
3136}
3137
3138// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3139// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3140//
3141// <prefix> ::= <prefix> <unqualified-name>
3142// ::= <template-prefix> <template-args>
3143// ::= <template-param>
3144// ::= <decltype>
3145// ::= # empty
3146// ::= <substitution>
3147// ::= <prefix> <data-member-prefix>
3148// extension ::= L
3149//
3150// <data-member-prefix> := <member source-name> [<template-args>] M
3151//
3152// <template-prefix> ::= <prefix> <template unqualified-name>
3153// ::= <template-param>
3154// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003155template <typename Derived, typename Alloc>
3156Node *
3157AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003158 if (!consumeIf('N'))
3159 return nullptr;
3160
3161 Qualifiers CVTmp = parseCVQualifiers();
3162 if (State) State->CVQualifiers = CVTmp;
3163
3164 if (consumeIf('O')) {
3165 if (State) State->ReferenceQualifier = FrefQualRValue;
3166 } else if (consumeIf('R')) {
3167 if (State) State->ReferenceQualifier = FrefQualLValue;
3168 } else
3169 if (State) State->ReferenceQualifier = FrefQualNone;
3170
3171 Node *SoFar = nullptr;
3172 auto PushComponent = [&](Node *Comp) {
Richard Smithb485b352018-08-24 23:30:26 +00003173 if (!Comp) return false;
Richard Smithc20d1442018-08-20 20:14:49 +00003174 if (SoFar) SoFar = make<NestedName>(SoFar, Comp);
3175 else SoFar = Comp;
3176 if (State) State->EndsWithTemplateArgs = false;
Richard Smithb485b352018-08-24 23:30:26 +00003177 return SoFar != nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003178 };
3179
Richard Smithb485b352018-08-24 23:30:26 +00003180 if (consumeIf("St")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003181 SoFar = make<NameType>("std");
Richard Smithb485b352018-08-24 23:30:26 +00003182 if (!SoFar)
3183 return nullptr;
3184 }
Richard Smithc20d1442018-08-20 20:14:49 +00003185
3186 while (!consumeIf('E')) {
3187 consumeIf('L'); // extension
3188
3189 // <data-member-prefix> := <member source-name> [<template-args>] M
3190 if (consumeIf('M')) {
3191 if (SoFar == nullptr)
3192 return nullptr;
3193 continue;
3194 }
3195
3196 // ::= <template-param>
3197 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003198 if (!PushComponent(getDerived().parseTemplateParam()))
Richard Smithc20d1442018-08-20 20:14:49 +00003199 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003200 Subs.push_back(SoFar);
3201 continue;
3202 }
3203
3204 // ::= <template-prefix> <template-args>
3205 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003206 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003207 if (TA == nullptr || SoFar == nullptr)
3208 return nullptr;
3209 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003210 if (!SoFar)
3211 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003212 if (State) State->EndsWithTemplateArgs = true;
3213 Subs.push_back(SoFar);
3214 continue;
3215 }
3216
3217 // ::= <decltype>
3218 if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
Pavel Labathba825192018-10-16 14:29:14 +00003219 if (!PushComponent(getDerived().parseDecltype()))
Richard Smithc20d1442018-08-20 20:14:49 +00003220 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003221 Subs.push_back(SoFar);
3222 continue;
3223 }
3224
3225 // ::= <substitution>
3226 if (look() == 'S' && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00003227 Node *S = getDerived().parseSubstitution();
Richard Smithb485b352018-08-24 23:30:26 +00003228 if (!PushComponent(S))
Richard Smithc20d1442018-08-20 20:14:49 +00003229 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003230 if (SoFar != S)
3231 Subs.push_back(S);
3232 continue;
3233 }
3234
3235 // Parse an <unqualified-name> thats actually a <ctor-dtor-name>.
3236 if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {
3237 if (SoFar == nullptr)
3238 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003239 if (!PushComponent(getDerived().parseCtorDtorName(SoFar, State)))
Richard Smithc20d1442018-08-20 20:14:49 +00003240 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003241 SoFar = getDerived().parseAbiTags(SoFar);
Richard Smithc20d1442018-08-20 20:14:49 +00003242 if (SoFar == nullptr)
3243 return nullptr;
3244 Subs.push_back(SoFar);
3245 continue;
3246 }
3247
3248 // ::= <prefix> <unqualified-name>
Pavel Labathba825192018-10-16 14:29:14 +00003249 if (!PushComponent(getDerived().parseUnqualifiedName(State)))
Richard Smithc20d1442018-08-20 20:14:49 +00003250 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003251 Subs.push_back(SoFar);
3252 }
3253
3254 if (SoFar == nullptr || Subs.empty())
3255 return nullptr;
3256
3257 Subs.pop_back();
3258 return SoFar;
3259}
3260
3261// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003262template <typename Derived, typename Alloc>
3263Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3264 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003265 if (SN == nullptr)
3266 return nullptr;
3267 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003268 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003269 if (TA == nullptr)
3270 return nullptr;
3271 return make<NameWithTemplateArgs>(SN, TA);
3272 }
3273 return SN;
3274}
3275
3276// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3277// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003278template <typename Derived, typename Alloc>
3279Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003280 Node *Result;
3281 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003282 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003283 else
Pavel Labathba825192018-10-16 14:29:14 +00003284 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003285 if (Result == nullptr)
3286 return nullptr;
3287 return make<DtorName>(Result);
3288}
3289
3290// <unresolved-type> ::= <template-param>
3291// ::= <decltype>
3292// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003293template <typename Derived, typename Alloc>
3294Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003295 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003296 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003297 if (TP == nullptr)
3298 return nullptr;
3299 Subs.push_back(TP);
3300 return TP;
3301 }
3302 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003303 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003304 if (DT == nullptr)
3305 return nullptr;
3306 Subs.push_back(DT);
3307 return DT;
3308 }
Pavel Labathba825192018-10-16 14:29:14 +00003309 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003310}
3311
3312// <base-unresolved-name> ::= <simple-id> # unresolved name
3313// extension ::= <operator-name> # unresolved operator-function-id
3314// extension ::= <operator-name> <template-args> # unresolved operator template-id
3315// ::= on <operator-name> # unresolved operator-function-id
3316// ::= on <operator-name> <template-args> # unresolved operator template-id
3317// ::= dn <destructor-name> # destructor or pseudo-destructor;
3318// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003319template <typename Derived, typename Alloc>
3320Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003321 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003322 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003323
3324 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003325 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003326
3327 consumeIf("on");
3328
Pavel Labathba825192018-10-16 14:29:14 +00003329 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003330 if (Oper == nullptr)
3331 return nullptr;
3332 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003333 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003334 if (TA == nullptr)
3335 return nullptr;
3336 return make<NameWithTemplateArgs>(Oper, TA);
3337 }
3338 return Oper;
3339}
3340
3341// <unresolved-name>
3342// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3343// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3344// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3345// # A::x, N::y, A<T>::z; "gs" means leading "::"
3346// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3347// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3348// # T::N::x /decltype(p)::N::x
3349// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3350//
3351// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003352template <typename Derived, typename Alloc>
3353Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003354 Node *SoFar = nullptr;
3355
3356 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3357 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3358 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003359 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003360 if (SoFar == nullptr)
3361 return nullptr;
3362
3363 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003364 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003365 if (TA == nullptr)
3366 return nullptr;
3367 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003368 if (!SoFar)
3369 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003370 }
3371
3372 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003373 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003374 if (Qual == nullptr)
3375 return nullptr;
3376 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003377 if (!SoFar)
3378 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003379 }
3380
Pavel Labathba825192018-10-16 14:29:14 +00003381 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003382 if (Base == nullptr)
3383 return nullptr;
3384 return make<QualifiedName>(SoFar, Base);
3385 }
3386
3387 bool Global = consumeIf("gs");
3388
3389 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3390 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003391 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003392 if (SoFar == nullptr)
3393 return nullptr;
3394 if (Global)
3395 SoFar = make<GlobalQualifiedName>(SoFar);
3396 return SoFar;
3397 }
3398
3399 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3400 if (std::isdigit(look())) {
3401 do {
Pavel Labathba825192018-10-16 14:29:14 +00003402 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003403 if (Qual == nullptr)
3404 return nullptr;
3405 if (SoFar)
3406 SoFar = make<QualifiedName>(SoFar, Qual);
3407 else if (Global)
3408 SoFar = make<GlobalQualifiedName>(Qual);
3409 else
3410 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003411 if (!SoFar)
3412 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003413 } while (!consumeIf('E'));
3414 }
3415 // sr <unresolved-type> <base-unresolved-name>
3416 // sr <unresolved-type> <template-args> <base-unresolved-name>
3417 else {
Pavel Labathba825192018-10-16 14:29:14 +00003418 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003419 if (SoFar == nullptr)
3420 return nullptr;
3421
3422 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003423 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003424 if (TA == nullptr)
3425 return nullptr;
3426 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003427 if (!SoFar)
3428 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003429 }
3430 }
3431
3432 assert(SoFar != nullptr);
3433
Pavel Labathba825192018-10-16 14:29:14 +00003434 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003435 if (Base == nullptr)
3436 return nullptr;
3437 return make<QualifiedName>(SoFar, Base);
3438}
3439
3440// <abi-tags> ::= <abi-tag> [<abi-tags>]
3441// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003442template <typename Derived, typename Alloc>
3443Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003444 while (consumeIf('B')) {
3445 StringView SN = parseBareSourceName();
3446 if (SN.empty())
3447 return nullptr;
3448 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003449 if (!N)
3450 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003451 }
3452 return N;
3453}
3454
3455// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003456template <typename Alloc, typename Derived>
3457StringView
3458AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003459 const char *Tmp = First;
3460 if (AllowNegative)
3461 consumeIf('n');
3462 if (numLeft() == 0 || !std::isdigit(*First))
3463 return StringView();
3464 while (numLeft() != 0 && std::isdigit(*First))
3465 ++First;
3466 return StringView(Tmp, First);
3467}
3468
3469// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003470template <typename Alloc, typename Derived>
3471bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003472 *Out = 0;
3473 if (look() < '0' || look() > '9')
3474 return true;
3475 while (look() >= '0' && look() <= '9') {
3476 *Out *= 10;
3477 *Out += static_cast<size_t>(consume() - '0');
3478 }
3479 return false;
3480}
3481
Pavel Labathba825192018-10-16 14:29:14 +00003482template <typename Alloc, typename Derived>
3483StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003484 size_t Int = 0;
3485 if (parsePositiveInteger(&Int) || numLeft() < Int)
3486 return StringView();
3487 StringView R(First, First + Int);
3488 First += Int;
3489 return R;
3490}
3491
3492// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3493//
3494// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3495// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3496// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3497//
3498// <ref-qualifier> ::= R # & ref-qualifier
3499// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003500template <typename Derived, typename Alloc>
3501Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003502 Qualifiers CVQuals = parseCVQualifiers();
3503
3504 Node *ExceptionSpec = nullptr;
3505 if (consumeIf("Do")) {
3506 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003507 if (!ExceptionSpec)
3508 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003509 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003510 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003511 if (E == nullptr || !consumeIf('E'))
3512 return nullptr;
3513 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003514 if (!ExceptionSpec)
3515 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003516 } else if (consumeIf("Dw")) {
3517 size_t SpecsBegin = Names.size();
3518 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003519 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003520 if (T == nullptr)
3521 return nullptr;
3522 Names.push_back(T);
3523 }
3524 ExceptionSpec =
3525 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003526 if (!ExceptionSpec)
3527 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003528 }
3529
3530 consumeIf("Dx"); // transaction safe
3531
3532 if (!consumeIf('F'))
3533 return nullptr;
3534 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003535 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003536 if (ReturnType == nullptr)
3537 return nullptr;
3538
3539 FunctionRefQual ReferenceQualifier = FrefQualNone;
3540 size_t ParamsBegin = Names.size();
3541 while (true) {
3542 if (consumeIf('E'))
3543 break;
3544 if (consumeIf('v'))
3545 continue;
3546 if (consumeIf("RE")) {
3547 ReferenceQualifier = FrefQualLValue;
3548 break;
3549 }
3550 if (consumeIf("OE")) {
3551 ReferenceQualifier = FrefQualRValue;
3552 break;
3553 }
Pavel Labathba825192018-10-16 14:29:14 +00003554 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003555 if (T == nullptr)
3556 return nullptr;
3557 Names.push_back(T);
3558 }
3559
3560 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3561 return make<FunctionType>(ReturnType, Params, CVQuals,
3562 ReferenceQualifier, ExceptionSpec);
3563}
3564
3565// extension:
3566// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3567// ::= Dv [<dimension expression>] _ <element type>
3568// <extended element type> ::= <element type>
3569// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003570template <typename Derived, typename Alloc>
3571Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003572 if (!consumeIf("Dv"))
3573 return nullptr;
3574 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003575 Node *DimensionNumber = make<NameType>(parseNumber());
3576 if (!DimensionNumber)
3577 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003578 if (!consumeIf('_'))
3579 return nullptr;
3580 if (consumeIf('p'))
3581 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003582 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003583 if (ElemType == nullptr)
3584 return nullptr;
3585 return make<VectorType>(ElemType, DimensionNumber);
3586 }
3587
3588 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003589 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003590 if (!DimExpr)
3591 return nullptr;
3592 if (!consumeIf('_'))
3593 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003594 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003595 if (!ElemType)
3596 return nullptr;
3597 return make<VectorType>(ElemType, DimExpr);
3598 }
Pavel Labathba825192018-10-16 14:29:14 +00003599 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003600 if (!ElemType)
3601 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003602 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003603}
3604
3605// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3606// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003607template <typename Derived, typename Alloc>
3608Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003609 if (!consumeIf('D'))
3610 return nullptr;
3611 if (!consumeIf('t') && !consumeIf('T'))
3612 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003613 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003614 if (E == nullptr)
3615 return nullptr;
3616 if (!consumeIf('E'))
3617 return nullptr;
3618 return make<EnclosingExpr>("decltype(", E, ")");
3619}
3620
3621// <array-type> ::= A <positive dimension number> _ <element type>
3622// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003623template <typename Derived, typename Alloc>
3624Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003625 if (!consumeIf('A'))
3626 return nullptr;
3627
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003628 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003629
Richard Smithc20d1442018-08-20 20:14:49 +00003630 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003631 Dimension = make<NameType>(parseNumber());
3632 if (!Dimension)
3633 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003634 if (!consumeIf('_'))
3635 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003636 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003637 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003638 if (DimExpr == nullptr)
3639 return nullptr;
3640 if (!consumeIf('_'))
3641 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003642 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003643 }
3644
Pavel Labathba825192018-10-16 14:29:14 +00003645 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003646 if (Ty == nullptr)
3647 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003648 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003649}
3650
3651// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003652template <typename Derived, typename Alloc>
3653Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003654 if (!consumeIf('M'))
3655 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003656 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003657 if (ClassType == nullptr)
3658 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003659 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003660 if (MemberType == nullptr)
3661 return nullptr;
3662 return make<PointerToMemberType>(ClassType, MemberType);
3663}
3664
3665// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3666// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3667// ::= Tu <name> # dependent elaborated type specifier using 'union'
3668// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003669template <typename Derived, typename Alloc>
3670Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003671 StringView ElabSpef;
3672 if (consumeIf("Ts"))
3673 ElabSpef = "struct";
3674 else if (consumeIf("Tu"))
3675 ElabSpef = "union";
3676 else if (consumeIf("Te"))
3677 ElabSpef = "enum";
3678
Pavel Labathba825192018-10-16 14:29:14 +00003679 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003680 if (Name == nullptr)
3681 return nullptr;
3682
3683 if (!ElabSpef.empty())
3684 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3685
3686 return Name;
3687}
3688
3689// <qualified-type> ::= <qualifiers> <type>
3690// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3691// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003692template <typename Derived, typename Alloc>
3693Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003694 if (consumeIf('U')) {
3695 StringView Qual = parseBareSourceName();
3696 if (Qual.empty())
3697 return nullptr;
3698
3699 // FIXME parse the optional <template-args> here!
3700
3701 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3702 if (Qual.startsWith("objcproto")) {
3703 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3704 StringView Proto;
3705 {
3706 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3707 SaveLast(Last, ProtoSourceName.end());
3708 Proto = parseBareSourceName();
3709 }
3710 if (Proto.empty())
3711 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003712 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003713 if (Child == nullptr)
3714 return nullptr;
3715 return make<ObjCProtoName>(Child, Proto);
3716 }
3717
Pavel Labathba825192018-10-16 14:29:14 +00003718 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003719 if (Child == nullptr)
3720 return nullptr;
3721 return make<VendorExtQualType>(Child, Qual);
3722 }
3723
3724 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003725 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003726 if (Ty == nullptr)
3727 return nullptr;
3728 if (Quals != QualNone)
3729 Ty = make<QualType>(Ty, Quals);
3730 return Ty;
3731}
3732
3733// <type> ::= <builtin-type>
3734// ::= <qualified-type>
3735// ::= <function-type>
3736// ::= <class-enum-type>
3737// ::= <array-type>
3738// ::= <pointer-to-member-type>
3739// ::= <template-param>
3740// ::= <template-template-param> <template-args>
3741// ::= <decltype>
3742// ::= P <type> # pointer
3743// ::= R <type> # l-value reference
3744// ::= O <type> # r-value reference (C++11)
3745// ::= C <type> # complex pair (C99)
3746// ::= G <type> # imaginary (C99)
3747// ::= <substitution> # See Compression below
3748// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3749// extension ::= <vector-type> # <vector-type> starts with Dv
3750//
3751// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3752// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003753template <typename Derived, typename Alloc>
3754Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003755 Node *Result = nullptr;
3756
Richard Smithc20d1442018-08-20 20:14:49 +00003757 switch (look()) {
3758 // ::= <qualified-type>
3759 case 'r':
3760 case 'V':
3761 case 'K': {
3762 unsigned AfterQuals = 0;
3763 if (look(AfterQuals) == 'r') ++AfterQuals;
3764 if (look(AfterQuals) == 'V') ++AfterQuals;
3765 if (look(AfterQuals) == 'K') ++AfterQuals;
3766
3767 if (look(AfterQuals) == 'F' ||
3768 (look(AfterQuals) == 'D' &&
3769 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3770 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003771 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003772 break;
3773 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003774 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003775 }
3776 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003777 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003778 break;
3779 }
3780 // <builtin-type> ::= v # void
3781 case 'v':
3782 ++First;
3783 return make<NameType>("void");
3784 // ::= w # wchar_t
3785 case 'w':
3786 ++First;
3787 return make<NameType>("wchar_t");
3788 // ::= b # bool
3789 case 'b':
3790 ++First;
3791 return make<NameType>("bool");
3792 // ::= c # char
3793 case 'c':
3794 ++First;
3795 return make<NameType>("char");
3796 // ::= a # signed char
3797 case 'a':
3798 ++First;
3799 return make<NameType>("signed char");
3800 // ::= h # unsigned char
3801 case 'h':
3802 ++First;
3803 return make<NameType>("unsigned char");
3804 // ::= s # short
3805 case 's':
3806 ++First;
3807 return make<NameType>("short");
3808 // ::= t # unsigned short
3809 case 't':
3810 ++First;
3811 return make<NameType>("unsigned short");
3812 // ::= i # int
3813 case 'i':
3814 ++First;
3815 return make<NameType>("int");
3816 // ::= j # unsigned int
3817 case 'j':
3818 ++First;
3819 return make<NameType>("unsigned int");
3820 // ::= l # long
3821 case 'l':
3822 ++First;
3823 return make<NameType>("long");
3824 // ::= m # unsigned long
3825 case 'm':
3826 ++First;
3827 return make<NameType>("unsigned long");
3828 // ::= x # long long, __int64
3829 case 'x':
3830 ++First;
3831 return make<NameType>("long long");
3832 // ::= y # unsigned long long, __int64
3833 case 'y':
3834 ++First;
3835 return make<NameType>("unsigned long long");
3836 // ::= n # __int128
3837 case 'n':
3838 ++First;
3839 return make<NameType>("__int128");
3840 // ::= o # unsigned __int128
3841 case 'o':
3842 ++First;
3843 return make<NameType>("unsigned __int128");
3844 // ::= f # float
3845 case 'f':
3846 ++First;
3847 return make<NameType>("float");
3848 // ::= d # double
3849 case 'd':
3850 ++First;
3851 return make<NameType>("double");
3852 // ::= e # long double, __float80
3853 case 'e':
3854 ++First;
3855 return make<NameType>("long double");
3856 // ::= g # __float128
3857 case 'g':
3858 ++First;
3859 return make<NameType>("__float128");
3860 // ::= z # ellipsis
3861 case 'z':
3862 ++First;
3863 return make<NameType>("...");
3864
3865 // <builtin-type> ::= u <source-name> # vendor extended type
3866 case 'u': {
3867 ++First;
3868 StringView Res = parseBareSourceName();
3869 if (Res.empty())
3870 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003871 // Typically, <builtin-type>s are not considered substitution candidates,
3872 // but the exception to that exception is vendor extended types (Itanium C++
3873 // ABI 5.9.1).
3874 Result = make<NameType>(Res);
3875 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003876 }
3877 case 'D':
3878 switch (look(1)) {
3879 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3880 case 'd':
3881 First += 2;
3882 return make<NameType>("decimal64");
3883 // ::= De # IEEE 754r decimal floating point (128 bits)
3884 case 'e':
3885 First += 2;
3886 return make<NameType>("decimal128");
3887 // ::= Df # IEEE 754r decimal floating point (32 bits)
3888 case 'f':
3889 First += 2;
3890 return make<NameType>("decimal32");
3891 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3892 case 'h':
3893 First += 2;
3894 return make<NameType>("decimal16");
3895 // ::= Di # char32_t
3896 case 'i':
3897 First += 2;
3898 return make<NameType>("char32_t");
3899 // ::= Ds # char16_t
3900 case 's':
3901 First += 2;
3902 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003903 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3904 case 'u':
3905 First += 2;
3906 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003907 // ::= Da # auto (in dependent new-expressions)
3908 case 'a':
3909 First += 2;
3910 return make<NameType>("auto");
3911 // ::= Dc # decltype(auto)
3912 case 'c':
3913 First += 2;
3914 return make<NameType>("decltype(auto)");
3915 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3916 case 'n':
3917 First += 2;
3918 return make<NameType>("std::nullptr_t");
3919
3920 // ::= <decltype>
3921 case 't':
3922 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003923 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003924 break;
3925 }
3926 // extension ::= <vector-type> # <vector-type> starts with Dv
3927 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003928 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003929 break;
3930 }
3931 // ::= Dp <type> # pack expansion (C++0x)
3932 case 'p': {
3933 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003934 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003935 if (!Child)
3936 return nullptr;
3937 Result = make<ParameterPackExpansion>(Child);
3938 break;
3939 }
3940 // Exception specifier on a function type.
3941 case 'o':
3942 case 'O':
3943 case 'w':
3944 // Transaction safe function type.
3945 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003946 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003947 break;
3948 }
3949 break;
3950 // ::= <function-type>
3951 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003952 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003953 break;
3954 }
3955 // ::= <array-type>
3956 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003957 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003958 break;
3959 }
3960 // ::= <pointer-to-member-type>
3961 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003962 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003963 break;
3964 }
3965 // ::= <template-param>
3966 case 'T': {
3967 // This could be an elaborate type specifier on a <class-enum-type>.
3968 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00003969 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003970 break;
3971 }
3972
Pavel Labathba825192018-10-16 14:29:14 +00003973 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003974 if (Result == nullptr)
3975 return nullptr;
3976
3977 // Result could be either of:
3978 // <type> ::= <template-param>
3979 // <type> ::= <template-template-param> <template-args>
3980 //
3981 // <template-template-param> ::= <template-param>
3982 // ::= <substitution>
3983 //
3984 // If this is followed by some <template-args>, and we're permitted to
3985 // parse them, take the second production.
3986
3987 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003988 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003989 if (TA == nullptr)
3990 return nullptr;
3991 Result = make<NameWithTemplateArgs>(Result, TA);
3992 }
3993 break;
3994 }
3995 // ::= P <type> # pointer
3996 case 'P': {
3997 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00003998 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003999 if (Ptr == nullptr)
4000 return nullptr;
4001 Result = make<PointerType>(Ptr);
4002 break;
4003 }
4004 // ::= R <type> # l-value reference
4005 case 'R': {
4006 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004007 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004008 if (Ref == nullptr)
4009 return nullptr;
4010 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4011 break;
4012 }
4013 // ::= O <type> # r-value reference (C++11)
4014 case 'O': {
4015 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004016 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004017 if (Ref == nullptr)
4018 return nullptr;
4019 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4020 break;
4021 }
4022 // ::= C <type> # complex pair (C99)
4023 case 'C': {
4024 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004025 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004026 if (P == nullptr)
4027 return nullptr;
4028 Result = make<PostfixQualifiedType>(P, " complex");
4029 break;
4030 }
4031 // ::= G <type> # imaginary (C99)
4032 case 'G': {
4033 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004034 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004035 if (P == nullptr)
4036 return P;
4037 Result = make<PostfixQualifiedType>(P, " imaginary");
4038 break;
4039 }
4040 // ::= <substitution> # See Compression below
4041 case 'S': {
4042 if (look(1) && look(1) != 't') {
Pavel Labathba825192018-10-16 14:29:14 +00004043 Node *Sub = getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00004044 if (Sub == nullptr)
4045 return nullptr;
4046
4047 // Sub could be either of:
4048 // <type> ::= <substitution>
4049 // <type> ::= <template-template-param> <template-args>
4050 //
4051 // <template-template-param> ::= <template-param>
4052 // ::= <substitution>
4053 //
4054 // If this is followed by some <template-args>, and we're permitted to
4055 // parse them, take the second production.
4056
4057 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004058 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004059 if (TA == nullptr)
4060 return nullptr;
4061 Result = make<NameWithTemplateArgs>(Sub, TA);
4062 break;
4063 }
4064
4065 // If all we parsed was a substitution, don't re-insert into the
4066 // substitution table.
4067 return Sub;
4068 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004069 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004070 }
4071 // ::= <class-enum-type>
4072 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004073 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004074 break;
4075 }
4076 }
4077
4078 // If we parsed a type, insert it into the substitution table. Note that all
4079 // <builtin-type>s and <substitution>s have already bailed out, because they
4080 // don't get substitutions.
4081 if (Result != nullptr)
4082 Subs.push_back(Result);
4083 return Result;
4084}
4085
Pavel Labathba825192018-10-16 14:29:14 +00004086template <typename Derived, typename Alloc>
4087Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) {
4088 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004089 if (E == nullptr)
4090 return nullptr;
4091 return make<PrefixExpr>(Kind, E);
4092}
4093
Pavel Labathba825192018-10-16 14:29:14 +00004094template <typename Derived, typename Alloc>
4095Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) {
4096 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004097 if (LHS == nullptr)
4098 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004099 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004100 if (RHS == nullptr)
4101 return nullptr;
4102 return make<BinaryExpr>(LHS, Kind, RHS);
4103}
4104
Pavel Labathba825192018-10-16 14:29:14 +00004105template <typename Derived, typename Alloc>
4106Node *
4107AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004108 StringView Tmp = parseNumber(true);
4109 if (!Tmp.empty() && consumeIf('E'))
4110 return make<IntegerLiteral>(Lit, Tmp);
4111 return nullptr;
4112}
4113
4114// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004115template <typename Alloc, typename Derived>
4116Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004117 Qualifiers CVR = QualNone;
4118 if (consumeIf('r'))
4119 CVR |= QualRestrict;
4120 if (consumeIf('V'))
4121 CVR |= QualVolatile;
4122 if (consumeIf('K'))
4123 CVR |= QualConst;
4124 return CVR;
4125}
4126
4127// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4128// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4129// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4130// ::= 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 -04004131// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004132template <typename Derived, typename Alloc>
4133Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004134 if (consumeIf("fpT"))
4135 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004136 if (consumeIf("fp")) {
4137 parseCVQualifiers();
4138 StringView Num = parseNumber();
4139 if (!consumeIf('_'))
4140 return nullptr;
4141 return make<FunctionParam>(Num);
4142 }
4143 if (consumeIf("fL")) {
4144 if (parseNumber().empty())
4145 return nullptr;
4146 if (!consumeIf('p'))
4147 return nullptr;
4148 parseCVQualifiers();
4149 StringView Num = parseNumber();
4150 if (!consumeIf('_'))
4151 return nullptr;
4152 return make<FunctionParam>(Num);
4153 }
4154 return nullptr;
4155}
4156
4157// [gs] nw <expression>* _ <type> E # new (expr-list) type
4158// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4159// [gs] na <expression>* _ <type> E # new[] (expr-list) type
4160// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4161// <initializer> ::= pi <expression>* E # parenthesized initialization
Pavel Labathba825192018-10-16 14:29:14 +00004162template <typename Derived, typename Alloc>
4163Node *AbstractManglingParser<Derived, Alloc>::parseNewExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004164 bool Global = consumeIf("gs");
4165 bool IsArray = look(1) == 'a';
4166 if (!consumeIf("nw") && !consumeIf("na"))
4167 return nullptr;
4168 size_t Exprs = Names.size();
4169 while (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00004170 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004171 if (Ex == nullptr)
4172 return nullptr;
4173 Names.push_back(Ex);
4174 }
4175 NodeArray ExprList = popTrailingNodeArray(Exprs);
Pavel Labathba825192018-10-16 14:29:14 +00004176 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004177 if (Ty == nullptr)
4178 return Ty;
4179 if (consumeIf("pi")) {
4180 size_t InitsBegin = Names.size();
4181 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004182 Node *Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004183 if (Init == nullptr)
4184 return Init;
4185 Names.push_back(Init);
4186 }
4187 NodeArray Inits = popTrailingNodeArray(InitsBegin);
4188 return make<NewExpr>(ExprList, Ty, Inits, Global, IsArray);
4189 } else if (!consumeIf('E'))
4190 return nullptr;
4191 return make<NewExpr>(ExprList, Ty, NodeArray(), Global, IsArray);
4192}
4193
4194// cv <type> <expression> # conversion with one argument
4195// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004196template <typename Derived, typename Alloc>
4197Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004198 if (!consumeIf("cv"))
4199 return nullptr;
4200 Node *Ty;
4201 {
4202 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004203 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004204 }
4205
4206 if (Ty == nullptr)
4207 return nullptr;
4208
4209 if (consumeIf('_')) {
4210 size_t ExprsBegin = Names.size();
4211 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004212 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004213 if (E == nullptr)
4214 return E;
4215 Names.push_back(E);
4216 }
4217 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4218 return make<ConversionExpr>(Ty, Exprs);
4219 }
4220
Pavel Labathba825192018-10-16 14:29:14 +00004221 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004222 if (E[0] == nullptr)
4223 return nullptr;
4224 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4225}
4226
4227// <expr-primary> ::= L <type> <value number> E # integer literal
4228// ::= L <type> <value float> E # floating literal
4229// ::= L <string type> E # string literal
4230// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004231// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004232// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4233// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004234template <typename Derived, typename Alloc>
4235Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004236 if (!consumeIf('L'))
4237 return nullptr;
4238 switch (look()) {
4239 case 'w':
4240 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004241 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004242 case 'b':
4243 if (consumeIf("b0E"))
4244 return make<BoolExpr>(0);
4245 if (consumeIf("b1E"))
4246 return make<BoolExpr>(1);
4247 return nullptr;
4248 case 'c':
4249 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004250 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004251 case 'a':
4252 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004253 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004254 case 'h':
4255 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004256 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004257 case 's':
4258 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004259 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004260 case 't':
4261 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004262 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004263 case 'i':
4264 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004265 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004266 case 'j':
4267 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004268 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004269 case 'l':
4270 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004271 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004272 case 'm':
4273 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004274 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004275 case 'x':
4276 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004277 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004278 case 'y':
4279 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004280 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004281 case 'n':
4282 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004283 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004284 case 'o':
4285 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004286 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004287 case 'f':
4288 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004289 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004290 case 'd':
4291 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004292 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004293 case 'e':
4294 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004295#if defined(__powerpc__) || defined(__s390__)
4296 // Handle cases where long doubles encoded with e have the same size
4297 // and representation as doubles.
4298 return getDerived().template parseFloatingLiteral<double>();
4299#else
Pavel Labathba825192018-10-16 14:29:14 +00004300 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004301#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004302 case '_':
4303 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004304 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004305 if (R != nullptr && consumeIf('E'))
4306 return R;
4307 }
4308 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004309 case 'A': {
4310 Node *T = getDerived().parseType();
4311 if (T == nullptr)
4312 return nullptr;
4313 // FIXME: We need to include the string contents in the mangling.
4314 if (consumeIf('E'))
4315 return make<StringLiteral>(T);
4316 return nullptr;
4317 }
4318 case 'D':
4319 if (consumeIf("DnE"))
4320 return make<NameType>("nullptr");
4321 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004322 case 'T':
4323 // Invalid mangled name per
4324 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4325 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004326 case 'U': {
4327 // FIXME: Should we support LUb... for block literals?
4328 if (look(1) != 'l')
4329 return nullptr;
4330 Node *T = parseUnnamedTypeName(nullptr);
4331 if (!T || !consumeIf('E'))
4332 return nullptr;
4333 return make<LambdaExpr>(T);
4334 }
Richard Smithc20d1442018-08-20 20:14:49 +00004335 default: {
4336 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004337 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004338 if (T == nullptr)
4339 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004340 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004341 if (N.empty())
4342 return nullptr;
4343 if (!consumeIf('E'))
4344 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004345 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004346 }
4347 }
4348}
4349
4350// <braced-expression> ::= <expression>
4351// ::= di <field source-name> <braced-expression> # .name = expr
4352// ::= dx <index expression> <braced-expression> # [expr] = expr
4353// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004354template <typename Derived, typename Alloc>
4355Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004356 if (look() == 'd') {
4357 switch (look(1)) {
4358 case 'i': {
4359 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004360 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004361 if (Field == nullptr)
4362 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004363 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004364 if (Init == nullptr)
4365 return nullptr;
4366 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4367 }
4368 case 'x': {
4369 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004370 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004371 if (Index == nullptr)
4372 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004373 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004374 if (Init == nullptr)
4375 return nullptr;
4376 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4377 }
4378 case 'X': {
4379 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004380 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004381 if (RangeBegin == nullptr)
4382 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004383 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004384 if (RangeEnd == nullptr)
4385 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004386 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004387 if (Init == nullptr)
4388 return nullptr;
4389 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4390 }
4391 }
4392 }
Pavel Labathba825192018-10-16 14:29:14 +00004393 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004394}
4395
4396// (not yet in the spec)
4397// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4398// ::= fR <binary-operator-name> <expression> <expression>
4399// ::= fl <binary-operator-name> <expression>
4400// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004401template <typename Derived, typename Alloc>
4402Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004403 if (!consumeIf('f'))
4404 return nullptr;
4405
4406 char FoldKind = look();
4407 bool IsLeftFold, HasInitializer;
4408 HasInitializer = FoldKind == 'L' || FoldKind == 'R';
4409 if (FoldKind == 'l' || FoldKind == 'L')
4410 IsLeftFold = true;
4411 else if (FoldKind == 'r' || FoldKind == 'R')
4412 IsLeftFold = false;
4413 else
4414 return nullptr;
4415 ++First;
4416
4417 // FIXME: This map is duplicated in parseOperatorName and parseExpr.
4418 StringView OperatorName;
4419 if (consumeIf("aa")) OperatorName = "&&";
4420 else if (consumeIf("an")) OperatorName = "&";
4421 else if (consumeIf("aN")) OperatorName = "&=";
4422 else if (consumeIf("aS")) OperatorName = "=";
4423 else if (consumeIf("cm")) OperatorName = ",";
4424 else if (consumeIf("ds")) OperatorName = ".*";
4425 else if (consumeIf("dv")) OperatorName = "/";
4426 else if (consumeIf("dV")) OperatorName = "/=";
4427 else if (consumeIf("eo")) OperatorName = "^";
4428 else if (consumeIf("eO")) OperatorName = "^=";
4429 else if (consumeIf("eq")) OperatorName = "==";
4430 else if (consumeIf("ge")) OperatorName = ">=";
4431 else if (consumeIf("gt")) OperatorName = ">";
4432 else if (consumeIf("le")) OperatorName = "<=";
4433 else if (consumeIf("ls")) OperatorName = "<<";
4434 else if (consumeIf("lS")) OperatorName = "<<=";
4435 else if (consumeIf("lt")) OperatorName = "<";
4436 else if (consumeIf("mi")) OperatorName = "-";
4437 else if (consumeIf("mI")) OperatorName = "-=";
4438 else if (consumeIf("ml")) OperatorName = "*";
4439 else if (consumeIf("mL")) OperatorName = "*=";
4440 else if (consumeIf("ne")) OperatorName = "!=";
4441 else if (consumeIf("oo")) OperatorName = "||";
4442 else if (consumeIf("or")) OperatorName = "|";
4443 else if (consumeIf("oR")) OperatorName = "|=";
4444 else if (consumeIf("pl")) OperatorName = "+";
4445 else if (consumeIf("pL")) OperatorName = "+=";
4446 else if (consumeIf("rm")) OperatorName = "%";
4447 else if (consumeIf("rM")) OperatorName = "%=";
4448 else if (consumeIf("rs")) OperatorName = ">>";
4449 else if (consumeIf("rS")) OperatorName = ">>=";
4450 else return nullptr;
4451
Pavel Labathba825192018-10-16 14:29:14 +00004452 Node *Pack = getDerived().parseExpr(), *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004453 if (Pack == nullptr)
4454 return nullptr;
4455 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004456 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004457 if (Init == nullptr)
4458 return nullptr;
4459 }
4460
4461 if (IsLeftFold && Init)
4462 std::swap(Pack, Init);
4463
4464 return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);
4465}
4466
Richard Smith1865d2f2020-10-22 19:29:36 -07004467// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4468//
4469// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4470template <typename Derived, typename Alloc>
4471Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr() {
4472 Node *Ty = getDerived().parseType();
4473 if (!Ty)
4474 return nullptr;
4475 Node *Expr = getDerived().parseExpr();
4476 if (!Expr)
4477 return nullptr;
4478 StringView Offset = getDerived().parseNumber(true);
4479 if (!consumeIf('E'))
4480 return nullptr;
4481 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset);
4482}
4483
4484// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4485// <union-selector> ::= _ [<number>]
4486//
4487// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4488template <typename Derived, typename Alloc>
4489Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4490 Node *Ty = getDerived().parseType();
4491 if (!Ty)
4492 return nullptr;
4493 Node *Expr = getDerived().parseExpr();
4494 if (!Expr)
4495 return nullptr;
4496 StringView Offset = getDerived().parseNumber(true);
4497 size_t SelectorsBegin = Names.size();
4498 while (consumeIf('_')) {
4499 Node *Selector = make<NameType>(parseNumber());
4500 if (!Selector)
4501 return nullptr;
4502 Names.push_back(Selector);
4503 }
4504 bool OnePastTheEnd = consumeIf('p');
4505 if (!consumeIf('E'))
4506 return nullptr;
4507 return make<SubobjectExpr>(
4508 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4509}
4510
Richard Smithc20d1442018-08-20 20:14:49 +00004511// <expression> ::= <unary operator-name> <expression>
4512// ::= <binary operator-name> <expression> <expression>
4513// ::= <ternary operator-name> <expression> <expression> <expression>
4514// ::= cl <expression>+ E # call
4515// ::= cv <type> <expression> # conversion with one argument
4516// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4517// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4518// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4519// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4520// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4521// ::= [gs] dl <expression> # delete expression
4522// ::= [gs] da <expression> # delete[] expression
4523// ::= pp_ <expression> # prefix ++
4524// ::= mm_ <expression> # prefix --
4525// ::= ti <type> # typeid (type)
4526// ::= te <expression> # typeid (expression)
4527// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4528// ::= sc <type> <expression> # static_cast<type> (expression)
4529// ::= cc <type> <expression> # const_cast<type> (expression)
4530// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4531// ::= st <type> # sizeof (a type)
4532// ::= sz <expression> # sizeof (an expression)
4533// ::= at <type> # alignof (a type)
4534// ::= az <expression> # alignof (an expression)
4535// ::= nx <expression> # noexcept (expression)
4536// ::= <template-param>
4537// ::= <function-param>
4538// ::= dt <expression> <unresolved-name> # expr.name
4539// ::= pt <expression> <unresolved-name> # expr->name
4540// ::= ds <expression> <expression> # expr.*expr
4541// ::= sZ <template-param> # size of a parameter pack
4542// ::= sZ <function-param> # size of a function parameter pack
4543// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4544// ::= sp <expression> # pack expansion
4545// ::= tw <expression> # throw expression
4546// ::= tr # throw with no operand (rethrow)
4547// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4548// # freestanding dependent name (e.g., T::x),
4549// # objectless nonstatic member reference
4550// ::= fL <binary-operator-name> <expression> <expression>
4551// ::= fR <binary-operator-name> <expression> <expression>
4552// ::= fl <binary-operator-name> <expression>
4553// ::= fr <binary-operator-name> <expression>
4554// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004555template <typename Derived, typename Alloc>
4556Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004557 bool Global = consumeIf("gs");
4558 if (numLeft() < 2)
4559 return nullptr;
4560
4561 switch (*First) {
4562 case 'L':
Pavel Labathba825192018-10-16 14:29:14 +00004563 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00004564 case 'T':
Pavel Labathba825192018-10-16 14:29:14 +00004565 return getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004566 case 'f': {
4567 // Disambiguate a fold expression from a <function-param>.
4568 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
Pavel Labathba825192018-10-16 14:29:14 +00004569 return getDerived().parseFunctionParam();
4570 return getDerived().parseFoldExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004571 }
4572 case 'a':
4573 switch (First[1]) {
4574 case 'a':
4575 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004576 return getDerived().parseBinaryExpr("&&");
Richard Smithc20d1442018-08-20 20:14:49 +00004577 case 'd':
4578 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004579 return getDerived().parsePrefixExpr("&");
Richard Smithc20d1442018-08-20 20:14:49 +00004580 case 'n':
4581 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004582 return getDerived().parseBinaryExpr("&");
Richard Smithc20d1442018-08-20 20:14:49 +00004583 case 'N':
4584 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004585 return getDerived().parseBinaryExpr("&=");
Richard Smithc20d1442018-08-20 20:14:49 +00004586 case 'S':
4587 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004588 return getDerived().parseBinaryExpr("=");
Richard Smithc20d1442018-08-20 20:14:49 +00004589 case 't': {
4590 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004591 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004592 if (Ty == nullptr)
4593 return nullptr;
4594 return make<EnclosingExpr>("alignof (", Ty, ")");
4595 }
4596 case 'z': {
4597 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004598 Node *Ty = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004599 if (Ty == nullptr)
4600 return nullptr;
4601 return make<EnclosingExpr>("alignof (", Ty, ")");
4602 }
4603 }
4604 return nullptr;
4605 case 'c':
4606 switch (First[1]) {
4607 // cc <type> <expression> # const_cast<type>(expression)
4608 case 'c': {
4609 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004610 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004611 if (Ty == nullptr)
4612 return Ty;
Pavel Labathba825192018-10-16 14:29:14 +00004613 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004614 if (Ex == nullptr)
4615 return Ex;
4616 return make<CastExpr>("const_cast", Ty, Ex);
4617 }
4618 // cl <expression>+ E # call
4619 case 'l': {
4620 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004621 Node *Callee = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004622 if (Callee == nullptr)
4623 return Callee;
4624 size_t ExprsBegin = Names.size();
4625 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004626 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004627 if (E == nullptr)
4628 return E;
4629 Names.push_back(E);
4630 }
4631 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin));
4632 }
4633 case 'm':
4634 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004635 return getDerived().parseBinaryExpr(",");
Richard Smithc20d1442018-08-20 20:14:49 +00004636 case 'o':
4637 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004638 return getDerived().parsePrefixExpr("~");
Richard Smithc20d1442018-08-20 20:14:49 +00004639 case 'v':
Pavel Labathba825192018-10-16 14:29:14 +00004640 return getDerived().parseConversionExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004641 }
4642 return nullptr;
4643 case 'd':
4644 switch (First[1]) {
4645 case 'a': {
4646 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004647 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004648 if (Ex == nullptr)
4649 return Ex;
4650 return make<DeleteExpr>(Ex, Global, /*is_array=*/true);
4651 }
4652 case 'c': {
4653 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004654 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004655 if (T == nullptr)
4656 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004657 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004658 if (Ex == nullptr)
4659 return Ex;
4660 return make<CastExpr>("dynamic_cast", T, Ex);
4661 }
4662 case 'e':
4663 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004664 return getDerived().parsePrefixExpr("*");
Richard Smithc20d1442018-08-20 20:14:49 +00004665 case 'l': {
4666 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004667 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004668 if (E == nullptr)
4669 return E;
4670 return make<DeleteExpr>(E, Global, /*is_array=*/false);
4671 }
4672 case 'n':
Pavel Labathba825192018-10-16 14:29:14 +00004673 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004674 case 's': {
4675 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004676 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004677 if (LHS == nullptr)
4678 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004679 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004680 if (RHS == nullptr)
4681 return nullptr;
4682 return make<MemberExpr>(LHS, ".*", RHS);
4683 }
4684 case 't': {
4685 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004686 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004687 if (LHS == nullptr)
4688 return LHS;
Pavel Labathba825192018-10-16 14:29:14 +00004689 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004690 if (RHS == nullptr)
4691 return nullptr;
4692 return make<MemberExpr>(LHS, ".", RHS);
4693 }
4694 case 'v':
4695 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004696 return getDerived().parseBinaryExpr("/");
Richard Smithc20d1442018-08-20 20:14:49 +00004697 case 'V':
4698 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004699 return getDerived().parseBinaryExpr("/=");
Richard Smithc20d1442018-08-20 20:14:49 +00004700 }
4701 return nullptr;
4702 case 'e':
4703 switch (First[1]) {
4704 case 'o':
4705 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004706 return getDerived().parseBinaryExpr("^");
Richard Smithc20d1442018-08-20 20:14:49 +00004707 case 'O':
4708 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004709 return getDerived().parseBinaryExpr("^=");
Richard Smithc20d1442018-08-20 20:14:49 +00004710 case 'q':
4711 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004712 return getDerived().parseBinaryExpr("==");
Richard Smithc20d1442018-08-20 20:14:49 +00004713 }
4714 return nullptr;
4715 case 'g':
4716 switch (First[1]) {
4717 case 'e':
4718 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004719 return getDerived().parseBinaryExpr(">=");
Richard Smithc20d1442018-08-20 20:14:49 +00004720 case 't':
4721 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004722 return getDerived().parseBinaryExpr(">");
Richard Smithc20d1442018-08-20 20:14:49 +00004723 }
4724 return nullptr;
4725 case 'i':
4726 switch (First[1]) {
4727 case 'x': {
4728 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004729 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004730 if (Base == nullptr)
4731 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004732 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004733 if (Index == nullptr)
4734 return Index;
4735 return make<ArraySubscriptExpr>(Base, Index);
4736 }
4737 case 'l': {
4738 First += 2;
4739 size_t InitsBegin = Names.size();
4740 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004741 Node *E = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004742 if (E == nullptr)
4743 return nullptr;
4744 Names.push_back(E);
4745 }
4746 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4747 }
4748 }
4749 return nullptr;
4750 case 'l':
4751 switch (First[1]) {
4752 case 'e':
4753 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004754 return getDerived().parseBinaryExpr("<=");
Richard Smithc20d1442018-08-20 20:14:49 +00004755 case 's':
4756 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004757 return getDerived().parseBinaryExpr("<<");
Richard Smithc20d1442018-08-20 20:14:49 +00004758 case 'S':
4759 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004760 return getDerived().parseBinaryExpr("<<=");
Richard Smithc20d1442018-08-20 20:14:49 +00004761 case 't':
4762 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004763 return getDerived().parseBinaryExpr("<");
Richard Smithc20d1442018-08-20 20:14:49 +00004764 }
4765 return nullptr;
4766 case 'm':
4767 switch (First[1]) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004768 case 'c':
4769 First += 2;
4770 return parsePointerToMemberConversionExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004771 case 'i':
4772 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004773 return getDerived().parseBinaryExpr("-");
Richard Smithc20d1442018-08-20 20:14:49 +00004774 case 'I':
4775 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004776 return getDerived().parseBinaryExpr("-=");
Richard Smithc20d1442018-08-20 20:14:49 +00004777 case 'l':
4778 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004779 return getDerived().parseBinaryExpr("*");
Richard Smithc20d1442018-08-20 20:14:49 +00004780 case 'L':
4781 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004782 return getDerived().parseBinaryExpr("*=");
Richard Smithc20d1442018-08-20 20:14:49 +00004783 case 'm':
4784 First += 2;
4785 if (consumeIf('_'))
Pavel Labathba825192018-10-16 14:29:14 +00004786 return getDerived().parsePrefixExpr("--");
4787 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004788 if (Ex == nullptr)
4789 return nullptr;
4790 return make<PostfixExpr>(Ex, "--");
4791 }
4792 return nullptr;
4793 case 'n':
4794 switch (First[1]) {
4795 case 'a':
4796 case 'w':
Pavel Labathba825192018-10-16 14:29:14 +00004797 return getDerived().parseNewExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004798 case 'e':
4799 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004800 return getDerived().parseBinaryExpr("!=");
Richard Smithc20d1442018-08-20 20:14:49 +00004801 case 'g':
4802 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004803 return getDerived().parsePrefixExpr("-");
Richard Smithc20d1442018-08-20 20:14:49 +00004804 case 't':
4805 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004806 return getDerived().parsePrefixExpr("!");
Richard Smithc20d1442018-08-20 20:14:49 +00004807 case 'x':
4808 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004809 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004810 if (Ex == nullptr)
4811 return Ex;
4812 return make<EnclosingExpr>("noexcept (", Ex, ")");
4813 }
4814 return nullptr;
4815 case 'o':
4816 switch (First[1]) {
4817 case 'n':
Pavel Labathba825192018-10-16 14:29:14 +00004818 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004819 case 'o':
4820 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004821 return getDerived().parseBinaryExpr("||");
Richard Smithc20d1442018-08-20 20:14:49 +00004822 case 'r':
4823 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004824 return getDerived().parseBinaryExpr("|");
Richard Smithc20d1442018-08-20 20:14:49 +00004825 case 'R':
4826 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004827 return getDerived().parseBinaryExpr("|=");
Richard Smithc20d1442018-08-20 20:14:49 +00004828 }
4829 return nullptr;
4830 case 'p':
4831 switch (First[1]) {
4832 case 'm':
4833 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004834 return getDerived().parseBinaryExpr("->*");
Richard Smithc20d1442018-08-20 20:14:49 +00004835 case 'l':
4836 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004837 return getDerived().parseBinaryExpr("+");
Richard Smithc20d1442018-08-20 20:14:49 +00004838 case 'L':
4839 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004840 return getDerived().parseBinaryExpr("+=");
Richard Smithc20d1442018-08-20 20:14:49 +00004841 case 'p': {
4842 First += 2;
4843 if (consumeIf('_'))
Pavel Labathba825192018-10-16 14:29:14 +00004844 return getDerived().parsePrefixExpr("++");
4845 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004846 if (Ex == nullptr)
4847 return Ex;
4848 return make<PostfixExpr>(Ex, "++");
4849 }
4850 case 's':
4851 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004852 return getDerived().parsePrefixExpr("+");
Richard Smithc20d1442018-08-20 20:14:49 +00004853 case 't': {
4854 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004855 Node *L = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004856 if (L == nullptr)
4857 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004858 Node *R = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004859 if (R == nullptr)
4860 return nullptr;
4861 return make<MemberExpr>(L, "->", R);
4862 }
4863 }
4864 return nullptr;
4865 case 'q':
4866 if (First[1] == 'u') {
4867 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004868 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004869 if (Cond == nullptr)
4870 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004871 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004872 if (LHS == nullptr)
4873 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004874 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004875 if (RHS == nullptr)
4876 return nullptr;
4877 return make<ConditionalExpr>(Cond, LHS, RHS);
4878 }
4879 return nullptr;
4880 case 'r':
4881 switch (First[1]) {
4882 case 'c': {
4883 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004884 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004885 if (T == nullptr)
4886 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004887 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004888 if (Ex == nullptr)
4889 return Ex;
4890 return make<CastExpr>("reinterpret_cast", T, Ex);
4891 }
4892 case 'm':
4893 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004894 return getDerived().parseBinaryExpr("%");
Richard Smithc20d1442018-08-20 20:14:49 +00004895 case 'M':
4896 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004897 return getDerived().parseBinaryExpr("%=");
Richard Smithc20d1442018-08-20 20:14:49 +00004898 case 's':
4899 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004900 return getDerived().parseBinaryExpr(">>");
Richard Smithc20d1442018-08-20 20:14:49 +00004901 case 'S':
4902 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004903 return getDerived().parseBinaryExpr(">>=");
Richard Smithc20d1442018-08-20 20:14:49 +00004904 }
4905 return nullptr;
4906 case 's':
4907 switch (First[1]) {
4908 case 'c': {
4909 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004910 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004911 if (T == nullptr)
4912 return T;
Pavel Labathba825192018-10-16 14:29:14 +00004913 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004914 if (Ex == nullptr)
4915 return Ex;
4916 return make<CastExpr>("static_cast", T, Ex);
4917 }
Richard Smith1865d2f2020-10-22 19:29:36 -07004918 case 'o':
4919 First += 2;
4920 return parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004921 case 'p': {
4922 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004923 Node *Child = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004924 if (Child == nullptr)
4925 return nullptr;
4926 return make<ParameterPackExpansion>(Child);
4927 }
4928 case 'r':
Pavel Labathba825192018-10-16 14:29:14 +00004929 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00004930 case 't': {
4931 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004932 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004933 if (Ty == nullptr)
4934 return Ty;
4935 return make<EnclosingExpr>("sizeof (", Ty, ")");
4936 }
4937 case 'z': {
4938 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004939 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004940 if (Ex == nullptr)
4941 return Ex;
4942 return make<EnclosingExpr>("sizeof (", Ex, ")");
4943 }
4944 case 'Z':
4945 First += 2;
4946 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00004947 Node *R = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004948 if (R == nullptr)
4949 return nullptr;
4950 return make<SizeofParamPackExpr>(R);
4951 } else if (look() == 'f') {
Pavel Labathba825192018-10-16 14:29:14 +00004952 Node *FP = getDerived().parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004953 if (FP == nullptr)
4954 return nullptr;
4955 return make<EnclosingExpr>("sizeof... (", FP, ")");
4956 }
4957 return nullptr;
4958 case 'P': {
4959 First += 2;
4960 size_t ArgsBegin = Names.size();
4961 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004962 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00004963 if (Arg == nullptr)
4964 return nullptr;
4965 Names.push_back(Arg);
4966 }
Richard Smithb485b352018-08-24 23:30:26 +00004967 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4968 if (!Pack)
4969 return nullptr;
4970 return make<EnclosingExpr>("sizeof... (", Pack, ")");
Richard Smithc20d1442018-08-20 20:14:49 +00004971 }
4972 }
4973 return nullptr;
4974 case 't':
4975 switch (First[1]) {
4976 case 'e': {
4977 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004978 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004979 if (Ex == nullptr)
4980 return Ex;
4981 return make<EnclosingExpr>("typeid (", Ex, ")");
4982 }
4983 case 'i': {
4984 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004985 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004986 if (Ty == nullptr)
4987 return Ty;
4988 return make<EnclosingExpr>("typeid (", Ty, ")");
4989 }
4990 case 'l': {
4991 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004992 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004993 if (Ty == nullptr)
4994 return nullptr;
4995 size_t InitsBegin = Names.size();
4996 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004997 Node *E = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004998 if (E == nullptr)
4999 return nullptr;
5000 Names.push_back(E);
5001 }
5002 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
5003 }
5004 case 'r':
5005 First += 2;
5006 return make<NameType>("throw");
5007 case 'w': {
5008 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005009 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005010 if (Ex == nullptr)
5011 return nullptr;
5012 return make<ThrowExpr>(Ex);
5013 }
5014 }
5015 return nullptr;
5016 case '1':
5017 case '2':
5018 case '3':
5019 case '4':
5020 case '5':
5021 case '6':
5022 case '7':
5023 case '8':
5024 case '9':
Pavel Labathba825192018-10-16 14:29:14 +00005025 return getDerived().parseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00005026 }
Erik Pilkingtone8457c62019-06-18 23:34:09 +00005027
5028 if (consumeIf("u8__uuidoft")) {
5029 Node *Ty = getDerived().parseType();
5030 if (!Ty)
5031 return nullptr;
5032 return make<UUIDOfExpr>(Ty);
5033 }
5034
5035 if (consumeIf("u8__uuidofz")) {
5036 Node *Ex = getDerived().parseExpr();
5037 if (!Ex)
5038 return nullptr;
5039 return make<UUIDOfExpr>(Ex);
5040 }
5041
Richard Smithc20d1442018-08-20 20:14:49 +00005042 return nullptr;
5043}
5044
5045// <call-offset> ::= h <nv-offset> _
5046// ::= v <v-offset> _
5047//
5048// <nv-offset> ::= <offset number>
5049// # non-virtual base override
5050//
5051// <v-offset> ::= <offset number> _ <virtual offset number>
5052// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00005053template <typename Alloc, typename Derived>
5054bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00005055 // Just scan through the call offset, we never add this information into the
5056 // output.
5057 if (consumeIf('h'))
5058 return parseNumber(true).empty() || !consumeIf('_');
5059 if (consumeIf('v'))
5060 return parseNumber(true).empty() || !consumeIf('_') ||
5061 parseNumber(true).empty() || !consumeIf('_');
5062 return true;
5063}
5064
5065// <special-name> ::= TV <type> # virtual table
5066// ::= TT <type> # VTT structure (construction vtable index)
5067// ::= TI <type> # typeinfo structure
5068// ::= TS <type> # typeinfo name (null-terminated byte string)
5069// ::= Tc <call-offset> <call-offset> <base encoding>
5070// # base is the nominal target function of thunk
5071// # first call-offset is 'this' adjustment
5072// # second call-offset is result adjustment
5073// ::= T <call-offset> <base encoding>
5074// # base is the nominal target function of thunk
5075// ::= GV <object name> # Guard variable for one-time initialization
5076// # No <type>
5077// ::= TW <object name> # Thread-local wrapper
5078// ::= TH <object name> # Thread-local initialization
5079// ::= GR <object name> _ # First temporary
5080// ::= GR <object name> <seq-id> _ # Subsequent temporaries
5081// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first
5082// extension ::= GR <object name> # reference temporary for object
Pavel Labathba825192018-10-16 14:29:14 +00005083template <typename Derived, typename Alloc>
5084Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00005085 switch (look()) {
5086 case 'T':
5087 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07005088 // TA <template-arg> # template parameter object
5089 //
5090 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
5091 case 'A': {
5092 First += 2;
5093 Node *Arg = getDerived().parseTemplateArg();
5094 if (Arg == nullptr)
5095 return nullptr;
5096 return make<SpecialName>("template parameter object for ", Arg);
5097 }
Richard Smithc20d1442018-08-20 20:14:49 +00005098 // TV <type> # virtual table
5099 case 'V': {
5100 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005101 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005102 if (Ty == nullptr)
5103 return nullptr;
5104 return make<SpecialName>("vtable for ", Ty);
5105 }
5106 // TT <type> # VTT structure (construction vtable index)
5107 case 'T': {
5108 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005109 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005110 if (Ty == nullptr)
5111 return nullptr;
5112 return make<SpecialName>("VTT for ", Ty);
5113 }
5114 // TI <type> # typeinfo structure
5115 case 'I': {
5116 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005117 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005118 if (Ty == nullptr)
5119 return nullptr;
5120 return make<SpecialName>("typeinfo for ", Ty);
5121 }
5122 // TS <type> # typeinfo name (null-terminated byte string)
5123 case 'S': {
5124 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005125 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005126 if (Ty == nullptr)
5127 return nullptr;
5128 return make<SpecialName>("typeinfo name for ", Ty);
5129 }
5130 // Tc <call-offset> <call-offset> <base encoding>
5131 case 'c': {
5132 First += 2;
5133 if (parseCallOffset() || parseCallOffset())
5134 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00005135 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005136 if (Encoding == nullptr)
5137 return nullptr;
5138 return make<SpecialName>("covariant return thunk to ", Encoding);
5139 }
5140 // extension ::= TC <first type> <number> _ <second type>
5141 // # construction vtable for second-in-first
5142 case 'C': {
5143 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005144 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005145 if (FirstType == nullptr)
5146 return nullptr;
5147 if (parseNumber(true).empty() || !consumeIf('_'))
5148 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00005149 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005150 if (SecondType == nullptr)
5151 return nullptr;
5152 return make<CtorVtableSpecialName>(SecondType, FirstType);
5153 }
5154 // TW <object name> # Thread-local wrapper
5155 case 'W': {
5156 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005157 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005158 if (Name == nullptr)
5159 return nullptr;
5160 return make<SpecialName>("thread-local wrapper routine for ", Name);
5161 }
5162 // TH <object name> # Thread-local initialization
5163 case 'H': {
5164 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005165 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005166 if (Name == nullptr)
5167 return nullptr;
5168 return make<SpecialName>("thread-local initialization routine for ", Name);
5169 }
5170 // T <call-offset> <base encoding>
5171 default: {
5172 ++First;
5173 bool IsVirt = look() == 'v';
5174 if (parseCallOffset())
5175 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00005176 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005177 if (BaseEncoding == nullptr)
5178 return nullptr;
5179 if (IsVirt)
5180 return make<SpecialName>("virtual thunk to ", BaseEncoding);
5181 else
5182 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
5183 }
5184 }
5185 case 'G':
5186 switch (look(1)) {
5187 // GV <object name> # Guard variable for one-time initialization
5188 case 'V': {
5189 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005190 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005191 if (Name == nullptr)
5192 return nullptr;
5193 return make<SpecialName>("guard variable for ", Name);
5194 }
5195 // GR <object name> # reference temporary for object
5196 // GR <object name> _ # First temporary
5197 // GR <object name> <seq-id> _ # Subsequent temporaries
5198 case 'R': {
5199 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005200 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005201 if (Name == nullptr)
5202 return nullptr;
5203 size_t Count;
5204 bool ParsedSeqId = !parseSeqId(&Count);
5205 if (!consumeIf('_') && ParsedSeqId)
5206 return nullptr;
5207 return make<SpecialName>("reference temporary for ", Name);
5208 }
5209 }
5210 }
5211 return nullptr;
5212}
5213
5214// <encoding> ::= <function name> <bare-function-type>
5215// ::= <data name>
5216// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005217template <typename Derived, typename Alloc>
5218Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005219 // The template parameters of an encoding are unrelated to those of the
5220 // enclosing context.
5221 class SaveTemplateParams {
5222 AbstractManglingParser *Parser;
5223 decltype(TemplateParams) OldParams;
5224
5225 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005226 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005227 OldParams = std::move(Parser->TemplateParams);
5228 Parser->TemplateParams.clear();
5229 }
5230 ~SaveTemplateParams() {
5231 Parser->TemplateParams = std::move(OldParams);
5232 }
5233 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005234
Richard Smithc20d1442018-08-20 20:14:49 +00005235 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005236 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005237
5238 auto IsEndOfEncoding = [&] {
5239 // The set of chars that can potentially follow an <encoding> (none of which
5240 // can start a <type>). Enumerating these allows us to avoid speculative
5241 // parsing.
5242 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5243 };
5244
5245 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005246 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005247 if (Name == nullptr)
5248 return nullptr;
5249
5250 if (resolveForwardTemplateRefs(NameInfo))
5251 return nullptr;
5252
5253 if (IsEndOfEncoding())
5254 return Name;
5255
5256 Node *Attrs = nullptr;
5257 if (consumeIf("Ua9enable_ifI")) {
5258 size_t BeforeArgs = Names.size();
5259 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005260 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005261 if (Arg == nullptr)
5262 return nullptr;
5263 Names.push_back(Arg);
5264 }
5265 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005266 if (!Attrs)
5267 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005268 }
5269
5270 Node *ReturnType = nullptr;
5271 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005272 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005273 if (ReturnType == nullptr)
5274 return nullptr;
5275 }
5276
5277 if (consumeIf('v'))
5278 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5279 Attrs, NameInfo.CVQualifiers,
5280 NameInfo.ReferenceQualifier);
5281
5282 size_t ParamsBegin = Names.size();
5283 do {
Pavel Labathba825192018-10-16 14:29:14 +00005284 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005285 if (Ty == nullptr)
5286 return nullptr;
5287 Names.push_back(Ty);
5288 } while (!IsEndOfEncoding());
5289
5290 return make<FunctionEncoding>(ReturnType, Name,
5291 popTrailingNodeArray(ParamsBegin),
5292 Attrs, NameInfo.CVQualifiers,
5293 NameInfo.ReferenceQualifier);
5294}
5295
5296template <class Float>
5297struct FloatData;
5298
5299template <>
5300struct FloatData<float>
5301{
5302 static const size_t mangled_size = 8;
5303 static const size_t max_demangled_size = 24;
5304 static constexpr const char* spec = "%af";
5305};
5306
5307template <>
5308struct FloatData<double>
5309{
5310 static const size_t mangled_size = 16;
5311 static const size_t max_demangled_size = 32;
5312 static constexpr const char* spec = "%a";
5313};
5314
5315template <>
5316struct FloatData<long double>
5317{
5318#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5319 defined(__wasm__)
5320 static const size_t mangled_size = 32;
5321#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5322 static const size_t mangled_size = 16;
5323#else
5324 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5325#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005326 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5327 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5328 // Negatives are one character longer than positives.
5329 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5330 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5331 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005332 static constexpr const char *spec = "%LaL";
5333};
5334
Pavel Labathba825192018-10-16 14:29:14 +00005335template <typename Alloc, typename Derived>
5336template <class Float>
5337Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005338 const size_t N = FloatData<Float>::mangled_size;
5339 if (numLeft() <= N)
5340 return nullptr;
5341 StringView Data(First, First + N);
5342 for (char C : Data)
5343 if (!std::isxdigit(C))
5344 return nullptr;
5345 First += N;
5346 if (!consumeIf('E'))
5347 return nullptr;
5348 return make<FloatLiteralImpl<Float>>(Data);
5349}
5350
5351// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005352template <typename Alloc, typename Derived>
5353bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005354 if (!(look() >= '0' && look() <= '9') &&
5355 !(look() >= 'A' && look() <= 'Z'))
5356 return true;
5357
5358 size_t Id = 0;
5359 while (true) {
5360 if (look() >= '0' && look() <= '9') {
5361 Id *= 36;
5362 Id += static_cast<size_t>(look() - '0');
5363 } else if (look() >= 'A' && look() <= 'Z') {
5364 Id *= 36;
5365 Id += static_cast<size_t>(look() - 'A') + 10;
5366 } else {
5367 *Out = Id;
5368 return false;
5369 }
5370 ++First;
5371 }
5372}
5373
5374// <substitution> ::= S <seq-id> _
5375// ::= S_
5376// <substitution> ::= Sa # ::std::allocator
5377// <substitution> ::= Sb # ::std::basic_string
5378// <substitution> ::= Ss # ::std::basic_string < char,
5379// ::std::char_traits<char>,
5380// ::std::allocator<char> >
5381// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5382// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5383// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Pavel Labathba825192018-10-16 14:29:14 +00005384template <typename Derived, typename Alloc>
5385Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005386 if (!consumeIf('S'))
5387 return nullptr;
5388
5389 if (std::islower(look())) {
5390 Node *SpecialSub;
5391 switch (look()) {
5392 case 'a':
5393 ++First;
5394 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::allocator);
5395 break;
5396 case 'b':
5397 ++First;
5398 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::basic_string);
5399 break;
5400 case 's':
5401 ++First;
5402 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::string);
5403 break;
5404 case 'i':
5405 ++First;
5406 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::istream);
5407 break;
5408 case 'o':
5409 ++First;
5410 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::ostream);
5411 break;
5412 case 'd':
5413 ++First;
5414 SpecialSub = make<SpecialSubstitution>(SpecialSubKind::iostream);
5415 break;
5416 default:
5417 return nullptr;
5418 }
Richard Smithb485b352018-08-24 23:30:26 +00005419 if (!SpecialSub)
5420 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005421 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5422 // has ABI tags, the tags are appended to the substitution; the result is a
5423 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005424 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005425 if (WithTags != SpecialSub) {
5426 Subs.push_back(WithTags);
5427 SpecialSub = WithTags;
5428 }
5429 return SpecialSub;
5430 }
5431
5432 // ::= S_
5433 if (consumeIf('_')) {
5434 if (Subs.empty())
5435 return nullptr;
5436 return Subs[0];
5437 }
5438
5439 // ::= S <seq-id> _
5440 size_t Index = 0;
5441 if (parseSeqId(&Index))
5442 return nullptr;
5443 ++Index;
5444 if (!consumeIf('_') || Index >= Subs.size())
5445 return nullptr;
5446 return Subs[Index];
5447}
5448
5449// <template-param> ::= T_ # first template parameter
5450// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005451// ::= TL <level-1> __
5452// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005453template <typename Derived, typename Alloc>
5454Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005455 if (!consumeIf('T'))
5456 return nullptr;
5457
Richard Smithdf1c14c2019-09-06 23:53:21 +00005458 size_t Level = 0;
5459 if (consumeIf('L')) {
5460 if (parsePositiveInteger(&Level))
5461 return nullptr;
5462 ++Level;
5463 if (!consumeIf('_'))
5464 return nullptr;
5465 }
5466
Richard Smithc20d1442018-08-20 20:14:49 +00005467 size_t Index = 0;
5468 if (!consumeIf('_')) {
5469 if (parsePositiveInteger(&Index))
5470 return nullptr;
5471 ++Index;
5472 if (!consumeIf('_'))
5473 return nullptr;
5474 }
5475
Richard Smithc20d1442018-08-20 20:14:49 +00005476 // If we're in a context where this <template-param> refers to a
5477 // <template-arg> further ahead in the mangled name (currently just conversion
5478 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005479 // This can only happen at the outermost level.
5480 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005481 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5482 if (!ForwardRef)
5483 return nullptr;
5484 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5485 ForwardTemplateRefs.push_back(
5486 static_cast<ForwardTemplateReference *>(ForwardRef));
5487 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005488 }
5489
Richard Smithdf1c14c2019-09-06 23:53:21 +00005490 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5491 Index >= TemplateParams[Level]->size()) {
5492 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5493 // list are mangled as the corresponding artificial template type parameter.
5494 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5495 // This will be popped by the ScopedTemplateParamList in
5496 // parseUnnamedTypeName.
5497 if (Level == TemplateParams.size())
5498 TemplateParams.push_back(nullptr);
5499 return make<NameType>("auto");
5500 }
5501
Richard Smithc20d1442018-08-20 20:14:49 +00005502 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005503 }
5504
5505 return (*TemplateParams[Level])[Index];
5506}
5507
5508// <template-param-decl> ::= Ty # type parameter
5509// ::= Tn <type> # non-type parameter
5510// ::= Tt <template-param-decl>* E # template parameter
5511// ::= Tp <template-param-decl> # parameter pack
5512template <typename Derived, typename Alloc>
5513Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5514 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5515 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5516 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5517 if (N) TemplateParams.back()->push_back(N);
5518 return N;
5519 };
5520
5521 if (consumeIf("Ty")) {
5522 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5523 if (!Name)
5524 return nullptr;
5525 return make<TypeTemplateParamDecl>(Name);
5526 }
5527
5528 if (consumeIf("Tn")) {
5529 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5530 if (!Name)
5531 return nullptr;
5532 Node *Type = parseType();
5533 if (!Type)
5534 return nullptr;
5535 return make<NonTypeTemplateParamDecl>(Name, Type);
5536 }
5537
5538 if (consumeIf("Tt")) {
5539 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5540 if (!Name)
5541 return nullptr;
5542 size_t ParamsBegin = Names.size();
5543 ScopedTemplateParamList TemplateTemplateParamParams(this);
5544 while (!consumeIf("E")) {
5545 Node *P = parseTemplateParamDecl();
5546 if (!P)
5547 return nullptr;
5548 Names.push_back(P);
5549 }
5550 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5551 return make<TemplateTemplateParamDecl>(Name, Params);
5552 }
5553
5554 if (consumeIf("Tp")) {
5555 Node *P = parseTemplateParamDecl();
5556 if (!P)
5557 return nullptr;
5558 return make<TemplateParamPackDecl>(P);
5559 }
5560
5561 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005562}
5563
5564// <template-arg> ::= <type> # type or template
5565// ::= X <expression> E # expression
5566// ::= <expr-primary> # simple expressions
5567// ::= J <template-arg>* E # argument pack
5568// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005569template <typename Derived, typename Alloc>
5570Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005571 switch (look()) {
5572 case 'X': {
5573 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005574 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005575 if (Arg == nullptr || !consumeIf('E'))
5576 return nullptr;
5577 return Arg;
5578 }
5579 case 'J': {
5580 ++First;
5581 size_t ArgsBegin = Names.size();
5582 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005583 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005584 if (Arg == nullptr)
5585 return nullptr;
5586 Names.push_back(Arg);
5587 }
5588 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5589 return make<TemplateArgumentPack>(Args);
5590 }
5591 case 'L': {
5592 // ::= LZ <encoding> E # extension
5593 if (look(1) == 'Z') {
5594 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005595 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005596 if (Arg == nullptr || !consumeIf('E'))
5597 return nullptr;
5598 return Arg;
5599 }
5600 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005601 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005602 }
5603 default:
Pavel Labathba825192018-10-16 14:29:14 +00005604 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005605 }
5606}
5607
5608// <template-args> ::= I <template-arg>* E
5609// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005610template <typename Derived, typename Alloc>
5611Node *
5612AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005613 if (!consumeIf('I'))
5614 return nullptr;
5615
5616 // <template-params> refer to the innermost <template-args>. Clear out any
5617 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005618 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005619 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005620 TemplateParams.push_back(&OuterTemplateParams);
5621 OuterTemplateParams.clear();
5622 }
Richard Smithc20d1442018-08-20 20:14:49 +00005623
5624 size_t ArgsBegin = Names.size();
5625 while (!consumeIf('E')) {
5626 if (TagTemplates) {
5627 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005628 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005629 TemplateParams = std::move(OldParams);
5630 if (Arg == nullptr)
5631 return nullptr;
5632 Names.push_back(Arg);
5633 Node *TableEntry = Arg;
5634 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5635 TableEntry = make<ParameterPack>(
5636 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005637 if (!TableEntry)
5638 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005639 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005640 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005641 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005642 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005643 if (Arg == nullptr)
5644 return nullptr;
5645 Names.push_back(Arg);
5646 }
5647 }
5648 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5649}
5650
5651// <mangled-name> ::= _Z <encoding>
5652// ::= <type>
5653// extension ::= ___Z <encoding> _block_invoke
5654// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5655// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005656template <typename Derived, typename Alloc>
5657Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005658 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005659 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005660 if (Encoding == nullptr)
5661 return nullptr;
5662 if (look() == '.') {
5663 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5664 First = Last;
5665 }
5666 if (numLeft() != 0)
5667 return nullptr;
5668 return Encoding;
5669 }
5670
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005671 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005672 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005673 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5674 return nullptr;
5675 bool RequireNumber = consumeIf('_');
5676 if (parseNumber().empty() && RequireNumber)
5677 return nullptr;
5678 if (look() == '.')
5679 First = Last;
5680 if (numLeft() != 0)
5681 return nullptr;
5682 return make<SpecialName>("invocation function for block in ", Encoding);
5683 }
5684
Pavel Labathba825192018-10-16 14:29:14 +00005685 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005686 if (numLeft() != 0)
5687 return nullptr;
5688 return Ty;
5689}
5690
Pavel Labathba825192018-10-16 14:29:14 +00005691template <typename Alloc>
5692struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5693 using AbstractManglingParser<ManglingParser<Alloc>,
5694 Alloc>::AbstractManglingParser;
5695};
5696
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005697DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005698
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005699#endif // DEMANGLE_ITANIUMDEMANGLE_H