blob: a434868ce1a52c5cccb2db99f3da78fa0da9931e [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//
Nathan Sidwell5b0a8cf2022-01-24 06:38:47 -08009// Generic itanium demangler library.
10// There are two copies of this file in the source tree. The one under
11// libcxxabi is the original and the one under llvm is the copy. Use
12// cp-to-llvm.sh to update the copy. See README.txt for more details.
Richard Smithc20d1442018-08-20 20:14:49 +000013//
14//===----------------------------------------------------------------------===//
15
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000016#ifndef DEMANGLE_ITANIUMDEMANGLE_H
17#define DEMANGLE_ITANIUMDEMANGLE_H
Richard Smithc20d1442018-08-20 20:14:49 +000018
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000019#include "DemangleConfig.h"
Richard Smithc20d1442018-08-20 20:14:49 +000020#include "StringView.h"
21#include "Utility.h"
Nathan Sidwellbbc632f2022-01-24 04:11:59 -080022#include <algorithm>
Richard Smithc20d1442018-08-20 20:14:49 +000023#include <cassert>
24#include <cctype>
25#include <cstdio>
26#include <cstdlib>
27#include <cstring>
Nathan Sidwellbbc632f2022-01-24 04:11:59 -080028#include <limits>
Richard Smithc20d1442018-08-20 20:14:49 +000029#include <utility>
30
Nathan Sidwellf19ccea2022-02-18 04:05:06 -080031#define FOR_EACH_NODE_KIND(X) \
32 X(NodeArrayNode) \
33 X(DotSuffix) \
34 X(VendorExtQualType) \
35 X(QualType) \
36 X(ConversionOperatorType) \
37 X(PostfixQualifiedType) \
38 X(ElaboratedTypeSpefType) \
39 X(NameType) \
40 X(AbiTagAttr) \
41 X(EnableIfAttr) \
42 X(ObjCProtoName) \
43 X(PointerType) \
44 X(ReferenceType) \
45 X(PointerToMemberType) \
46 X(ArrayType) \
47 X(FunctionType) \
48 X(NoexceptSpec) \
49 X(DynamicExceptionSpec) \
50 X(FunctionEncoding) \
51 X(LiteralOperator) \
52 X(SpecialName) \
53 X(CtorVtableSpecialName) \
54 X(QualifiedName) \
55 X(NestedName) \
56 X(LocalName) \
Nathan Sidwelledde7bb2022-01-26 07:22:04 -080057 X(ModuleName) \
58 X(ModuleEntity) \
Nathan Sidwellf19ccea2022-02-18 04:05:06 -080059 X(VectorType) \
60 X(PixelVectorType) \
61 X(BinaryFPType) \
62 X(SyntheticTemplateParamName) \
63 X(TypeTemplateParamDecl) \
64 X(NonTypeTemplateParamDecl) \
65 X(TemplateTemplateParamDecl) \
66 X(TemplateParamPackDecl) \
67 X(ParameterPack) \
68 X(TemplateArgumentPack) \
69 X(ParameterPackExpansion) \
70 X(TemplateArgs) \
71 X(ForwardTemplateReference) \
72 X(NameWithTemplateArgs) \
73 X(GlobalQualifiedName) \
74 X(ExpandedSpecialSubstitution) \
75 X(SpecialSubstitution) \
76 X(CtorDtorName) \
77 X(DtorName) \
78 X(UnnamedTypeName) \
79 X(ClosureTypeName) \
80 X(StructuredBindingName) \
81 X(BinaryExpr) \
82 X(ArraySubscriptExpr) \
83 X(PostfixExpr) \
84 X(ConditionalExpr) \
85 X(MemberExpr) \
86 X(SubobjectExpr) \
87 X(EnclosingExpr) \
88 X(CastExpr) \
89 X(SizeofParamPackExpr) \
90 X(CallExpr) \
91 X(NewExpr) \
92 X(DeleteExpr) \
93 X(PrefixExpr) \
94 X(FunctionParam) \
95 X(ConversionExpr) \
96 X(PointerToMemberConversionExpr) \
97 X(InitListExpr) \
98 X(FoldExpr) \
99 X(ThrowExpr) \
100 X(BoolExpr) \
101 X(StringLiteral) \
102 X(LambdaExpr) \
103 X(EnumLiteral) \
104 X(IntegerLiteral) \
105 X(FloatLiteral) \
106 X(DoubleLiteral) \
107 X(LongDoubleLiteral) \
108 X(BracedExpr) \
109 X(BracedRangeExpr)
Richard Smithc20d1442018-08-20 20:14:49 +0000110
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000111DEMANGLE_NAMESPACE_BEGIN
112
Mikhail Borisov8452f062021-08-17 18:06:53 -0400113template <class T, size_t N> class PODSmallVector {
114 static_assert(std::is_pod<T>::value,
115 "T is required to be a plain old data type");
116
117 T *First = nullptr;
118 T *Last = nullptr;
119 T *Cap = nullptr;
120 T Inline[N] = {0};
121
122 bool isInline() const { return First == Inline; }
123
124 void clearInline() {
125 First = Inline;
126 Last = Inline;
127 Cap = Inline + N;
128 }
129
130 void reserve(size_t NewCap) {
131 size_t S = size();
132 if (isInline()) {
133 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
134 if (Tmp == nullptr)
135 std::terminate();
136 std::copy(First, Last, Tmp);
137 First = Tmp;
138 } else {
139 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
140 if (First == nullptr)
141 std::terminate();
142 }
143 Last = First + S;
144 Cap = First + NewCap;
145 }
146
147public:
148 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
149
150 PODSmallVector(const PODSmallVector &) = delete;
151 PODSmallVector &operator=(const PODSmallVector &) = delete;
152
153 PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {
154 if (Other.isInline()) {
155 std::copy(Other.begin(), Other.end(), First);
156 Last = First + Other.size();
157 Other.clear();
158 return;
159 }
160
161 First = Other.First;
162 Last = Other.Last;
163 Cap = Other.Cap;
164 Other.clearInline();
165 }
166
167 PODSmallVector &operator=(PODSmallVector &&Other) {
168 if (Other.isInline()) {
169 if (!isInline()) {
170 std::free(First);
171 clearInline();
172 }
173 std::copy(Other.begin(), Other.end(), First);
174 Last = First + Other.size();
175 Other.clear();
176 return *this;
177 }
178
179 if (isInline()) {
180 First = Other.First;
181 Last = Other.Last;
182 Cap = Other.Cap;
183 Other.clearInline();
184 return *this;
185 }
186
187 std::swap(First, Other.First);
188 std::swap(Last, Other.Last);
189 std::swap(Cap, Other.Cap);
190 Other.clear();
191 return *this;
192 }
193
194 // NOLINTNEXTLINE(readability-identifier-naming)
195 void push_back(const T &Elem) {
196 if (Last == Cap)
197 reserve(size() * 2);
198 *Last++ = Elem;
199 }
200
201 // NOLINTNEXTLINE(readability-identifier-naming)
202 void pop_back() {
203 assert(Last != First && "Popping empty vector!");
204 --Last;
205 }
206
207 void dropBack(size_t Index) {
208 assert(Index <= size() && "dropBack() can't expand!");
209 Last = First + Index;
210 }
211
212 T *begin() { return First; }
213 T *end() { return Last; }
214
215 bool empty() const { return First == Last; }
216 size_t size() const { return static_cast<size_t>(Last - First); }
217 T &back() {
218 assert(Last != First && "Calling back() on empty vector!");
219 return *(Last - 1);
220 }
221 T &operator[](size_t Index) {
222 assert(Index < size() && "Invalid access!");
223 return *(begin() + Index);
224 }
225 void clear() { Last = First; }
226
227 ~PODSmallVector() {
228 if (!isInline())
229 std::free(First);
230 }
231};
232
Richard Smithc20d1442018-08-20 20:14:49 +0000233// Base class of all AST nodes. The AST is built by the parser, then is
234// traversed by the printLeft/Right functions to produce a demangled string.
235class Node {
236public:
237 enum Kind : unsigned char {
238#define ENUMERATOR(NodeKind) K ## NodeKind,
239 FOR_EACH_NODE_KIND(ENUMERATOR)
240#undef ENUMERATOR
241 };
242
243 /// Three-way bool to track a cached value. Unknown is possible if this node
244 /// has an unexpanded parameter pack below it that may affect this cache.
245 enum class Cache : unsigned char { Yes, No, Unknown, };
246
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800247 /// Operator precedence for expression nodes. Used to determine required
248 /// parens in expression emission.
249 enum class Prec {
250 Primary,
251 Postfix,
252 Unary,
253 Cast,
254 PtrMem,
255 Multiplicative,
256 Additive,
257 Shift,
258 Spaceship,
259 Relational,
260 Equality,
261 And,
262 Xor,
263 Ior,
264 AndIf,
265 OrIf,
266 Conditional,
267 Assign,
268 Comma,
269 Default,
270 };
271
Richard Smithc20d1442018-08-20 20:14:49 +0000272private:
273 Kind K;
274
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800275 Prec Precedence : 6;
276
Richard Smithc20d1442018-08-20 20:14:49 +0000277 // FIXME: Make these protected.
278public:
279 /// Tracks if this node has a component on its right side, in which case we
280 /// need to call printRight.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800281 Cache RHSComponentCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000282
283 /// Track if this node is a (possibly qualified) array type. This can affect
284 /// how we format the output string.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800285 Cache ArrayCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000286
287 /// Track if this node is a (possibly qualified) function type. This can
288 /// affect how we format the output string.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800289 Cache FunctionCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000290
291public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800292 Node(Kind K_, Prec Precedence_ = Prec::Primary,
293 Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,
294 Cache FunctionCache_ = Cache::No)
295 : K(K_), Precedence(Precedence_), RHSComponentCache(RHSComponentCache_),
296 ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {}
297 Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_ = Cache::No,
298 Cache FunctionCache_ = Cache::No)
299 : Node(K_, Prec::Primary, RHSComponentCache_, ArrayCache_,
300 FunctionCache_) {}
Richard Smithc20d1442018-08-20 20:14:49 +0000301
302 /// Visit the most-derived object corresponding to this object.
303 template<typename Fn> void visit(Fn F) const;
304
305 // The following function is provided by all derived classes:
306 //
307 // Call F with arguments that, when passed to the constructor of this node,
308 // would construct an equivalent node.
309 //template<typename Fn> void match(Fn F) const;
310
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700311 bool hasRHSComponent(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000312 if (RHSComponentCache != Cache::Unknown)
313 return RHSComponentCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700314 return hasRHSComponentSlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000315 }
316
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700317 bool hasArray(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000318 if (ArrayCache != Cache::Unknown)
319 return ArrayCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700320 return hasArraySlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000321 }
322
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700323 bool hasFunction(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000324 if (FunctionCache != Cache::Unknown)
325 return FunctionCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700326 return hasFunctionSlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000327 }
328
329 Kind getKind() const { return K; }
330
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800331 Prec getPrecedence() const { return Precedence; }
332
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700333 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
334 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
335 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
Richard Smithc20d1442018-08-20 20:14:49 +0000336
337 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
338 // get at a node that actually represents some concrete syntax.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700339 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }
Richard Smithc20d1442018-08-20 20:14:49 +0000340
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800341 // Print this node as an expression operand, surrounding it in parentheses if
342 // its precedence is [Strictly] weaker than P.
343 void printAsOperand(OutputBuffer &OB, Prec P = Prec::Default,
344 bool StrictlyWorse = false) const {
345 bool Paren =
346 unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse);
347 if (Paren)
348 OB.printOpen();
349 print(OB);
350 if (Paren)
351 OB.printClose();
352 }
353
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700354 void print(OutputBuffer &OB) const {
355 printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000356 if (RHSComponentCache != Cache::No)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700357 printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000358 }
359
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -0800360 // Print the "left" side of this Node into OutputBuffer.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700361 virtual void printLeft(OutputBuffer &) const = 0;
Richard Smithc20d1442018-08-20 20:14:49 +0000362
363 // Print the "right". This distinction is necessary to represent C++ types
364 // that appear on the RHS of their subtype, such as arrays or functions.
365 // Since most types don't have such a component, provide a default
366 // implementation.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700367 virtual void printRight(OutputBuffer &) const {}
Richard Smithc20d1442018-08-20 20:14:49 +0000368
369 virtual StringView getBaseName() const { return StringView(); }
370
371 // Silence compiler warnings, this dtor will never be called.
372 virtual ~Node() = default;
373
374#ifndef NDEBUG
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000375 DEMANGLE_DUMP_METHOD void dump() const;
Richard Smithc20d1442018-08-20 20:14:49 +0000376#endif
377};
378
379class NodeArray {
380 Node **Elements;
381 size_t NumElements;
382
383public:
384 NodeArray() : Elements(nullptr), NumElements(0) {}
385 NodeArray(Node **Elements_, size_t NumElements_)
386 : Elements(Elements_), NumElements(NumElements_) {}
387
388 bool empty() const { return NumElements == 0; }
389 size_t size() const { return NumElements; }
390
391 Node **begin() const { return Elements; }
392 Node **end() const { return Elements + NumElements; }
393
394 Node *operator[](size_t Idx) const { return Elements[Idx]; }
395
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700396 void printWithComma(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000397 bool FirstElement = true;
398 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700399 size_t BeforeComma = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +0000400 if (!FirstElement)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700401 OB += ", ";
402 size_t AfterComma = OB.getCurrentPosition();
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800403 Elements[Idx]->printAsOperand(OB, Node::Prec::Comma);
Richard Smithc20d1442018-08-20 20:14:49 +0000404
405 // Elements[Idx] is an empty parameter pack expansion, we should erase the
406 // comma we just printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700407 if (AfterComma == OB.getCurrentPosition()) {
408 OB.setCurrentPosition(BeforeComma);
Richard Smithc20d1442018-08-20 20:14:49 +0000409 continue;
410 }
411
412 FirstElement = false;
413 }
414 }
415};
416
417struct NodeArrayNode : Node {
418 NodeArray Array;
419 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
420
421 template<typename Fn> void match(Fn F) const { F(Array); }
422
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700423 void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000424};
425
426class DotSuffix final : public Node {
427 const Node *Prefix;
428 const StringView Suffix;
429
430public:
431 DotSuffix(const Node *Prefix_, StringView Suffix_)
432 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
433
434 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
435
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700436 void printLeft(OutputBuffer &OB) const override {
437 Prefix->print(OB);
438 OB += " (";
439 OB += Suffix;
440 OB += ")";
Richard Smithc20d1442018-08-20 20:14:49 +0000441 }
442};
443
444class VendorExtQualType final : public Node {
445 const Node *Ty;
446 StringView Ext;
Alex Orlovf50df922021-03-24 10:21:32 +0400447 const Node *TA;
Richard Smithc20d1442018-08-20 20:14:49 +0000448
449public:
Alex Orlovf50df922021-03-24 10:21:32 +0400450 VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)
451 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
Richard Smithc20d1442018-08-20 20:14:49 +0000452
Alex Orlovf50df922021-03-24 10:21:32 +0400453 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
Richard Smithc20d1442018-08-20 20:14:49 +0000454
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700455 void printLeft(OutputBuffer &OB) const override {
456 Ty->print(OB);
457 OB += " ";
458 OB += Ext;
Alex Orlovf50df922021-03-24 10:21:32 +0400459 if (TA != nullptr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700460 TA->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000461 }
462};
463
464enum FunctionRefQual : unsigned char {
465 FrefQualNone,
466 FrefQualLValue,
467 FrefQualRValue,
468};
469
470enum Qualifiers {
471 QualNone = 0,
472 QualConst = 0x1,
473 QualVolatile = 0x2,
474 QualRestrict = 0x4,
475};
476
477inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
478 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
479}
480
Richard Smithdf1c14c2019-09-06 23:53:21 +0000481class QualType final : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +0000482protected:
483 const Qualifiers Quals;
484 const Node *Child;
485
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700486 void printQuals(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000487 if (Quals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700488 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000489 if (Quals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700490 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000491 if (Quals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700492 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000493 }
494
495public:
496 QualType(const Node *Child_, Qualifiers Quals_)
497 : Node(KQualType, Child_->RHSComponentCache,
498 Child_->ArrayCache, Child_->FunctionCache),
499 Quals(Quals_), Child(Child_) {}
500
501 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
502
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700503 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
504 return Child->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000505 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700506 bool hasArraySlow(OutputBuffer &OB) const override {
507 return Child->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000508 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700509 bool hasFunctionSlow(OutputBuffer &OB) const override {
510 return Child->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000511 }
512
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700513 void printLeft(OutputBuffer &OB) const override {
514 Child->printLeft(OB);
515 printQuals(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000516 }
517
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700518 void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000519};
520
521class ConversionOperatorType final : public Node {
522 const Node *Ty;
523
524public:
525 ConversionOperatorType(const Node *Ty_)
526 : Node(KConversionOperatorType), Ty(Ty_) {}
527
528 template<typename Fn> void match(Fn F) const { F(Ty); }
529
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700530 void printLeft(OutputBuffer &OB) const override {
531 OB += "operator ";
532 Ty->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000533 }
534};
535
536class PostfixQualifiedType final : public Node {
537 const Node *Ty;
538 const StringView Postfix;
539
540public:
541 PostfixQualifiedType(Node *Ty_, StringView Postfix_)
542 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
543
544 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
545
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700546 void printLeft(OutputBuffer &OB) const override {
547 Ty->printLeft(OB);
548 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +0000549 }
550};
551
552class NameType final : public Node {
553 const StringView Name;
554
555public:
556 NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
557
558 template<typename Fn> void match(Fn F) const { F(Name); }
559
560 StringView getName() const { return Name; }
561 StringView getBaseName() const override { return Name; }
562
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700563 void printLeft(OutputBuffer &OB) const override { OB += Name; }
Richard Smithc20d1442018-08-20 20:14:49 +0000564};
565
566class ElaboratedTypeSpefType : public Node {
567 StringView Kind;
568 Node *Child;
569public:
570 ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
571 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
572
573 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
574
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700575 void printLeft(OutputBuffer &OB) const override {
576 OB += Kind;
577 OB += ' ';
578 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000579 }
580};
581
582struct AbiTagAttr : Node {
583 Node *Base;
584 StringView Tag;
585
586 AbiTagAttr(Node* Base_, StringView Tag_)
587 : Node(KAbiTagAttr, Base_->RHSComponentCache,
588 Base_->ArrayCache, Base_->FunctionCache),
589 Base(Base_), Tag(Tag_) {}
590
591 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
592
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700593 void printLeft(OutputBuffer &OB) const override {
594 Base->printLeft(OB);
595 OB += "[abi:";
596 OB += Tag;
597 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +0000598 }
599};
600
601class EnableIfAttr : public Node {
602 NodeArray Conditions;
603public:
604 EnableIfAttr(NodeArray Conditions_)
605 : Node(KEnableIfAttr), Conditions(Conditions_) {}
606
607 template<typename Fn> void match(Fn F) const { F(Conditions); }
608
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700609 void printLeft(OutputBuffer &OB) const override {
610 OB += " [enable_if:";
611 Conditions.printWithComma(OB);
612 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +0000613 }
614};
615
616class ObjCProtoName : public Node {
617 const Node *Ty;
618 StringView Protocol;
619
620 friend class PointerType;
621
622public:
623 ObjCProtoName(const Node *Ty_, StringView Protocol_)
624 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
625
626 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
627
628 bool isObjCObject() const {
629 return Ty->getKind() == KNameType &&
630 static_cast<const NameType *>(Ty)->getName() == "objc_object";
631 }
632
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700633 void printLeft(OutputBuffer &OB) const override {
634 Ty->print(OB);
635 OB += "<";
636 OB += Protocol;
637 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +0000638 }
639};
640
641class PointerType final : public Node {
642 const Node *Pointee;
643
644public:
645 PointerType(const Node *Pointee_)
646 : Node(KPointerType, Pointee_->RHSComponentCache),
647 Pointee(Pointee_) {}
648
649 template<typename Fn> void match(Fn F) const { F(Pointee); }
650
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700651 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
652 return Pointee->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000653 }
654
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700655 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000656 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
657 if (Pointee->getKind() != KObjCProtoName ||
658 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700659 Pointee->printLeft(OB);
660 if (Pointee->hasArray(OB))
661 OB += " ";
662 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
663 OB += "(";
664 OB += "*";
Richard Smithc20d1442018-08-20 20:14:49 +0000665 } else {
666 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700667 OB += "id<";
668 OB += objcProto->Protocol;
669 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +0000670 }
671 }
672
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700673 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000674 if (Pointee->getKind() != KObjCProtoName ||
675 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700676 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
677 OB += ")";
678 Pointee->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000679 }
680 }
681};
682
683enum class ReferenceKind {
684 LValue,
685 RValue,
686};
687
688// Represents either a LValue or an RValue reference type.
689class ReferenceType : public Node {
690 const Node *Pointee;
691 ReferenceKind RK;
692
693 mutable bool Printing = false;
694
695 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
696 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
697 // other combination collapses to a lvalue ref.
Mikhail Borisov05f77222021-08-17 18:10:57 -0400698 //
699 // A combination of a TemplateForwardReference and a back-ref Substitution
700 // from an ill-formed string may have created a cycle; use cycle detection to
701 // avoid looping forever.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700702 std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000703 auto SoFar = std::make_pair(RK, Pointee);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400704 // Track the chain of nodes for the Floyd's 'tortoise and hare'
705 // cycle-detection algorithm, since getSyntaxNode(S) is impure
706 PODSmallVector<const Node *, 8> Prev;
Richard Smithc20d1442018-08-20 20:14:49 +0000707 for (;;) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700708 const Node *SN = SoFar.second->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000709 if (SN->getKind() != KReferenceType)
710 break;
711 auto *RT = static_cast<const ReferenceType *>(SN);
712 SoFar.second = RT->Pointee;
713 SoFar.first = std::min(SoFar.first, RT->RK);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400714
715 // The middle of Prev is the 'slow' pointer moving at half speed
716 Prev.push_back(SoFar.second);
717 if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {
718 // Cycle detected
719 SoFar.second = nullptr;
720 break;
721 }
Richard Smithc20d1442018-08-20 20:14:49 +0000722 }
723 return SoFar;
724 }
725
726public:
727 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
728 : Node(KReferenceType, Pointee_->RHSComponentCache),
729 Pointee(Pointee_), RK(RK_) {}
730
731 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
732
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700733 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
734 return Pointee->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000735 }
736
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700737 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000738 if (Printing)
739 return;
740 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700741 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400742 if (!Collapsed.second)
743 return;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700744 Collapsed.second->printLeft(OB);
745 if (Collapsed.second->hasArray(OB))
746 OB += " ";
747 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
748 OB += "(";
Richard Smithc20d1442018-08-20 20:14:49 +0000749
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700750 OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
Richard Smithc20d1442018-08-20 20:14:49 +0000751 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700752 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000753 if (Printing)
754 return;
755 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700756 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400757 if (!Collapsed.second)
758 return;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700759 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
760 OB += ")";
761 Collapsed.second->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000762 }
763};
764
765class PointerToMemberType final : public Node {
766 const Node *ClassType;
767 const Node *MemberType;
768
769public:
770 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
771 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
772 ClassType(ClassType_), MemberType(MemberType_) {}
773
774 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
775
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700776 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
777 return MemberType->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000778 }
779
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700780 void printLeft(OutputBuffer &OB) const override {
781 MemberType->printLeft(OB);
782 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
783 OB += "(";
Richard Smithc20d1442018-08-20 20:14:49 +0000784 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700785 OB += " ";
786 ClassType->print(OB);
787 OB += "::*";
Richard Smithc20d1442018-08-20 20:14:49 +0000788 }
789
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700790 void printRight(OutputBuffer &OB) const override {
791 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
792 OB += ")";
793 MemberType->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000794 }
795};
796
Richard Smithc20d1442018-08-20 20:14:49 +0000797class ArrayType final : public Node {
798 const Node *Base;
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800799 Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000800
801public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800802 ArrayType(const Node *Base_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000803 : Node(KArrayType,
804 /*RHSComponentCache=*/Cache::Yes,
805 /*ArrayCache=*/Cache::Yes),
806 Base(Base_), Dimension(Dimension_) {}
807
808 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
809
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700810 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
811 bool hasArraySlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000812
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700813 void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000814
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700815 void printRight(OutputBuffer &OB) const override {
816 if (OB.back() != ']')
817 OB += " ";
818 OB += "[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800819 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700820 Dimension->print(OB);
821 OB += "]";
822 Base->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000823 }
824};
825
826class FunctionType final : public Node {
827 const Node *Ret;
828 NodeArray Params;
829 Qualifiers CVQuals;
830 FunctionRefQual RefQual;
831 const Node *ExceptionSpec;
832
833public:
834 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
835 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
836 : Node(KFunctionType,
837 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
838 /*FunctionCache=*/Cache::Yes),
839 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
840 ExceptionSpec(ExceptionSpec_) {}
841
842 template<typename Fn> void match(Fn F) const {
843 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
844 }
845
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700846 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
847 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000848
849 // Handle C++'s ... quirky decl grammar by using the left & right
850 // distinction. Consider:
851 // int (*f(float))(char) {}
852 // f is a function that takes a float and returns a pointer to a function
853 // that takes a char and returns an int. If we're trying to print f, start
854 // by printing out the return types's left, then print our parameters, then
855 // finally print right of the return type.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700856 void printLeft(OutputBuffer &OB) const override {
857 Ret->printLeft(OB);
858 OB += " ";
Richard Smithc20d1442018-08-20 20:14:49 +0000859 }
860
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700861 void printRight(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800862 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700863 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800864 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700865 Ret->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000866
867 if (CVQuals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700868 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000869 if (CVQuals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700870 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000871 if (CVQuals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700872 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000873
874 if (RefQual == FrefQualLValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700875 OB += " &";
Richard Smithc20d1442018-08-20 20:14:49 +0000876 else if (RefQual == FrefQualRValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700877 OB += " &&";
Richard Smithc20d1442018-08-20 20:14:49 +0000878
879 if (ExceptionSpec != nullptr) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700880 OB += ' ';
881 ExceptionSpec->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000882 }
883 }
884};
885
886class NoexceptSpec : public Node {
887 const Node *E;
888public:
889 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
890
891 template<typename Fn> void match(Fn F) const { F(E); }
892
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700893 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800894 OB += "noexcept";
895 OB.printOpen();
896 E->printAsOperand(OB);
897 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000898 }
899};
900
901class DynamicExceptionSpec : public Node {
902 NodeArray Types;
903public:
904 DynamicExceptionSpec(NodeArray Types_)
905 : Node(KDynamicExceptionSpec), Types(Types_) {}
906
907 template<typename Fn> void match(Fn F) const { F(Types); }
908
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700909 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800910 OB += "throw";
911 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700912 Types.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800913 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000914 }
915};
916
917class FunctionEncoding final : public Node {
918 const Node *Ret;
919 const Node *Name;
920 NodeArray Params;
921 const Node *Attrs;
922 Qualifiers CVQuals;
923 FunctionRefQual RefQual;
924
925public:
926 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
927 const Node *Attrs_, Qualifiers CVQuals_,
928 FunctionRefQual RefQual_)
929 : Node(KFunctionEncoding,
930 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
931 /*FunctionCache=*/Cache::Yes),
932 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
933 CVQuals(CVQuals_), RefQual(RefQual_) {}
934
935 template<typename Fn> void match(Fn F) const {
936 F(Ret, Name, Params, Attrs, CVQuals, RefQual);
937 }
938
939 Qualifiers getCVQuals() const { return CVQuals; }
940 FunctionRefQual getRefQual() const { return RefQual; }
941 NodeArray getParams() const { return Params; }
942 const Node *getReturnType() const { return Ret; }
943
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700944 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
945 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000946
947 const Node *getName() const { return Name; }
948
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700949 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000950 if (Ret) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700951 Ret->printLeft(OB);
952 if (!Ret->hasRHSComponent(OB))
953 OB += " ";
Richard Smithc20d1442018-08-20 20:14:49 +0000954 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700955 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000956 }
957
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700958 void printRight(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800959 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700960 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800961 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000962 if (Ret)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700963 Ret->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000964
965 if (CVQuals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700966 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000967 if (CVQuals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700968 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000969 if (CVQuals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700970 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000971
972 if (RefQual == FrefQualLValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700973 OB += " &";
Richard Smithc20d1442018-08-20 20:14:49 +0000974 else if (RefQual == FrefQualRValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700975 OB += " &&";
Richard Smithc20d1442018-08-20 20:14:49 +0000976
977 if (Attrs != nullptr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700978 Attrs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000979 }
980};
981
982class LiteralOperator : public Node {
983 const Node *OpName;
984
985public:
986 LiteralOperator(const Node *OpName_)
987 : Node(KLiteralOperator), OpName(OpName_) {}
988
989 template<typename Fn> void match(Fn F) const { F(OpName); }
990
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700991 void printLeft(OutputBuffer &OB) const override {
992 OB += "operator\"\" ";
993 OpName->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000994 }
995};
996
997class SpecialName final : public Node {
998 const StringView Special;
999 const Node *Child;
1000
1001public:
1002 SpecialName(StringView Special_, const Node *Child_)
1003 : Node(KSpecialName), Special(Special_), Child(Child_) {}
1004
1005 template<typename Fn> void match(Fn F) const { F(Special, Child); }
1006
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001007 void printLeft(OutputBuffer &OB) const override {
1008 OB += Special;
1009 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001010 }
1011};
1012
1013class CtorVtableSpecialName final : public Node {
1014 const Node *FirstType;
1015 const Node *SecondType;
1016
1017public:
1018 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
1019 : Node(KCtorVtableSpecialName),
1020 FirstType(FirstType_), SecondType(SecondType_) {}
1021
1022 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
1023
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001024 void printLeft(OutputBuffer &OB) const override {
1025 OB += "construction vtable for ";
1026 FirstType->print(OB);
1027 OB += "-in-";
1028 SecondType->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001029 }
1030};
1031
1032struct NestedName : Node {
1033 Node *Qual;
1034 Node *Name;
1035
1036 NestedName(Node *Qual_, Node *Name_)
1037 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
1038
1039 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
1040
1041 StringView getBaseName() const override { return Name->getBaseName(); }
1042
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001043 void printLeft(OutputBuffer &OB) const override {
1044 Qual->print(OB);
1045 OB += "::";
1046 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001047 }
1048};
1049
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08001050struct ModuleName : Node {
1051 ModuleName *Parent;
1052 Node *Name;
1053 bool IsPartition;
1054
1055 ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false)
1056 : Node(KModuleName), Parent(Parent_), Name(Name_),
1057 IsPartition(IsPartition_) {}
1058
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001059 template <typename Fn> void match(Fn F) const {
1060 F(Parent, Name, IsPartition);
1061 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08001062
1063 void printLeft(OutputBuffer &OB) const override {
1064 if (Parent)
1065 Parent->print(OB);
1066 if (Parent || IsPartition)
1067 OB += IsPartition ? ':' : '.';
1068 Name->print(OB);
1069 }
1070};
1071
1072struct ModuleEntity : Node {
1073 ModuleName *Module;
1074 Node *Name;
1075
1076 ModuleEntity(ModuleName *Module_, Node *Name_)
1077 : Node(KModuleEntity), Module(Module_), Name(Name_) {}
1078
1079 template <typename Fn> void match(Fn F) const { F(Module, Name); }
1080
1081 StringView getBaseName() const override { return Name->getBaseName(); }
1082
1083 void printLeft(OutputBuffer &OB) const override {
1084 Name->print(OB);
1085 OB += '@';
1086 Module->print(OB);
1087 }
1088};
1089
Richard Smithc20d1442018-08-20 20:14:49 +00001090struct LocalName : Node {
1091 Node *Encoding;
1092 Node *Entity;
1093
1094 LocalName(Node *Encoding_, Node *Entity_)
1095 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
1096
1097 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
1098
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001099 void printLeft(OutputBuffer &OB) const override {
1100 Encoding->print(OB);
1101 OB += "::";
1102 Entity->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001103 }
1104};
1105
1106class QualifiedName final : public Node {
1107 // qualifier::name
1108 const Node *Qualifier;
1109 const Node *Name;
1110
1111public:
1112 QualifiedName(const Node *Qualifier_, const Node *Name_)
1113 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
1114
1115 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
1116
1117 StringView getBaseName() const override { return Name->getBaseName(); }
1118
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001119 void printLeft(OutputBuffer &OB) const override {
1120 Qualifier->print(OB);
1121 OB += "::";
1122 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001123 }
1124};
1125
1126class VectorType final : public Node {
1127 const Node *BaseType;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001128 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001129
1130public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001131 VectorType(const Node *BaseType_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +00001132 : Node(KVectorType), BaseType(BaseType_),
1133 Dimension(Dimension_) {}
1134
1135 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
1136
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001137 void printLeft(OutputBuffer &OB) const override {
1138 BaseType->print(OB);
1139 OB += " vector[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001140 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001141 Dimension->print(OB);
1142 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001143 }
1144};
1145
1146class PixelVectorType final : public Node {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001147 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001148
1149public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001150 PixelVectorType(const Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +00001151 : Node(KPixelVectorType), Dimension(Dimension_) {}
1152
1153 template<typename Fn> void match(Fn F) const { F(Dimension); }
1154
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001155 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001156 // FIXME: This should demangle as "vector pixel".
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001157 OB += "pixel vector[";
1158 Dimension->print(OB);
1159 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001160 }
1161};
1162
Pengfei Wang50e90b82021-09-23 11:02:25 +08001163class BinaryFPType final : public Node {
1164 const Node *Dimension;
1165
1166public:
1167 BinaryFPType(const Node *Dimension_)
1168 : Node(KBinaryFPType), Dimension(Dimension_) {}
1169
1170 template<typename Fn> void match(Fn F) const { F(Dimension); }
1171
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001172 void printLeft(OutputBuffer &OB) const override {
1173 OB += "_Float";
1174 Dimension->print(OB);
Pengfei Wang50e90b82021-09-23 11:02:25 +08001175 }
1176};
1177
Richard Smithdf1c14c2019-09-06 23:53:21 +00001178enum class TemplateParamKind { Type, NonType, Template };
1179
1180/// An invented name for a template parameter for which we don't have a
1181/// corresponding template argument.
1182///
1183/// This node is created when parsing the <lambda-sig> for a lambda with
1184/// explicit template arguments, which might be referenced in the parameter
1185/// types appearing later in the <lambda-sig>.
1186class SyntheticTemplateParamName final : public Node {
1187 TemplateParamKind Kind;
1188 unsigned Index;
1189
1190public:
1191 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
1192 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
1193
1194 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
1195
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001196 void printLeft(OutputBuffer &OB) const override {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001197 switch (Kind) {
1198 case TemplateParamKind::Type:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001199 OB += "$T";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001200 break;
1201 case TemplateParamKind::NonType:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001202 OB += "$N";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001203 break;
1204 case TemplateParamKind::Template:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001205 OB += "$TT";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001206 break;
1207 }
1208 if (Index > 0)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001209 OB << Index - 1;
Richard Smithdf1c14c2019-09-06 23:53:21 +00001210 }
1211};
1212
1213/// A template type parameter declaration, 'typename T'.
1214class TypeTemplateParamDecl final : public Node {
1215 Node *Name;
1216
1217public:
1218 TypeTemplateParamDecl(Node *Name_)
1219 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
1220
1221 template<typename Fn> void match(Fn F) const { F(Name); }
1222
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001223 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001224
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001225 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001226};
1227
1228/// A non-type template parameter declaration, 'int N'.
1229class NonTypeTemplateParamDecl final : public Node {
1230 Node *Name;
1231 Node *Type;
1232
1233public:
1234 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
1235 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
1236
1237 template<typename Fn> void match(Fn F) const { F(Name, Type); }
1238
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001239 void printLeft(OutputBuffer &OB) const override {
1240 Type->printLeft(OB);
1241 if (!Type->hasRHSComponent(OB))
1242 OB += " ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001243 }
1244
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001245 void printRight(OutputBuffer &OB) const override {
1246 Name->print(OB);
1247 Type->printRight(OB);
Richard Smithdf1c14c2019-09-06 23:53:21 +00001248 }
1249};
1250
1251/// A template template parameter declaration,
1252/// 'template<typename T> typename N'.
1253class TemplateTemplateParamDecl final : public Node {
1254 Node *Name;
1255 NodeArray Params;
1256
1257public:
1258 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
1259 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1260 Params(Params_) {}
1261
1262 template<typename Fn> void match(Fn F) const { F(Name, Params); }
1263
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001264 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001265 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001266 OB += "template<";
1267 Params.printWithComma(OB);
1268 OB += "> typename ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001269 }
1270
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001271 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001272};
1273
1274/// A template parameter pack declaration, 'typename ...T'.
1275class TemplateParamPackDecl final : public Node {
1276 Node *Param;
1277
1278public:
1279 TemplateParamPackDecl(Node *Param_)
1280 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1281
1282 template<typename Fn> void match(Fn F) const { F(Param); }
1283
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001284 void printLeft(OutputBuffer &OB) const override {
1285 Param->printLeft(OB);
1286 OB += "...";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001287 }
1288
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001289 void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001290};
1291
Richard Smithc20d1442018-08-20 20:14:49 +00001292/// An unexpanded parameter pack (either in the expression or type context). If
1293/// this AST is correct, this node will have a ParameterPackExpansion node above
1294/// it.
1295///
1296/// This node is created when some <template-args> are found that apply to an
1297/// <encoding>, and is stored in the TemplateParams table. In order for this to
1298/// appear in the final AST, it has to referenced via a <template-param> (ie,
1299/// T_).
1300class ParameterPack final : public Node {
1301 NodeArray Data;
1302
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08001303 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1304 // one.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001305 void initializePackExpansion(OutputBuffer &OB) const {
1306 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1307 OB.CurrentPackMax = static_cast<unsigned>(Data.size());
1308 OB.CurrentPackIndex = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00001309 }
1310 }
1311
1312public:
1313 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1314 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
1315 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1316 return P->ArrayCache == Cache::No;
1317 }))
1318 ArrayCache = Cache::No;
1319 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1320 return P->FunctionCache == Cache::No;
1321 }))
1322 FunctionCache = Cache::No;
1323 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1324 return P->RHSComponentCache == Cache::No;
1325 }))
1326 RHSComponentCache = Cache::No;
1327 }
1328
1329 template<typename Fn> void match(Fn F) const { F(Data); }
1330
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001331 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1332 initializePackExpansion(OB);
1333 size_t Idx = OB.CurrentPackIndex;
1334 return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001335 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001336 bool hasArraySlow(OutputBuffer &OB) const override {
1337 initializePackExpansion(OB);
1338 size_t Idx = OB.CurrentPackIndex;
1339 return Idx < Data.size() && Data[Idx]->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001340 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001341 bool hasFunctionSlow(OutputBuffer &OB) const override {
1342 initializePackExpansion(OB);
1343 size_t Idx = OB.CurrentPackIndex;
1344 return Idx < Data.size() && Data[Idx]->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001345 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001346 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1347 initializePackExpansion(OB);
1348 size_t Idx = OB.CurrentPackIndex;
1349 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;
Richard Smithc20d1442018-08-20 20:14:49 +00001350 }
1351
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001352 void printLeft(OutputBuffer &OB) const override {
1353 initializePackExpansion(OB);
1354 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001355 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001356 Data[Idx]->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001357 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001358 void printRight(OutputBuffer &OB) const override {
1359 initializePackExpansion(OB);
1360 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001361 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001362 Data[Idx]->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001363 }
1364};
1365
1366/// A variadic template argument. This node represents an occurrence of
1367/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1368/// one of it's Elements is. The parser inserts a ParameterPack into the
1369/// TemplateParams table if the <template-args> this pack belongs to apply to an
1370/// <encoding>.
1371class TemplateArgumentPack final : public Node {
1372 NodeArray Elements;
1373public:
1374 TemplateArgumentPack(NodeArray Elements_)
1375 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1376
1377 template<typename Fn> void match(Fn F) const { F(Elements); }
1378
1379 NodeArray getElements() const { return Elements; }
1380
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001381 void printLeft(OutputBuffer &OB) const override {
1382 Elements.printWithComma(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001383 }
1384};
1385
1386/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1387/// which each have Child->ParameterPackSize elements.
1388class ParameterPackExpansion final : public Node {
1389 const Node *Child;
1390
1391public:
1392 ParameterPackExpansion(const Node *Child_)
1393 : Node(KParameterPackExpansion), Child(Child_) {}
1394
1395 template<typename Fn> void match(Fn F) const { F(Child); }
1396
1397 const Node *getChild() const { return Child; }
1398
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001399 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001400 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001401 SwapAndRestore<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1402 SwapAndRestore<unsigned> SavePackMax(OB.CurrentPackMax, Max);
1403 size_t StreamPos = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +00001404
1405 // Print the first element in the pack. If Child contains a ParameterPack,
1406 // it will set up S.CurrentPackMax and print the first element.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001407 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001408
1409 // No ParameterPack was found in Child. This can occur if we've found a pack
1410 // expansion on a <function-param>.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001411 if (OB.CurrentPackMax == Max) {
1412 OB += "...";
Richard Smithc20d1442018-08-20 20:14:49 +00001413 return;
1414 }
1415
1416 // We found a ParameterPack, but it has no elements. Erase whatever we may
1417 // of printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001418 if (OB.CurrentPackMax == 0) {
1419 OB.setCurrentPosition(StreamPos);
Richard Smithc20d1442018-08-20 20:14:49 +00001420 return;
1421 }
1422
1423 // Else, iterate through the rest of the elements in the pack.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001424 for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {
1425 OB += ", ";
1426 OB.CurrentPackIndex = I;
1427 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001428 }
1429 }
1430};
1431
1432class TemplateArgs final : public Node {
1433 NodeArray Params;
1434
1435public:
1436 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1437
1438 template<typename Fn> void match(Fn F) const { F(Params); }
1439
1440 NodeArray getParams() { return Params; }
1441
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001442 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001443 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001444 OB += "<";
1445 Params.printWithComma(OB);
1446 if (OB.back() == '>')
1447 OB += " ";
1448 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +00001449 }
1450};
1451
Richard Smithb485b352018-08-24 23:30:26 +00001452/// A forward-reference to a template argument that was not known at the point
1453/// where the template parameter name was parsed in a mangling.
1454///
1455/// This is created when demangling the name of a specialization of a
1456/// conversion function template:
1457///
1458/// \code
1459/// struct A {
1460/// template<typename T> operator T*();
1461/// };
1462/// \endcode
1463///
1464/// When demangling a specialization of the conversion function template, we
1465/// encounter the name of the template (including the \c T) before we reach
1466/// the template argument list, so we cannot substitute the parameter name
1467/// for the corresponding argument while parsing. Instead, we create a
1468/// \c ForwardTemplateReference node that is resolved after we parse the
1469/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001470struct ForwardTemplateReference : Node {
1471 size_t Index;
1472 Node *Ref = nullptr;
1473
1474 // If we're currently printing this node. It is possible (though invalid) for
1475 // a forward template reference to refer to itself via a substitution. This
1476 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1477 // out if more than one print* function is active.
1478 mutable bool Printing = false;
1479
1480 ForwardTemplateReference(size_t Index_)
1481 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1482 Cache::Unknown),
1483 Index(Index_) {}
1484
1485 // We don't provide a matcher for these, because the value of the node is
1486 // not determined by its construction parameters, and it generally needs
1487 // special handling.
1488 template<typename Fn> void match(Fn F) const = delete;
1489
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001490 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001491 if (Printing)
1492 return false;
1493 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001494 return Ref->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001495 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001496 bool hasArraySlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001497 if (Printing)
1498 return false;
1499 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001500 return Ref->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001501 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001502 bool hasFunctionSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001503 if (Printing)
1504 return false;
1505 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001506 return Ref->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001507 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001508 const Node *getSyntaxNode(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001509 if (Printing)
1510 return this;
1511 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001512 return Ref->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001513 }
1514
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001515 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001516 if (Printing)
1517 return;
1518 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001519 Ref->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001520 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001521 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001522 if (Printing)
1523 return;
1524 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001525 Ref->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001526 }
1527};
1528
1529struct NameWithTemplateArgs : Node {
1530 // name<template_args>
1531 Node *Name;
1532 Node *TemplateArgs;
1533
1534 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1535 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1536
1537 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1538
1539 StringView getBaseName() const override { return Name->getBaseName(); }
1540
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001541 void printLeft(OutputBuffer &OB) const override {
1542 Name->print(OB);
1543 TemplateArgs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001544 }
1545};
1546
1547class GlobalQualifiedName final : public Node {
1548 Node *Child;
1549
1550public:
1551 GlobalQualifiedName(Node* Child_)
1552 : Node(KGlobalQualifiedName), Child(Child_) {}
1553
1554 template<typename Fn> void match(Fn F) const { F(Child); }
1555
1556 StringView getBaseName() const override { return Child->getBaseName(); }
1557
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001558 void printLeft(OutputBuffer &OB) const override {
1559 OB += "::";
1560 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001561 }
1562};
1563
Richard Smithc20d1442018-08-20 20:14:49 +00001564enum class SpecialSubKind {
1565 allocator,
1566 basic_string,
1567 string,
1568 istream,
1569 ostream,
1570 iostream,
1571};
1572
1573class ExpandedSpecialSubstitution final : public Node {
1574 SpecialSubKind SSK;
1575
1576public:
1577 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1578 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1579
1580 template<typename Fn> void match(Fn F) const { F(SSK); }
1581
1582 StringView getBaseName() const override {
1583 switch (SSK) {
1584 case SpecialSubKind::allocator:
1585 return StringView("allocator");
1586 case SpecialSubKind::basic_string:
1587 return StringView("basic_string");
1588 case SpecialSubKind::string:
1589 return StringView("basic_string");
1590 case SpecialSubKind::istream:
1591 return StringView("basic_istream");
1592 case SpecialSubKind::ostream:
1593 return StringView("basic_ostream");
1594 case SpecialSubKind::iostream:
1595 return StringView("basic_iostream");
1596 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001597 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001598 }
1599
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001600 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001601 switch (SSK) {
1602 case SpecialSubKind::allocator:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001603 OB += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001604 break;
1605 case SpecialSubKind::basic_string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001606 OB += "std::basic_string";
Richard Smithb485b352018-08-24 23:30:26 +00001607 break;
Richard Smithc20d1442018-08-20 20:14:49 +00001608 case SpecialSubKind::string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001609 OB += "std::basic_string<char, std::char_traits<char>, "
1610 "std::allocator<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001611 break;
1612 case SpecialSubKind::istream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001613 OB += "std::basic_istream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001614 break;
1615 case SpecialSubKind::ostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001616 OB += "std::basic_ostream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001617 break;
1618 case SpecialSubKind::iostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001619 OB += "std::basic_iostream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001620 break;
1621 }
1622 }
1623};
1624
1625class SpecialSubstitution final : public Node {
1626public:
1627 SpecialSubKind SSK;
1628
1629 SpecialSubstitution(SpecialSubKind SSK_)
1630 : Node(KSpecialSubstitution), SSK(SSK_) {}
1631
1632 template<typename Fn> void match(Fn F) const { F(SSK); }
1633
1634 StringView getBaseName() const override {
1635 switch (SSK) {
1636 case SpecialSubKind::allocator:
1637 return StringView("allocator");
1638 case SpecialSubKind::basic_string:
1639 return StringView("basic_string");
1640 case SpecialSubKind::string:
1641 return StringView("string");
1642 case SpecialSubKind::istream:
1643 return StringView("istream");
1644 case SpecialSubKind::ostream:
1645 return StringView("ostream");
1646 case SpecialSubKind::iostream:
1647 return StringView("iostream");
1648 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001649 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001650 }
1651
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001652 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001653 switch (SSK) {
1654 case SpecialSubKind::allocator:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001655 OB += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001656 break;
1657 case SpecialSubKind::basic_string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001658 OB += "std::basic_string";
Richard Smithc20d1442018-08-20 20:14:49 +00001659 break;
1660 case SpecialSubKind::string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001661 OB += "std::string";
Richard Smithc20d1442018-08-20 20:14:49 +00001662 break;
1663 case SpecialSubKind::istream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001664 OB += "std::istream";
Richard Smithc20d1442018-08-20 20:14:49 +00001665 break;
1666 case SpecialSubKind::ostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001667 OB += "std::ostream";
Richard Smithc20d1442018-08-20 20:14:49 +00001668 break;
1669 case SpecialSubKind::iostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001670 OB += "std::iostream";
Richard Smithc20d1442018-08-20 20:14:49 +00001671 break;
1672 }
1673 }
1674};
1675
1676class CtorDtorName final : public Node {
1677 const Node *Basename;
1678 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001679 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001680
1681public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001682 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1683 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1684 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001685
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001686 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001687
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001688 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001689 if (IsDtor)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001690 OB += "~";
1691 OB += Basename->getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001692 }
1693};
1694
1695class DtorName : public Node {
1696 const Node *Base;
1697
1698public:
1699 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1700
1701 template<typename Fn> void match(Fn F) const { F(Base); }
1702
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001703 void printLeft(OutputBuffer &OB) const override {
1704 OB += "~";
1705 Base->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001706 }
1707};
1708
1709class UnnamedTypeName : public Node {
1710 const StringView Count;
1711
1712public:
1713 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1714
1715 template<typename Fn> void match(Fn F) const { F(Count); }
1716
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001717 void printLeft(OutputBuffer &OB) const override {
1718 OB += "'unnamed";
1719 OB += Count;
1720 OB += "\'";
Richard Smithc20d1442018-08-20 20:14:49 +00001721 }
1722};
1723
1724class ClosureTypeName : public Node {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001725 NodeArray TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00001726 NodeArray Params;
1727 StringView Count;
1728
1729public:
Richard Smithdf1c14c2019-09-06 23:53:21 +00001730 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1731 StringView Count_)
1732 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1733 Params(Params_), Count(Count_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001734
Richard Smithdf1c14c2019-09-06 23:53:21 +00001735 template<typename Fn> void match(Fn F) const {
1736 F(TemplateParams, Params, Count);
1737 }
1738
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001739 void printDeclarator(OutputBuffer &OB) const {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001740 if (!TemplateParams.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001741 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001742 OB += "<";
1743 TemplateParams.printWithComma(OB);
1744 OB += ">";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001745 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001746 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001747 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001748 OB.printClose();
Richard Smithdf1c14c2019-09-06 23:53:21 +00001749 }
Richard Smithc20d1442018-08-20 20:14:49 +00001750
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001751 void printLeft(OutputBuffer &OB) const override {
1752 OB += "\'lambda";
1753 OB += Count;
1754 OB += "\'";
1755 printDeclarator(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001756 }
1757};
1758
1759class StructuredBindingName : public Node {
1760 NodeArray Bindings;
1761public:
1762 StructuredBindingName(NodeArray Bindings_)
1763 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1764
1765 template<typename Fn> void match(Fn F) const { F(Bindings); }
1766
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001767 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001768 OB.printOpen('[');
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001769 Bindings.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001770 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001771 }
1772};
1773
1774// -- Expression Nodes --
1775
1776class BinaryExpr : public Node {
1777 const Node *LHS;
1778 const StringView InfixOperator;
1779 const Node *RHS;
1780
1781public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001782 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
1783 Prec Prec_)
1784 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
1785 RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001786
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001787 template <typename Fn> void match(Fn F) const {
1788 F(LHS, InfixOperator, RHS, getPrecedence());
1789 }
Richard Smithc20d1442018-08-20 20:14:49 +00001790
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001791 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001792 bool ParenAll = OB.isGtInsideTemplateArgs() && InfixOperator == ">";
1793 if (ParenAll)
1794 OB.printOpen();
1795 // Assignment is right associative, with special LHS precedence.
1796 bool IsAssign = getPrecedence() == Prec::Assign;
1797 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1798 // No space before comma operator
1799 if (!(InfixOperator == ","))
1800 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001801 OB += InfixOperator;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001802 OB += " ";
1803 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1804 if (ParenAll)
1805 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001806 }
1807};
1808
1809class ArraySubscriptExpr : public Node {
1810 const Node *Op1;
1811 const Node *Op2;
1812
1813public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001814 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1815 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001816
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001817 template <typename Fn> void match(Fn F) const {
1818 F(Op1, Op2, getPrecedence());
1819 }
Richard Smithc20d1442018-08-20 20:14:49 +00001820
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001821 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001822 Op1->printAsOperand(OB, getPrecedence());
1823 OB.printOpen('[');
1824 Op2->printAsOperand(OB);
1825 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001826 }
1827};
1828
1829class PostfixExpr : public Node {
1830 const Node *Child;
1831 const StringView Operator;
1832
1833public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001834 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
1835 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001836
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001837 template <typename Fn> void match(Fn F) const {
1838 F(Child, Operator, getPrecedence());
1839 }
Richard Smithc20d1442018-08-20 20:14:49 +00001840
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001841 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001842 Child->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001843 OB += Operator;
Richard Smithc20d1442018-08-20 20:14:49 +00001844 }
1845};
1846
1847class ConditionalExpr : public Node {
1848 const Node *Cond;
1849 const Node *Then;
1850 const Node *Else;
1851
1852public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001853 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1854 Prec Prec_)
1855 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001856
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001857 template <typename Fn> void match(Fn F) const {
1858 F(Cond, Then, Else, getPrecedence());
1859 }
Richard Smithc20d1442018-08-20 20:14:49 +00001860
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001861 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001862 Cond->printAsOperand(OB, getPrecedence());
1863 OB += " ? ";
1864 Then->printAsOperand(OB);
1865 OB += " : ";
1866 Else->printAsOperand(OB, Prec::Assign, true);
Richard Smithc20d1442018-08-20 20:14:49 +00001867 }
1868};
1869
1870class MemberExpr : public Node {
1871 const Node *LHS;
1872 const StringView Kind;
1873 const Node *RHS;
1874
1875public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001876 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
1877 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001878
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001879 template <typename Fn> void match(Fn F) const {
1880 F(LHS, Kind, RHS, getPrecedence());
1881 }
Richard Smithc20d1442018-08-20 20:14:49 +00001882
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001883 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001884 LHS->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001885 OB += Kind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001886 RHS->printAsOperand(OB, getPrecedence(), false);
Richard Smithc20d1442018-08-20 20:14:49 +00001887 }
1888};
1889
Richard Smith1865d2f2020-10-22 19:29:36 -07001890class SubobjectExpr : public Node {
1891 const Node *Type;
1892 const Node *SubExpr;
1893 StringView Offset;
1894 NodeArray UnionSelectors;
1895 bool OnePastTheEnd;
1896
1897public:
1898 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1899 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1900 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1901 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1902
1903 template<typename Fn> void match(Fn F) const {
1904 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1905 }
1906
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001907 void printLeft(OutputBuffer &OB) const override {
1908 SubExpr->print(OB);
1909 OB += ".<";
1910 Type->print(OB);
1911 OB += " at offset ";
Richard Smith1865d2f2020-10-22 19:29:36 -07001912 if (Offset.empty()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001913 OB += "0";
Richard Smith1865d2f2020-10-22 19:29:36 -07001914 } else if (Offset[0] == 'n') {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001915 OB += "-";
1916 OB += Offset.dropFront();
Richard Smith1865d2f2020-10-22 19:29:36 -07001917 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001918 OB += Offset;
Richard Smith1865d2f2020-10-22 19:29:36 -07001919 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001920 OB += ">";
Richard Smith1865d2f2020-10-22 19:29:36 -07001921 }
1922};
1923
Richard Smithc20d1442018-08-20 20:14:49 +00001924class EnclosingExpr : public Node {
1925 const StringView Prefix;
1926 const Node *Infix;
1927 const StringView Postfix;
1928
1929public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001930 EnclosingExpr(StringView Prefix_, Node *Infix_, Prec Prec_ = Prec::Primary)
1931 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001932
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001933 template <typename Fn> void match(Fn F) const {
1934 F(Prefix, Infix, getPrecedence());
1935 }
Richard Smithc20d1442018-08-20 20:14:49 +00001936
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001937 void printLeft(OutputBuffer &OB) const override {
1938 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001939 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001940 Infix->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001941 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001942 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +00001943 }
1944};
1945
1946class CastExpr : public Node {
1947 // cast_kind<to>(from)
1948 const StringView CastKind;
1949 const Node *To;
1950 const Node *From;
1951
1952public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001953 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
1954 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001955
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001956 template <typename Fn> void match(Fn F) const {
1957 F(CastKind, To, From, getPrecedence());
1958 }
Richard Smithc20d1442018-08-20 20:14:49 +00001959
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001960 void printLeft(OutputBuffer &OB) const override {
1961 OB += CastKind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001962 {
1963 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
1964 OB += "<";
1965 To->printLeft(OB);
1966 if (OB.back() == '>')
1967 OB += " ";
1968 OB += ">";
1969 }
1970 OB.printOpen();
1971 From->printAsOperand(OB);
1972 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001973 }
1974};
1975
1976class SizeofParamPackExpr : public Node {
1977 const Node *Pack;
1978
1979public:
1980 SizeofParamPackExpr(const Node *Pack_)
1981 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1982
1983 template<typename Fn> void match(Fn F) const { F(Pack); }
1984
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001985 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001986 OB += "sizeof...";
1987 OB.printOpen();
Richard Smithc20d1442018-08-20 20:14:49 +00001988 ParameterPackExpansion PPE(Pack);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001989 PPE.printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001990 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001991 }
1992};
1993
1994class CallExpr : public Node {
1995 const Node *Callee;
1996 NodeArray Args;
1997
1998public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001999 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
2000 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002001
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002002 template <typename Fn> void match(Fn F) const {
2003 F(Callee, Args, getPrecedence());
2004 }
Richard Smithc20d1442018-08-20 20:14:49 +00002005
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002006 void printLeft(OutputBuffer &OB) const override {
2007 Callee->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002008 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002009 Args.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002010 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002011 }
2012};
2013
2014class NewExpr : public Node {
2015 // new (expr_list) type(init_list)
2016 NodeArray ExprList;
2017 Node *Type;
2018 NodeArray InitList;
2019 bool IsGlobal; // ::operator new ?
2020 bool IsArray; // new[] ?
2021public:
2022 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002023 bool IsArray_, Prec Prec_)
2024 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
2025 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002026
2027 template<typename Fn> void match(Fn F) const {
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002028 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00002029 }
2030
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002031 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002032 if (IsGlobal)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08002033 OB += "::";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002034 OB += "new";
Richard Smithc20d1442018-08-20 20:14:49 +00002035 if (IsArray)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002036 OB += "[]";
Richard Smithc20d1442018-08-20 20:14:49 +00002037 if (!ExprList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002038 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002039 ExprList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002040 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002041 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002042 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002043 Type->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002044 if (!InitList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002045 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002046 InitList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002047 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002048 }
Richard Smithc20d1442018-08-20 20:14:49 +00002049 }
2050};
2051
2052class DeleteExpr : public Node {
2053 Node *Op;
2054 bool IsGlobal;
2055 bool IsArray;
2056
2057public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002058 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
2059 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
2060 IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002061
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002062 template <typename Fn> void match(Fn F) const {
2063 F(Op, IsGlobal, IsArray, getPrecedence());
2064 }
Richard Smithc20d1442018-08-20 20:14:49 +00002065
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002066 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002067 if (IsGlobal)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002068 OB += "::";
2069 OB += "delete";
Richard Smithc20d1442018-08-20 20:14:49 +00002070 if (IsArray)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08002071 OB += "[]";
2072 OB += ' ';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002073 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002074 }
2075};
2076
2077class PrefixExpr : public Node {
2078 StringView Prefix;
2079 Node *Child;
2080
2081public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002082 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
2083 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002084
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002085 template <typename Fn> void match(Fn F) const {
2086 F(Prefix, Child, getPrecedence());
2087 }
Richard Smithc20d1442018-08-20 20:14:49 +00002088
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002089 void printLeft(OutputBuffer &OB) const override {
2090 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002091 Child->printAsOperand(OB, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00002092 }
2093};
2094
2095class FunctionParam : public Node {
2096 StringView Number;
2097
2098public:
2099 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
2100
2101 template<typename Fn> void match(Fn F) const { F(Number); }
2102
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002103 void printLeft(OutputBuffer &OB) const override {
2104 OB += "fp";
2105 OB += Number;
Richard Smithc20d1442018-08-20 20:14:49 +00002106 }
2107};
2108
2109class ConversionExpr : public Node {
2110 const Node *Type;
2111 NodeArray Expressions;
2112
2113public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002114 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2115 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002116
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002117 template <typename Fn> void match(Fn F) const {
2118 F(Type, Expressions, getPrecedence());
2119 }
Richard Smithc20d1442018-08-20 20:14:49 +00002120
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002121 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002122 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002123 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002124 OB.printClose();
2125 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002126 Expressions.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002127 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002128 }
2129};
2130
Richard Smith1865d2f2020-10-22 19:29:36 -07002131class PointerToMemberConversionExpr : public Node {
2132 const Node *Type;
2133 const Node *SubExpr;
2134 StringView Offset;
2135
2136public:
2137 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002138 StringView Offset_, Prec Prec_)
2139 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2140 SubExpr(SubExpr_), Offset(Offset_) {}
Richard Smith1865d2f2020-10-22 19:29:36 -07002141
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002142 template <typename Fn> void match(Fn F) const {
2143 F(Type, SubExpr, Offset, getPrecedence());
2144 }
Richard Smith1865d2f2020-10-22 19:29:36 -07002145
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002146 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002147 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002148 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002149 OB.printClose();
2150 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002151 SubExpr->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002152 OB.printClose();
Richard Smith1865d2f2020-10-22 19:29:36 -07002153 }
2154};
2155
Richard Smithc20d1442018-08-20 20:14:49 +00002156class InitListExpr : public Node {
2157 const Node *Ty;
2158 NodeArray Inits;
2159public:
2160 InitListExpr(const Node *Ty_, NodeArray Inits_)
2161 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2162
2163 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2164
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002165 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002166 if (Ty)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002167 Ty->print(OB);
2168 OB += '{';
2169 Inits.printWithComma(OB);
2170 OB += '}';
Richard Smithc20d1442018-08-20 20:14:49 +00002171 }
2172};
2173
2174class BracedExpr : public Node {
2175 const Node *Elem;
2176 const Node *Init;
2177 bool IsArray;
2178public:
2179 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2180 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2181
2182 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
2183
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002184 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002185 if (IsArray) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002186 OB += '[';
2187 Elem->print(OB);
2188 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002189 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002190 OB += '.';
2191 Elem->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002192 }
2193 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002194 OB += " = ";
2195 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002196 }
2197};
2198
2199class BracedRangeExpr : public Node {
2200 const Node *First;
2201 const Node *Last;
2202 const Node *Init;
2203public:
2204 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2205 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2206
2207 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2208
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002209 void printLeft(OutputBuffer &OB) const override {
2210 OB += '[';
2211 First->print(OB);
2212 OB += " ... ";
2213 Last->print(OB);
2214 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002215 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002216 OB += " = ";
2217 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002218 }
2219};
2220
2221class FoldExpr : public Node {
2222 const Node *Pack, *Init;
2223 StringView OperatorName;
2224 bool IsLeftFold;
2225
2226public:
2227 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
2228 const Node *Init_)
2229 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2230 IsLeftFold(IsLeftFold_) {}
2231
2232 template<typename Fn> void match(Fn F) const {
2233 F(IsLeftFold, OperatorName, Pack, Init);
2234 }
2235
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002236 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002237 auto PrintPack = [&] {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002238 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002239 ParameterPackExpansion(Pack).print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002240 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002241 };
2242
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002243 OB.printOpen();
2244 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2245 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2246 // Fold expr operands are cast-expressions
2247 if (!IsLeftFold || Init != nullptr) {
2248 // '(init|pack) op '
2249 if (IsLeftFold)
2250 Init->printAsOperand(OB, Prec::Cast, true);
2251 else
2252 PrintPack();
2253 OB << " " << OperatorName << " ";
Richard Smithc20d1442018-08-20 20:14:49 +00002254 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002255 OB << "...";
2256 if (IsLeftFold || Init != nullptr) {
2257 // ' op (init|pack)'
2258 OB << " " << OperatorName << " ";
2259 if (IsLeftFold)
2260 PrintPack();
2261 else
2262 Init->printAsOperand(OB, Prec::Cast, true);
2263 }
2264 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002265 }
2266};
2267
2268class ThrowExpr : public Node {
2269 const Node *Op;
2270
2271public:
2272 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2273
2274 template<typename Fn> void match(Fn F) const { F(Op); }
2275
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002276 void printLeft(OutputBuffer &OB) const override {
2277 OB += "throw ";
2278 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002279 }
2280};
2281
2282class BoolExpr : public Node {
2283 bool Value;
2284
2285public:
2286 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2287
2288 template<typename Fn> void match(Fn F) const { F(Value); }
2289
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002290 void printLeft(OutputBuffer &OB) const override {
2291 OB += Value ? StringView("true") : StringView("false");
Richard Smithc20d1442018-08-20 20:14:49 +00002292 }
2293};
2294
Richard Smithdf1c14c2019-09-06 23:53:21 +00002295class StringLiteral : public Node {
2296 const Node *Type;
2297
2298public:
2299 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2300
2301 template<typename Fn> void match(Fn F) const { F(Type); }
2302
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002303 void printLeft(OutputBuffer &OB) const override {
2304 OB += "\"<";
2305 Type->print(OB);
2306 OB += ">\"";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002307 }
2308};
2309
2310class LambdaExpr : public Node {
2311 const Node *Type;
2312
Richard Smithdf1c14c2019-09-06 23:53:21 +00002313public:
2314 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2315
2316 template<typename Fn> void match(Fn F) const { F(Type); }
2317
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002318 void printLeft(OutputBuffer &OB) const override {
2319 OB += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002320 if (Type->getKind() == KClosureTypeName)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002321 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2322 OB += "{...}";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002323 }
2324};
2325
Erik Pilkington0a170f12020-05-13 14:13:37 -04002326class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002327 // ty(integer)
2328 const Node *Ty;
2329 StringView Integer;
2330
2331public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002332 EnumLiteral(const Node *Ty_, StringView Integer_)
2333 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002334
2335 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2336
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002337 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002338 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002339 Ty->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002340 OB.printClose();
Erik Pilkington0a170f12020-05-13 14:13:37 -04002341
2342 if (Integer[0] == 'n')
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002343 OB << "-" << Integer.dropFront(1);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002344 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002345 OB << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002346 }
2347};
2348
2349class IntegerLiteral : public Node {
2350 StringView Type;
2351 StringView Value;
2352
2353public:
2354 IntegerLiteral(StringView Type_, StringView Value_)
2355 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2356
2357 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2358
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002359 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002360 if (Type.size() > 3) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002361 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002362 OB += Type;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002363 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002364 }
2365
2366 if (Value[0] == 'n') {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002367 OB += '-';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002368 OB += Value.dropFront(1);
Richard Smithc20d1442018-08-20 20:14:49 +00002369 } else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002370 OB += Value;
Richard Smithc20d1442018-08-20 20:14:49 +00002371
2372 if (Type.size() <= 3)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002373 OB += Type;
Richard Smithc20d1442018-08-20 20:14:49 +00002374 }
2375};
2376
2377template <class Float> struct FloatData;
2378
2379namespace float_literal_impl {
2380constexpr Node::Kind getFloatLiteralKind(float *) {
2381 return Node::KFloatLiteral;
2382}
2383constexpr Node::Kind getFloatLiteralKind(double *) {
2384 return Node::KDoubleLiteral;
2385}
2386constexpr Node::Kind getFloatLiteralKind(long double *) {
2387 return Node::KLongDoubleLiteral;
2388}
2389}
2390
2391template <class Float> class FloatLiteralImpl : public Node {
2392 const StringView Contents;
2393
2394 static constexpr Kind KindForClass =
2395 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2396
2397public:
2398 FloatLiteralImpl(StringView Contents_)
2399 : Node(KindForClass), Contents(Contents_) {}
2400
2401 template<typename Fn> void match(Fn F) const { F(Contents); }
2402
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002403 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002404 const char *first = Contents.begin();
2405 const char *last = Contents.end() + 1;
2406
2407 const size_t N = FloatData<Float>::mangled_size;
2408 if (static_cast<std::size_t>(last - first) > N) {
2409 last = first + N;
2410 union {
2411 Float value;
2412 char buf[sizeof(Float)];
2413 };
2414 const char *t = first;
2415 char *e = buf;
2416 for (; t != last; ++t, ++e) {
2417 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2418 : static_cast<unsigned>(*t - 'a' + 10);
2419 ++t;
2420 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2421 : static_cast<unsigned>(*t - 'a' + 10);
2422 *e = static_cast<char>((d1 << 4) + d0);
2423 }
2424#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2425 std::reverse(buf, e);
2426#endif
2427 char num[FloatData<Float>::max_demangled_size] = {0};
2428 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002429 OB += StringView(num, num + n);
Richard Smithc20d1442018-08-20 20:14:49 +00002430 }
2431 }
2432};
2433
2434using FloatLiteral = FloatLiteralImpl<float>;
2435using DoubleLiteral = FloatLiteralImpl<double>;
2436using LongDoubleLiteral = FloatLiteralImpl<long double>;
2437
2438/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2439/// appropriate derived class.
2440template<typename Fn>
2441void Node::visit(Fn F) const {
2442 switch (K) {
2443#define CASE(X) case K ## X: return F(static_cast<const X*>(this));
2444 FOR_EACH_NODE_KIND(CASE)
2445#undef CASE
2446 }
2447 assert(0 && "unknown mangling node kind");
2448}
2449
2450/// Determine the kind of a node from its type.
2451template<typename NodeT> struct NodeKind;
2452#define SPECIALIZATION(X) \
2453 template<> struct NodeKind<X> { \
2454 static constexpr Node::Kind Kind = Node::K##X; \
2455 static constexpr const char *name() { return #X; } \
2456 };
2457FOR_EACH_NODE_KIND(SPECIALIZATION)
2458#undef SPECIALIZATION
2459
2460#undef FOR_EACH_NODE_KIND
2461
Pavel Labathba825192018-10-16 14:29:14 +00002462template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002463 const char *First;
2464 const char *Last;
2465
2466 // Name stack, this is used by the parser to hold temporary names that were
2467 // parsed. The parser collapses multiple names into new nodes to construct
2468 // the AST. Once the parser is finished, names.size() == 1.
2469 PODSmallVector<Node *, 32> Names;
2470
2471 // Substitution table. Itanium supports name substitutions as a means of
2472 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2473 // table.
2474 PODSmallVector<Node *, 32> Subs;
2475
Richard Smithdf1c14c2019-09-06 23:53:21 +00002476 using TemplateParamList = PODSmallVector<Node *, 8>;
2477
2478 class ScopedTemplateParamList {
2479 AbstractManglingParser *Parser;
2480 size_t OldNumTemplateParamLists;
2481 TemplateParamList Params;
2482
2483 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002484 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2485 : Parser(TheParser),
2486 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002487 Parser->TemplateParams.push_back(&Params);
2488 }
2489 ~ScopedTemplateParamList() {
2490 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2491 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2492 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002493 };
2494
Richard Smithc20d1442018-08-20 20:14:49 +00002495 // Template parameter table. Like the above, but referenced like "T42_".
2496 // This has a smaller size compared to Subs and Names because it can be
2497 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002498 TemplateParamList OuterTemplateParams;
2499
2500 // Lists of template parameters indexed by template parameter depth,
2501 // referenced like "TL2_4_". If nonempty, element 0 is always
2502 // OuterTemplateParams; inner elements are always template parameter lists of
2503 // lambda expressions. For a generic lambda with no explicit template
2504 // parameter list, the corresponding parameter list pointer will be null.
2505 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002506
2507 // Set of unresolved forward <template-param> references. These can occur in a
2508 // conversion operator's type, and are resolved in the enclosing <encoding>.
2509 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2510
Richard Smithc20d1442018-08-20 20:14:49 +00002511 bool TryToParseTemplateArgs = true;
2512 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002513 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2514
2515 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002516
2517 Alloc ASTAllocator;
2518
Pavel Labathba825192018-10-16 14:29:14 +00002519 AbstractManglingParser(const char *First_, const char *Last_)
2520 : First(First_), Last(Last_) {}
2521
2522 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002523
2524 void reset(const char *First_, const char *Last_) {
2525 First = First_;
2526 Last = Last_;
2527 Names.clear();
2528 Subs.clear();
2529 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002530 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002531 TryToParseTemplateArgs = true;
2532 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002533 for (int I = 0; I != 3; ++I)
2534 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002535 ASTAllocator.reset();
2536 }
2537
Richard Smithb485b352018-08-24 23:30:26 +00002538 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002539 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2540 }
2541
2542 template <class It> NodeArray makeNodeArray(It begin, It end) {
2543 size_t sz = static_cast<size_t>(end - begin);
2544 void *mem = ASTAllocator.allocateNodeArray(sz);
2545 Node **data = new (mem) Node *[sz];
2546 std::copy(begin, end, data);
2547 return NodeArray(data, sz);
2548 }
2549
2550 NodeArray popTrailingNodeArray(size_t FromPosition) {
2551 assert(FromPosition <= Names.size());
2552 NodeArray res =
2553 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2554 Names.dropBack(FromPosition);
2555 return res;
2556 }
2557
2558 bool consumeIf(StringView S) {
2559 if (StringView(First, Last).startsWith(S)) {
2560 First += S.size();
2561 return true;
2562 }
2563 return false;
2564 }
2565
2566 bool consumeIf(char C) {
2567 if (First != Last && *First == C) {
2568 ++First;
2569 return true;
2570 }
2571 return false;
2572 }
2573
2574 char consume() { return First != Last ? *First++ : '\0'; }
2575
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08002576 char look(unsigned Lookahead = 0) const {
Richard Smithc20d1442018-08-20 20:14:49 +00002577 if (static_cast<size_t>(Last - First) <= Lookahead)
2578 return '\0';
2579 return First[Lookahead];
2580 }
2581
2582 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2583
2584 StringView parseNumber(bool AllowNegative = false);
2585 Qualifiers parseCVQualifiers();
2586 bool parsePositiveInteger(size_t *Out);
2587 StringView parseBareSourceName();
2588
2589 bool parseSeqId(size_t *Out);
2590 Node *parseSubstitution();
2591 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002592 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002593 Node *parseTemplateArgs(bool TagTemplates = false);
2594 Node *parseTemplateArg();
2595
2596 /// Parse the <expr> production.
2597 Node *parseExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002598 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2599 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00002600 Node *parseIntegerLiteral(StringView Lit);
2601 Node *parseExprPrimary();
2602 template <class Float> Node *parseFloatingLiteral();
2603 Node *parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00002604 Node *parseConversionExpr();
2605 Node *parseBracedExpr();
2606 Node *parseFoldExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002607 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07002608 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002609
2610 /// Parse the <type> production.
2611 Node *parseType();
2612 Node *parseFunctionType();
2613 Node *parseVectorType();
2614 Node *parseDecltype();
2615 Node *parseArrayType();
2616 Node *parsePointerToMemberType();
2617 Node *parseClassEnumType();
2618 Node *parseQualifiedType();
2619
2620 Node *parseEncoding();
2621 bool parseCallOffset();
2622 Node *parseSpecialName();
2623
2624 /// Holds some extra information about a <name> that is being parsed. This
2625 /// information is only pertinent if the <name> refers to an <encoding>.
2626 struct NameState {
2627 bool CtorDtorConversion = false;
2628 bool EndsWithTemplateArgs = false;
2629 Qualifiers CVQualifiers = QualNone;
2630 FunctionRefQual ReferenceQualifier = FrefQualNone;
2631 size_t ForwardTemplateRefsBegin;
2632
Pavel Labathba825192018-10-16 14:29:14 +00002633 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002634 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2635 };
2636
2637 bool resolveForwardTemplateRefs(NameState &State) {
2638 size_t I = State.ForwardTemplateRefsBegin;
2639 size_t E = ForwardTemplateRefs.size();
2640 for (; I < E; ++I) {
2641 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002642 if (TemplateParams.empty() || !TemplateParams[0] ||
2643 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002644 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002645 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002646 }
2647 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2648 return false;
2649 }
2650
2651 /// Parse the <name> production>
2652 Node *parseName(NameState *State = nullptr);
2653 Node *parseLocalName(NameState *State);
2654 Node *parseOperatorName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002655 bool parseModuleNameOpt(ModuleName *&Module);
2656 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
Richard Smithc20d1442018-08-20 20:14:49 +00002657 Node *parseUnnamedTypeName(NameState *State);
2658 Node *parseSourceName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002659 Node *parseUnscopedName(NameState *State, bool *isSubstName);
Richard Smithc20d1442018-08-20 20:14:49 +00002660 Node *parseNestedName(NameState *State);
2661 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2662
2663 Node *parseAbiTags(Node *N);
2664
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002665 struct OperatorInfo {
2666 enum OIKind : unsigned char {
2667 Prefix, // Prefix unary: @ expr
2668 Postfix, // Postfix unary: expr @
2669 Binary, // Binary: lhs @ rhs
2670 Array, // Array index: lhs [ rhs ]
2671 Member, // Member access: lhs @ rhs
2672 New, // New
2673 Del, // Delete
2674 Call, // Function call: expr (expr*)
2675 CCast, // C cast: (type)expr
2676 Conditional, // Conditional: expr ? expr : expr
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08002677 NameOnly, // Overload only, not allowed in expression.
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002678 // Below do not have operator names
2679 NamedCast, // Named cast, @<type>(expr)
2680 OfIdOp, // alignof, sizeof, typeid
2681
2682 Unnameable = NamedCast,
2683 };
2684 char Enc[2]; // Encoding
2685 OIKind Kind; // Kind of operator
2686 bool Flag : 1; // Entry-specific flag
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002687 Node::Prec Prec : 7; // Precedence
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002688 const char *Name; // Spelling
2689
2690 public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002691 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2692 const char *N)
2693 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002694
2695 public:
2696 bool operator<(const OperatorInfo &Other) const {
2697 return *this < Other.Enc;
2698 }
2699 bool operator<(const char *Peek) const {
2700 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2701 }
2702 bool operator==(const char *Peek) const {
2703 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2704 }
2705 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2706
2707 public:
2708 StringView getSymbol() const {
2709 StringView Res = Name;
2710 if (Kind < Unnameable) {
2711 assert(Res.startsWith("operator") &&
2712 "operator name does not start with 'operator'");
2713 Res = Res.dropFront(sizeof("operator") - 1);
2714 Res.consumeFront(' ');
2715 }
2716 return Res;
2717 }
2718 StringView getName() const { return Name; }
2719 OIKind getKind() const { return Kind; }
2720 bool getFlag() const { return Flag; }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002721 Node::Prec getPrecedence() const { return Prec; }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002722 };
2723 const OperatorInfo *parseOperatorEncoding();
2724
Richard Smithc20d1442018-08-20 20:14:49 +00002725 /// Parse the <unresolved-name> production.
Nathan Sidwell77c52e22022-01-28 11:59:03 -08002726 Node *parseUnresolvedName(bool Global);
Richard Smithc20d1442018-08-20 20:14:49 +00002727 Node *parseSimpleId();
2728 Node *parseBaseUnresolvedName();
2729 Node *parseUnresolvedType();
2730 Node *parseDestructorName();
2731
2732 /// Top-level entry point into the parser.
2733 Node *parse();
2734};
2735
2736const char* parse_discriminator(const char* first, const char* last);
2737
2738// <name> ::= <nested-name> // N
2739// ::= <local-name> # See Scope Encoding below // Z
2740// ::= <unscoped-template-name> <template-args>
2741// ::= <unscoped-name>
2742//
2743// <unscoped-template-name> ::= <unscoped-name>
2744// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002745template <typename Derived, typename Alloc>
2746Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002747 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002748 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002749 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002750 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002751
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002752 Node *Result = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002753 bool IsSubst = false;
2754
2755 Result = getDerived().parseUnscopedName(State, &IsSubst);
2756 if (!Result)
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002757 return nullptr;
2758
2759 if (look() == 'I') {
2760 // ::= <unscoped-template-name> <template-args>
2761 if (!IsSubst)
2762 // An unscoped-template-name is substitutable.
2763 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00002764 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002765 if (TA == nullptr)
2766 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002767 if (State)
2768 State->EndsWithTemplateArgs = true;
2769 Result = make<NameWithTemplateArgs>(Result, TA);
2770 } else if (IsSubst) {
2771 // The substitution case must be followed by <template-args>.
2772 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002773 }
2774
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002775 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00002776}
2777
2778// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2779// := Z <function encoding> E s [<discriminator>]
2780// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002781template <typename Derived, typename Alloc>
2782Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002783 if (!consumeIf('Z'))
2784 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002785 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002786 if (Encoding == nullptr || !consumeIf('E'))
2787 return nullptr;
2788
2789 if (consumeIf('s')) {
2790 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002791 auto *StringLitName = make<NameType>("string literal");
2792 if (!StringLitName)
2793 return nullptr;
2794 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002795 }
2796
2797 if (consumeIf('d')) {
2798 parseNumber(true);
2799 if (!consumeIf('_'))
2800 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002801 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002802 if (N == nullptr)
2803 return nullptr;
2804 return make<LocalName>(Encoding, N);
2805 }
2806
Pavel Labathba825192018-10-16 14:29:14 +00002807 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002808 if (Entity == nullptr)
2809 return nullptr;
2810 First = parse_discriminator(First, Last);
2811 return make<LocalName>(Encoding, Entity);
2812}
2813
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08002814// <unscoped-name> ::= [L]* <unqualified-name>
2815// ::= St [L]* <unqualified-name> # ::std::
2816// [*] extension
Pavel Labathba825192018-10-16 14:29:14 +00002817template <typename Derived, typename Alloc>
2818Node *
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002819AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2820 bool *IsSubst) {
2821
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002822 Node *Std = nullptr;
2823 if (consumeIf("St")) {
2824 Std = make<NameType>("std");
2825 if (Std == nullptr)
Nathan Sidwell200e97c2022-01-21 11:37:01 -08002826 return nullptr;
2827 }
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002828 consumeIf('L');
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002829
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002830 Node *Res = nullptr;
2831 ModuleName *Module = nullptr;
2832 if (look() == 'S') {
2833 Node *S = getDerived().parseSubstitution();
2834 if (!S)
2835 return nullptr;
2836 if (S->getKind() == Node::KModuleName)
2837 Module = static_cast<ModuleName *>(S);
2838 else if (IsSubst && Std == nullptr) {
2839 Res = S;
2840 *IsSubst = true;
2841 } else {
2842 return nullptr;
2843 }
2844 }
2845
2846 if (Res == nullptr)
2847 Res = getDerived().parseUnqualifiedName(State, Std, Module);
2848
2849 return Res;
Richard Smithc20d1442018-08-20 20:14:49 +00002850}
2851
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002852// <unqualified-name> ::= [<module-name>] <operator-name> [<abi-tags>]
2853// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
2854// ::= [<module-name>] <source-name> [<abi-tags>]
2855// ::= [<module-name>] <unnamed-type-name> [<abi-tags>]
2856// # structured binding declaration
2857// ::= [<module-name>] DC <source-name>+ E
Pavel Labathba825192018-10-16 14:29:14 +00002858template <typename Derived, typename Alloc>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002859Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2860 NameState *State, Node *Scope, ModuleName *Module) {
2861 if (getDerived().parseModuleNameOpt(Module))
2862 return nullptr;
2863
Richard Smithc20d1442018-08-20 20:14:49 +00002864 Node *Result;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002865 if (look() == 'U') {
Pavel Labathba825192018-10-16 14:29:14 +00002866 Result = getDerived().parseUnnamedTypeName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002867 } else if (look() >= '1' && look() <= '9') {
Pavel Labathba825192018-10-16 14:29:14 +00002868 Result = getDerived().parseSourceName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002869 } else if (consumeIf("DC")) {
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002870 // Structured binding
Richard Smithc20d1442018-08-20 20:14:49 +00002871 size_t BindingsBegin = Names.size();
2872 do {
Pavel Labathba825192018-10-16 14:29:14 +00002873 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002874 if (Binding == nullptr)
2875 return nullptr;
2876 Names.push_back(Binding);
2877 } while (!consumeIf('E'));
2878 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002879 } else if (look() == 'C' || look() == 'D') {
2880 // A <ctor-dtor-name>.
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002881 if (Scope == nullptr || Module != nullptr)
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002882 return nullptr;
2883 Result = getDerived().parseCtorDtorName(Scope, State);
2884 } else {
Pavel Labathba825192018-10-16 14:29:14 +00002885 Result = getDerived().parseOperatorName(State);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002886 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002887
David Blaikie019fb1b2022-03-30 20:18:40 +00002888 if (Result != nullptr && Module != nullptr)
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002889 Result = make<ModuleEntity>(Module, Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002890 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002891 Result = getDerived().parseAbiTags(Result);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002892 if (Result != nullptr && Scope != nullptr)
2893 Result = make<NestedName>(Scope, Result);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002894
Richard Smithc20d1442018-08-20 20:14:49 +00002895 return Result;
2896}
2897
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002898// <module-name> ::= <module-subname>
2899// ::= <module-name> <module-subname>
2900// ::= <substitution> # passed in by caller
2901// <module-subname> ::= W <source-name>
2902// ::= W P <source-name>
2903template <typename Derived, typename Alloc>
2904bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2905 ModuleName *&Module) {
2906 while (consumeIf('W')) {
2907 bool IsPartition = consumeIf('P');
2908 Node *Sub = getDerived().parseSourceName(nullptr);
2909 if (!Sub)
2910 return true;
2911 Module =
2912 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2913 Subs.push_back(Module);
2914 }
2915
2916 return false;
2917}
2918
Richard Smithc20d1442018-08-20 20:14:49 +00002919// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2920// ::= <closure-type-name>
2921//
2922// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2923//
2924// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002925template <typename Derived, typename Alloc>
2926Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002927AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2928 // <template-params> refer to the innermost <template-args>. Clear out any
2929 // outer args that we may have inserted into TemplateParams.
2930 if (State != nullptr)
2931 TemplateParams.clear();
2932
Richard Smithc20d1442018-08-20 20:14:49 +00002933 if (consumeIf("Ut")) {
2934 StringView Count = parseNumber();
2935 if (!consumeIf('_'))
2936 return nullptr;
2937 return make<UnnamedTypeName>(Count);
2938 }
2939 if (consumeIf("Ul")) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002940 SwapAndRestore<size_t> SwapParams(ParsingLambdaParamsAtLevel,
2941 TemplateParams.size());
2942 ScopedTemplateParamList LambdaTemplateParams(this);
2943
2944 size_t ParamsBegin = Names.size();
2945 while (look() == 'T' &&
2946 StringView("yptn").find(look(1)) != StringView::npos) {
2947 Node *T = parseTemplateParamDecl();
2948 if (!T)
2949 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002950 Names.push_back(T);
2951 }
2952 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2953
2954 // FIXME: If TempParams is empty and none of the function parameters
2955 // includes 'auto', we should remove LambdaTemplateParams from the
2956 // TemplateParams list. Unfortunately, we don't find out whether there are
2957 // any 'auto' parameters until too late in an example such as:
2958 //
2959 // template<typename T> void f(
2960 // decltype([](decltype([]<typename T>(T v) {}),
2961 // auto) {})) {}
2962 // template<typename T> void f(
2963 // decltype([](decltype([]<typename T>(T w) {}),
2964 // int) {})) {}
2965 //
2966 // Here, the type of v is at level 2 but the type of w is at level 1. We
2967 // don't find this out until we encounter the type of the next parameter.
2968 //
2969 // However, compilers can't actually cope with the former example in
2970 // practice, and it's likely to be made ill-formed in future, so we don't
2971 // need to support it here.
2972 //
2973 // If we encounter an 'auto' in the function parameter types, we will
2974 // recreate a template parameter scope for it, but any intervening lambdas
2975 // will be parsed in the 'wrong' template parameter depth.
2976 if (TempParams.empty())
2977 TemplateParams.pop_back();
2978
Richard Smithc20d1442018-08-20 20:14:49 +00002979 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002980 do {
Pavel Labathba825192018-10-16 14:29:14 +00002981 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002982 if (P == nullptr)
2983 return nullptr;
2984 Names.push_back(P);
2985 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002986 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002987 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2988
Richard Smithc20d1442018-08-20 20:14:49 +00002989 StringView Count = parseNumber();
2990 if (!consumeIf('_'))
2991 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002992 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002993 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002994 if (consumeIf("Ub")) {
2995 (void)parseNumber();
2996 if (!consumeIf('_'))
2997 return nullptr;
2998 return make<NameType>("'block-literal'");
2999 }
Richard Smithc20d1442018-08-20 20:14:49 +00003000 return nullptr;
3001}
3002
3003// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00003004template <typename Derived, typename Alloc>
3005Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00003006 size_t Length = 0;
3007 if (parsePositiveInteger(&Length))
3008 return nullptr;
3009 if (numLeft() < Length || Length == 0)
3010 return nullptr;
3011 StringView Name(First, First + Length);
3012 First += Length;
3013 if (Name.startsWith("_GLOBAL__N"))
3014 return make<NameType>("(anonymous namespace)");
3015 return make<NameType>(Name);
3016}
3017
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003018// If the next 2 chars are an operator encoding, consume them and return their
3019// OperatorInfo. Otherwise return nullptr.
3020template <typename Derived, typename Alloc>
3021const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
3022AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
3023 static const OperatorInfo Ops[] = {
3024 // Keep ordered by encoding
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003025 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
3026 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
3027 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
3028 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
3029 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
3030 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary,
3031 "alignof "},
3032 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
3033 "operator co_await"},
3034 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
3035 "alignof "},
3036 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
3037 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
3038 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
3039 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
3040 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast,
3041 "operator"}, // C Cast
3042 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
3043 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
3044 "operator delete[]"},
3045 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3046 "dynamic_cast"},
3047 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
3048 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
3049 "operator delete"},
3050 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3051 "operator.*"},
3052 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
3053 "operator."},
3054 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
3055 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
3056 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
3057 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
3058 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
3059 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
3060 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
3061 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
3062 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
3063 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
3064 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
3065 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
3066 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
3067 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
3068 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3069 "operator*"},
3070 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
3071 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
3072 "operator new[]"},
3073 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
3074 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
3075 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
3076 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary,
3077 "operator new"},
3078 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
3079 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
3080 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
3081 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
3082 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
3083 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3084 "operator->*"},
3085 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
3086 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
3087 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
3088 "operator->"},
3089 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
3090 "operator?"},
3091 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
3092 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
3093 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3094 "reinterpret_cast"},
3095 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3096 "operator%"},
3097 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3098 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3099 "static_cast"},
3100 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3101 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3102 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
3103 "sizeof "},
3104 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3105 "typeid "},
3106 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix,
3107 "typeid "},
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003108 };
3109 const auto NumOps = sizeof(Ops) / sizeof(Ops[0]);
3110
3111#ifndef NDEBUG
3112 {
3113 // Verify table order.
3114 static bool Done;
3115 if (!Done) {
3116 Done = true;
3117 for (const auto *Op = &Ops[0]; Op != &Ops[NumOps - 1]; Op++)
3118 assert(Op[0] < Op[1] && "Operator table is not ordered");
3119 }
3120 }
3121#endif
3122
3123 if (numLeft() < 2)
3124 return nullptr;
3125
3126 auto Op = std::lower_bound(
3127 &Ops[0], &Ops[NumOps], First,
3128 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3129 if (Op == &Ops[NumOps] || *Op != First)
3130 return nullptr;
3131
3132 First += 2;
3133 return Op;
3134}
3135
3136// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003137// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003138// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003139template <typename Derived, typename Alloc>
3140Node *
3141AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003142 if (const auto *Op = parseOperatorEncoding()) {
3143 if (Op->getKind() == OperatorInfo::CCast) {
3144 // ::= cv <type> # (cast)
Richard Smithc20d1442018-08-20 20:14:49 +00003145 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
3146 // If we're parsing an encoding, State != nullptr and the conversion
3147 // operators' <type> could have a <template-param> that refers to some
3148 // <template-arg>s further ahead in the mangled name.
3149 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
3150 PermitForwardTemplateReferences ||
3151 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003152 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003153 if (Ty == nullptr)
3154 return nullptr;
3155 if (State) State->CtorDtorConversion = true;
3156 return make<ConversionOperatorType>(Ty);
3157 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003158
3159 if (Op->getKind() >= OperatorInfo::Unnameable)
3160 /* Not a nameable operator. */
3161 return nullptr;
3162 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3163 /* Not a nameable MemberExpr */
3164 return nullptr;
3165
3166 return make<NameType>(Op->getName());
3167 }
3168
3169 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003170 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003171 Node *SN = getDerived().parseSourceName(State);
3172 if (SN == nullptr)
3173 return nullptr;
3174 return make<LiteralOperator>(SN);
3175 }
3176
3177 if (consumeIf('v')) {
3178 // ::= v <digit> <source-name> # vendor extended operator
3179 if (look() >= '0' && look() <= '9') {
3180 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003181 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003182 if (SN == nullptr)
3183 return nullptr;
3184 return make<ConversionOperatorType>(SN);
3185 }
3186 return nullptr;
3187 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003188
Richard Smithc20d1442018-08-20 20:14:49 +00003189 return nullptr;
3190}
3191
3192// <ctor-dtor-name> ::= C1 # complete object constructor
3193// ::= C2 # base object constructor
3194// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003195// extension ::= C4 # gcc old-style "[unified]" constructor
3196// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003197// ::= D0 # deleting destructor
3198// ::= D1 # complete object destructor
3199// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003200// extension ::= D4 # gcc old-style "[unified]" destructor
3201// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003202template <typename Derived, typename Alloc>
3203Node *
3204AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3205 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003206 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3207 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3208 switch (SSK) {
3209 case SpecialSubKind::string:
3210 case SpecialSubKind::istream:
3211 case SpecialSubKind::ostream:
3212 case SpecialSubKind::iostream:
3213 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00003214 if (!SoFar)
3215 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00003216 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003217 default:
3218 break;
3219 }
3220 }
3221
3222 if (consumeIf('C')) {
3223 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003224 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3225 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003226 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003227 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003228 ++First;
3229 if (State) State->CtorDtorConversion = true;
3230 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003231 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003232 return nullptr;
3233 }
Nico Weber29294792019-04-03 23:14:33 +00003234 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003235 }
3236
Nico Weber29294792019-04-03 23:14:33 +00003237 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3238 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003239 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003240 First += 2;
3241 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003242 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003243 }
3244
3245 return nullptr;
3246}
3247
3248// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3249// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3250//
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003251// <prefix> ::= <prefix> [L]* <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003252// ::= <template-prefix> <template-args>
3253// ::= <template-param>
3254// ::= <decltype>
3255// ::= # empty
3256// ::= <substitution>
3257// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003258// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003259//
3260// <data-member-prefix> := <member source-name> [<template-args>] M
3261//
3262// <template-prefix> ::= <prefix> <template unqualified-name>
3263// ::= <template-param>
3264// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003265template <typename Derived, typename Alloc>
3266Node *
3267AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003268 if (!consumeIf('N'))
3269 return nullptr;
3270
3271 Qualifiers CVTmp = parseCVQualifiers();
3272 if (State) State->CVQualifiers = CVTmp;
3273
3274 if (consumeIf('O')) {
3275 if (State) State->ReferenceQualifier = FrefQualRValue;
3276 } else if (consumeIf('R')) {
3277 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003278 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003279 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003280 }
Richard Smithc20d1442018-08-20 20:14:49 +00003281
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003282 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003283 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003284 if (State)
3285 // Only set end-with-template on the case that does that.
3286 State->EndsWithTemplateArgs = false;
3287
Richard Smithc20d1442018-08-20 20:14:49 +00003288 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003289 // ::= <template-param>
3290 if (SoFar != nullptr)
3291 return nullptr; // Cannot have a prefix.
3292 SoFar = getDerived().parseTemplateParam();
3293 } else if (look() == 'I') {
3294 // ::= <template-prefix> <template-args>
3295 if (SoFar == nullptr)
3296 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003297 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003298 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003299 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003300 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3301 // Semantically <template-args> <template-args> cannot be generated by a
3302 // C++ entity. There will always be [something like] a name between
3303 // them.
3304 return nullptr;
3305 if (State)
3306 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003307 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003308 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3309 // ::= <decltype>
3310 if (SoFar != nullptr)
3311 return nullptr; // Cannot have a prefix.
3312 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003313 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003314 ModuleName *Module = nullptr;
3315 bool IsLocal = consumeIf('L'); // extension
3316
3317 if (look() == 'S') {
3318 // ::= <substitution>
3319 Node *S = nullptr;
3320 if (look(1) == 't') {
3321 First += 2;
3322 S = make<NameType>("std");
3323 } else {
3324 S = getDerived().parseSubstitution();
3325 }
3326 if (!S)
3327 return nullptr;
3328 if (S->getKind() == Node::KModuleName) {
3329 Module = static_cast<ModuleName *>(S);
3330 } else if (SoFar != nullptr || IsLocal) {
3331 return nullptr; // Cannot have a prefix.
3332 } else {
3333 SoFar = S;
3334 continue; // Do not push a new substitution.
3335 }
3336 }
3337
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003338 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003339 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003340 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003341
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003342 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003343 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003344 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003345
3346 // No longer used.
3347 // <data-member-prefix> := <member source-name> [<template-args>] M
3348 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003349 }
3350
3351 if (SoFar == nullptr || Subs.empty())
3352 return nullptr;
3353
3354 Subs.pop_back();
3355 return SoFar;
3356}
3357
3358// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003359template <typename Derived, typename Alloc>
3360Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3361 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003362 if (SN == nullptr)
3363 return nullptr;
3364 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003365 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003366 if (TA == nullptr)
3367 return nullptr;
3368 return make<NameWithTemplateArgs>(SN, TA);
3369 }
3370 return SN;
3371}
3372
3373// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3374// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003375template <typename Derived, typename Alloc>
3376Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003377 Node *Result;
3378 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003379 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003380 else
Pavel Labathba825192018-10-16 14:29:14 +00003381 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003382 if (Result == nullptr)
3383 return nullptr;
3384 return make<DtorName>(Result);
3385}
3386
3387// <unresolved-type> ::= <template-param>
3388// ::= <decltype>
3389// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003390template <typename Derived, typename Alloc>
3391Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003392 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003393 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003394 if (TP == nullptr)
3395 return nullptr;
3396 Subs.push_back(TP);
3397 return TP;
3398 }
3399 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003400 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003401 if (DT == nullptr)
3402 return nullptr;
3403 Subs.push_back(DT);
3404 return DT;
3405 }
Pavel Labathba825192018-10-16 14:29:14 +00003406 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003407}
3408
3409// <base-unresolved-name> ::= <simple-id> # unresolved name
3410// extension ::= <operator-name> # unresolved operator-function-id
3411// extension ::= <operator-name> <template-args> # unresolved operator template-id
3412// ::= on <operator-name> # unresolved operator-function-id
3413// ::= on <operator-name> <template-args> # unresolved operator template-id
3414// ::= dn <destructor-name> # destructor or pseudo-destructor;
3415// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003416template <typename Derived, typename Alloc>
3417Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003418 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003419 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003420
3421 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003422 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003423
3424 consumeIf("on");
3425
Pavel Labathba825192018-10-16 14:29:14 +00003426 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003427 if (Oper == nullptr)
3428 return nullptr;
3429 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003430 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003431 if (TA == nullptr)
3432 return nullptr;
3433 return make<NameWithTemplateArgs>(Oper, TA);
3434 }
3435 return Oper;
3436}
3437
3438// <unresolved-name>
3439// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3440// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3441// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3442// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003443// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003444// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3445// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3446// # T::N::x /decltype(p)::N::x
3447// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3448//
3449// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003450template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003451Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003452 Node *SoFar = nullptr;
3453
3454 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3455 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3456 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003457 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003458 if (SoFar == nullptr)
3459 return nullptr;
3460
3461 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003462 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003463 if (TA == nullptr)
3464 return nullptr;
3465 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003466 if (!SoFar)
3467 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003468 }
3469
3470 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003471 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003472 if (Qual == nullptr)
3473 return nullptr;
3474 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003475 if (!SoFar)
3476 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003477 }
3478
Pavel Labathba825192018-10-16 14:29:14 +00003479 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003480 if (Base == nullptr)
3481 return nullptr;
3482 return make<QualifiedName>(SoFar, Base);
3483 }
3484
Richard Smithc20d1442018-08-20 20:14:49 +00003485 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3486 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003487 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003488 if (SoFar == nullptr)
3489 return nullptr;
3490 if (Global)
3491 SoFar = make<GlobalQualifiedName>(SoFar);
3492 return SoFar;
3493 }
3494
3495 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3496 if (std::isdigit(look())) {
3497 do {
Pavel Labathba825192018-10-16 14:29:14 +00003498 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003499 if (Qual == nullptr)
3500 return nullptr;
3501 if (SoFar)
3502 SoFar = make<QualifiedName>(SoFar, Qual);
3503 else if (Global)
3504 SoFar = make<GlobalQualifiedName>(Qual);
3505 else
3506 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003507 if (!SoFar)
3508 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003509 } while (!consumeIf('E'));
3510 }
3511 // sr <unresolved-type> <base-unresolved-name>
3512 // sr <unresolved-type> <template-args> <base-unresolved-name>
3513 else {
Pavel Labathba825192018-10-16 14:29:14 +00003514 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003515 if (SoFar == nullptr)
3516 return nullptr;
3517
3518 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003519 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003520 if (TA == nullptr)
3521 return nullptr;
3522 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003523 if (!SoFar)
3524 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003525 }
3526 }
3527
3528 assert(SoFar != nullptr);
3529
Pavel Labathba825192018-10-16 14:29:14 +00003530 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003531 if (Base == nullptr)
3532 return nullptr;
3533 return make<QualifiedName>(SoFar, Base);
3534}
3535
3536// <abi-tags> ::= <abi-tag> [<abi-tags>]
3537// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003538template <typename Derived, typename Alloc>
3539Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003540 while (consumeIf('B')) {
3541 StringView SN = parseBareSourceName();
3542 if (SN.empty())
3543 return nullptr;
3544 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003545 if (!N)
3546 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003547 }
3548 return N;
3549}
3550
3551// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003552template <typename Alloc, typename Derived>
3553StringView
3554AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003555 const char *Tmp = First;
3556 if (AllowNegative)
3557 consumeIf('n');
3558 if (numLeft() == 0 || !std::isdigit(*First))
3559 return StringView();
3560 while (numLeft() != 0 && std::isdigit(*First))
3561 ++First;
3562 return StringView(Tmp, First);
3563}
3564
3565// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003566template <typename Alloc, typename Derived>
3567bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003568 *Out = 0;
3569 if (look() < '0' || look() > '9')
3570 return true;
3571 while (look() >= '0' && look() <= '9') {
3572 *Out *= 10;
3573 *Out += static_cast<size_t>(consume() - '0');
3574 }
3575 return false;
3576}
3577
Pavel Labathba825192018-10-16 14:29:14 +00003578template <typename Alloc, typename Derived>
3579StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003580 size_t Int = 0;
3581 if (parsePositiveInteger(&Int) || numLeft() < Int)
3582 return StringView();
3583 StringView R(First, First + Int);
3584 First += Int;
3585 return R;
3586}
3587
3588// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3589//
3590// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3591// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3592// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3593//
3594// <ref-qualifier> ::= R # & ref-qualifier
3595// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003596template <typename Derived, typename Alloc>
3597Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003598 Qualifiers CVQuals = parseCVQualifiers();
3599
3600 Node *ExceptionSpec = nullptr;
3601 if (consumeIf("Do")) {
3602 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003603 if (!ExceptionSpec)
3604 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003605 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003606 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003607 if (E == nullptr || !consumeIf('E'))
3608 return nullptr;
3609 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003610 if (!ExceptionSpec)
3611 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003612 } else if (consumeIf("Dw")) {
3613 size_t SpecsBegin = Names.size();
3614 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003615 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003616 if (T == nullptr)
3617 return nullptr;
3618 Names.push_back(T);
3619 }
3620 ExceptionSpec =
3621 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003622 if (!ExceptionSpec)
3623 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003624 }
3625
3626 consumeIf("Dx"); // transaction safe
3627
3628 if (!consumeIf('F'))
3629 return nullptr;
3630 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003631 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003632 if (ReturnType == nullptr)
3633 return nullptr;
3634
3635 FunctionRefQual ReferenceQualifier = FrefQualNone;
3636 size_t ParamsBegin = Names.size();
3637 while (true) {
3638 if (consumeIf('E'))
3639 break;
3640 if (consumeIf('v'))
3641 continue;
3642 if (consumeIf("RE")) {
3643 ReferenceQualifier = FrefQualLValue;
3644 break;
3645 }
3646 if (consumeIf("OE")) {
3647 ReferenceQualifier = FrefQualRValue;
3648 break;
3649 }
Pavel Labathba825192018-10-16 14:29:14 +00003650 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003651 if (T == nullptr)
3652 return nullptr;
3653 Names.push_back(T);
3654 }
3655
3656 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3657 return make<FunctionType>(ReturnType, Params, CVQuals,
3658 ReferenceQualifier, ExceptionSpec);
3659}
3660
3661// extension:
3662// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3663// ::= Dv [<dimension expression>] _ <element type>
3664// <extended element type> ::= <element type>
3665// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003666template <typename Derived, typename Alloc>
3667Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003668 if (!consumeIf("Dv"))
3669 return nullptr;
3670 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003671 Node *DimensionNumber = make<NameType>(parseNumber());
3672 if (!DimensionNumber)
3673 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003674 if (!consumeIf('_'))
3675 return nullptr;
3676 if (consumeIf('p'))
3677 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003678 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003679 if (ElemType == nullptr)
3680 return nullptr;
3681 return make<VectorType>(ElemType, DimensionNumber);
3682 }
3683
3684 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003685 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003686 if (!DimExpr)
3687 return nullptr;
3688 if (!consumeIf('_'))
3689 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003690 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003691 if (!ElemType)
3692 return nullptr;
3693 return make<VectorType>(ElemType, DimExpr);
3694 }
Pavel Labathba825192018-10-16 14:29:14 +00003695 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003696 if (!ElemType)
3697 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003698 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003699}
3700
3701// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3702// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003703template <typename Derived, typename Alloc>
3704Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003705 if (!consumeIf('D'))
3706 return nullptr;
3707 if (!consumeIf('t') && !consumeIf('T'))
3708 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003709 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003710 if (E == nullptr)
3711 return nullptr;
3712 if (!consumeIf('E'))
3713 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003714 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003715}
3716
3717// <array-type> ::= A <positive dimension number> _ <element type>
3718// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003719template <typename Derived, typename Alloc>
3720Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003721 if (!consumeIf('A'))
3722 return nullptr;
3723
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003724 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003725
Richard Smithc20d1442018-08-20 20:14:49 +00003726 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003727 Dimension = make<NameType>(parseNumber());
3728 if (!Dimension)
3729 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003730 if (!consumeIf('_'))
3731 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003732 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003733 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003734 if (DimExpr == nullptr)
3735 return nullptr;
3736 if (!consumeIf('_'))
3737 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003738 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003739 }
3740
Pavel Labathba825192018-10-16 14:29:14 +00003741 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003742 if (Ty == nullptr)
3743 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003744 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003745}
3746
3747// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003748template <typename Derived, typename Alloc>
3749Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003750 if (!consumeIf('M'))
3751 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003752 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003753 if (ClassType == nullptr)
3754 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003755 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003756 if (MemberType == nullptr)
3757 return nullptr;
3758 return make<PointerToMemberType>(ClassType, MemberType);
3759}
3760
3761// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3762// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3763// ::= Tu <name> # dependent elaborated type specifier using 'union'
3764// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003765template <typename Derived, typename Alloc>
3766Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003767 StringView ElabSpef;
3768 if (consumeIf("Ts"))
3769 ElabSpef = "struct";
3770 else if (consumeIf("Tu"))
3771 ElabSpef = "union";
3772 else if (consumeIf("Te"))
3773 ElabSpef = "enum";
3774
Pavel Labathba825192018-10-16 14:29:14 +00003775 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003776 if (Name == nullptr)
3777 return nullptr;
3778
3779 if (!ElabSpef.empty())
3780 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3781
3782 return Name;
3783}
3784
3785// <qualified-type> ::= <qualifiers> <type>
3786// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3787// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003788template <typename Derived, typename Alloc>
3789Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003790 if (consumeIf('U')) {
3791 StringView Qual = parseBareSourceName();
3792 if (Qual.empty())
3793 return nullptr;
3794
Richard Smithc20d1442018-08-20 20:14:49 +00003795 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3796 if (Qual.startsWith("objcproto")) {
3797 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3798 StringView Proto;
3799 {
3800 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3801 SaveLast(Last, ProtoSourceName.end());
3802 Proto = parseBareSourceName();
3803 }
3804 if (Proto.empty())
3805 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003806 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003807 if (Child == nullptr)
3808 return nullptr;
3809 return make<ObjCProtoName>(Child, Proto);
3810 }
3811
Alex Orlovf50df922021-03-24 10:21:32 +04003812 Node *TA = nullptr;
3813 if (look() == 'I') {
3814 TA = getDerived().parseTemplateArgs();
3815 if (TA == nullptr)
3816 return nullptr;
3817 }
3818
Pavel Labathba825192018-10-16 14:29:14 +00003819 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003820 if (Child == nullptr)
3821 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003822 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003823 }
3824
3825 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003826 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003827 if (Ty == nullptr)
3828 return nullptr;
3829 if (Quals != QualNone)
3830 Ty = make<QualType>(Ty, Quals);
3831 return Ty;
3832}
3833
3834// <type> ::= <builtin-type>
3835// ::= <qualified-type>
3836// ::= <function-type>
3837// ::= <class-enum-type>
3838// ::= <array-type>
3839// ::= <pointer-to-member-type>
3840// ::= <template-param>
3841// ::= <template-template-param> <template-args>
3842// ::= <decltype>
3843// ::= P <type> # pointer
3844// ::= R <type> # l-value reference
3845// ::= O <type> # r-value reference (C++11)
3846// ::= C <type> # complex pair (C99)
3847// ::= G <type> # imaginary (C99)
3848// ::= <substitution> # See Compression below
3849// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3850// extension ::= <vector-type> # <vector-type> starts with Dv
3851//
3852// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3853// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003854template <typename Derived, typename Alloc>
3855Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003856 Node *Result = nullptr;
3857
Richard Smithc20d1442018-08-20 20:14:49 +00003858 switch (look()) {
3859 // ::= <qualified-type>
3860 case 'r':
3861 case 'V':
3862 case 'K': {
3863 unsigned AfterQuals = 0;
3864 if (look(AfterQuals) == 'r') ++AfterQuals;
3865 if (look(AfterQuals) == 'V') ++AfterQuals;
3866 if (look(AfterQuals) == 'K') ++AfterQuals;
3867
3868 if (look(AfterQuals) == 'F' ||
3869 (look(AfterQuals) == 'D' &&
3870 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3871 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003872 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003873 break;
3874 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003875 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003876 }
3877 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003878 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003879 break;
3880 }
3881 // <builtin-type> ::= v # void
3882 case 'v':
3883 ++First;
3884 return make<NameType>("void");
3885 // ::= w # wchar_t
3886 case 'w':
3887 ++First;
3888 return make<NameType>("wchar_t");
3889 // ::= b # bool
3890 case 'b':
3891 ++First;
3892 return make<NameType>("bool");
3893 // ::= c # char
3894 case 'c':
3895 ++First;
3896 return make<NameType>("char");
3897 // ::= a # signed char
3898 case 'a':
3899 ++First;
3900 return make<NameType>("signed char");
3901 // ::= h # unsigned char
3902 case 'h':
3903 ++First;
3904 return make<NameType>("unsigned char");
3905 // ::= s # short
3906 case 's':
3907 ++First;
3908 return make<NameType>("short");
3909 // ::= t # unsigned short
3910 case 't':
3911 ++First;
3912 return make<NameType>("unsigned short");
3913 // ::= i # int
3914 case 'i':
3915 ++First;
3916 return make<NameType>("int");
3917 // ::= j # unsigned int
3918 case 'j':
3919 ++First;
3920 return make<NameType>("unsigned int");
3921 // ::= l # long
3922 case 'l':
3923 ++First;
3924 return make<NameType>("long");
3925 // ::= m # unsigned long
3926 case 'm':
3927 ++First;
3928 return make<NameType>("unsigned long");
3929 // ::= x # long long, __int64
3930 case 'x':
3931 ++First;
3932 return make<NameType>("long long");
3933 // ::= y # unsigned long long, __int64
3934 case 'y':
3935 ++First;
3936 return make<NameType>("unsigned long long");
3937 // ::= n # __int128
3938 case 'n':
3939 ++First;
3940 return make<NameType>("__int128");
3941 // ::= o # unsigned __int128
3942 case 'o':
3943 ++First;
3944 return make<NameType>("unsigned __int128");
3945 // ::= f # float
3946 case 'f':
3947 ++First;
3948 return make<NameType>("float");
3949 // ::= d # double
3950 case 'd':
3951 ++First;
3952 return make<NameType>("double");
3953 // ::= e # long double, __float80
3954 case 'e':
3955 ++First;
3956 return make<NameType>("long double");
3957 // ::= g # __float128
3958 case 'g':
3959 ++First;
3960 return make<NameType>("__float128");
3961 // ::= z # ellipsis
3962 case 'z':
3963 ++First;
3964 return make<NameType>("...");
3965
3966 // <builtin-type> ::= u <source-name> # vendor extended type
3967 case 'u': {
3968 ++First;
3969 StringView Res = parseBareSourceName();
3970 if (Res.empty())
3971 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003972 // Typically, <builtin-type>s are not considered substitution candidates,
3973 // but the exception to that exception is vendor extended types (Itanium C++
3974 // ABI 5.9.1).
3975 Result = make<NameType>(Res);
3976 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003977 }
3978 case 'D':
3979 switch (look(1)) {
3980 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3981 case 'd':
3982 First += 2;
3983 return make<NameType>("decimal64");
3984 // ::= De # IEEE 754r decimal floating point (128 bits)
3985 case 'e':
3986 First += 2;
3987 return make<NameType>("decimal128");
3988 // ::= Df # IEEE 754r decimal floating point (32 bits)
3989 case 'f':
3990 First += 2;
3991 return make<NameType>("decimal32");
3992 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3993 case 'h':
3994 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003995 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003996 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3997 case 'F': {
3998 First += 2;
3999 Node *DimensionNumber = make<NameType>(parseNumber());
4000 if (!DimensionNumber)
4001 return nullptr;
4002 if (!consumeIf('_'))
4003 return nullptr;
4004 return make<BinaryFPType>(DimensionNumber);
4005 }
Richard Smithc20d1442018-08-20 20:14:49 +00004006 // ::= Di # char32_t
4007 case 'i':
4008 First += 2;
4009 return make<NameType>("char32_t");
4010 // ::= Ds # char16_t
4011 case 's':
4012 First += 2;
4013 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00004014 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
4015 case 'u':
4016 First += 2;
4017 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004018 // ::= Da # auto (in dependent new-expressions)
4019 case 'a':
4020 First += 2;
4021 return make<NameType>("auto");
4022 // ::= Dc # decltype(auto)
4023 case 'c':
4024 First += 2;
4025 return make<NameType>("decltype(auto)");
4026 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
4027 case 'n':
4028 First += 2;
4029 return make<NameType>("std::nullptr_t");
4030
4031 // ::= <decltype>
4032 case 't':
4033 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00004034 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00004035 break;
4036 }
4037 // extension ::= <vector-type> # <vector-type> starts with Dv
4038 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00004039 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00004040 break;
4041 }
4042 // ::= Dp <type> # pack expansion (C++0x)
4043 case 'p': {
4044 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004045 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004046 if (!Child)
4047 return nullptr;
4048 Result = make<ParameterPackExpansion>(Child);
4049 break;
4050 }
4051 // Exception specifier on a function type.
4052 case 'o':
4053 case 'O':
4054 case 'w':
4055 // Transaction safe function type.
4056 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00004057 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00004058 break;
4059 }
4060 break;
4061 // ::= <function-type>
4062 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00004063 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00004064 break;
4065 }
4066 // ::= <array-type>
4067 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00004068 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00004069 break;
4070 }
4071 // ::= <pointer-to-member-type>
4072 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00004073 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00004074 break;
4075 }
4076 // ::= <template-param>
4077 case 'T': {
4078 // This could be an elaborate type specifier on a <class-enum-type>.
4079 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00004080 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004081 break;
4082 }
4083
Pavel Labathba825192018-10-16 14:29:14 +00004084 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004085 if (Result == nullptr)
4086 return nullptr;
4087
4088 // Result could be either of:
4089 // <type> ::= <template-param>
4090 // <type> ::= <template-template-param> <template-args>
4091 //
4092 // <template-template-param> ::= <template-param>
4093 // ::= <substitution>
4094 //
4095 // If this is followed by some <template-args>, and we're permitted to
4096 // parse them, take the second production.
4097
4098 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004099 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004100 if (TA == nullptr)
4101 return nullptr;
4102 Result = make<NameWithTemplateArgs>(Result, TA);
4103 }
4104 break;
4105 }
4106 // ::= P <type> # pointer
4107 case 'P': {
4108 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004109 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004110 if (Ptr == nullptr)
4111 return nullptr;
4112 Result = make<PointerType>(Ptr);
4113 break;
4114 }
4115 // ::= R <type> # l-value reference
4116 case 'R': {
4117 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004118 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004119 if (Ref == nullptr)
4120 return nullptr;
4121 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4122 break;
4123 }
4124 // ::= O <type> # r-value reference (C++11)
4125 case 'O': {
4126 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004127 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004128 if (Ref == nullptr)
4129 return nullptr;
4130 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4131 break;
4132 }
4133 // ::= C <type> # complex pair (C99)
4134 case 'C': {
4135 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004136 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004137 if (P == nullptr)
4138 return nullptr;
4139 Result = make<PostfixQualifiedType>(P, " complex");
4140 break;
4141 }
4142 // ::= G <type> # imaginary (C99)
4143 case 'G': {
4144 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004145 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004146 if (P == nullptr)
4147 return P;
4148 Result = make<PostfixQualifiedType>(P, " imaginary");
4149 break;
4150 }
4151 // ::= <substitution> # See Compression below
4152 case 'S': {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004153 if (look(1) != 't') {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004154 bool IsSubst = false;
4155 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4156 if (!Result)
Richard Smithc20d1442018-08-20 20:14:49 +00004157 return nullptr;
4158
4159 // Sub could be either of:
4160 // <type> ::= <substitution>
4161 // <type> ::= <template-template-param> <template-args>
4162 //
4163 // <template-template-param> ::= <template-param>
4164 // ::= <substitution>
4165 //
4166 // If this is followed by some <template-args>, and we're permitted to
4167 // parse them, take the second production.
4168
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004169 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4170 if (!IsSubst)
4171 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00004172 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004173 if (TA == nullptr)
4174 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004175 Result = make<NameWithTemplateArgs>(Result, TA);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004176 } else if (IsSubst) {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004177 // If all we parsed was a substitution, don't re-insert into the
4178 // substitution table.
4179 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00004180 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004181 break;
Richard Smithc20d1442018-08-20 20:14:49 +00004182 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004183 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004184 }
4185 // ::= <class-enum-type>
4186 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004187 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004188 break;
4189 }
4190 }
4191
4192 // If we parsed a type, insert it into the substitution table. Note that all
4193 // <builtin-type>s and <substitution>s have already bailed out, because they
4194 // don't get substitutions.
4195 if (Result != nullptr)
4196 Subs.push_back(Result);
4197 return Result;
4198}
4199
Pavel Labathba825192018-10-16 14:29:14 +00004200template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004201Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4202 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004203 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004204 if (E == nullptr)
4205 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004206 return make<PrefixExpr>(Kind, E, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004207}
4208
Pavel Labathba825192018-10-16 14:29:14 +00004209template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004210Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4211 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004212 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004213 if (LHS == nullptr)
4214 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004215 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004216 if (RHS == nullptr)
4217 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004218 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004219}
4220
Pavel Labathba825192018-10-16 14:29:14 +00004221template <typename Derived, typename Alloc>
4222Node *
4223AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004224 StringView Tmp = parseNumber(true);
4225 if (!Tmp.empty() && consumeIf('E'))
4226 return make<IntegerLiteral>(Lit, Tmp);
4227 return nullptr;
4228}
4229
4230// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004231template <typename Alloc, typename Derived>
4232Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004233 Qualifiers CVR = QualNone;
4234 if (consumeIf('r'))
4235 CVR |= QualRestrict;
4236 if (consumeIf('V'))
4237 CVR |= QualVolatile;
4238 if (consumeIf('K'))
4239 CVR |= QualConst;
4240 return CVR;
4241}
4242
4243// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4244// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4245// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4246// ::= 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 -04004247// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004248template <typename Derived, typename Alloc>
4249Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004250 if (consumeIf("fpT"))
4251 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004252 if (consumeIf("fp")) {
4253 parseCVQualifiers();
4254 StringView Num = parseNumber();
4255 if (!consumeIf('_'))
4256 return nullptr;
4257 return make<FunctionParam>(Num);
4258 }
4259 if (consumeIf("fL")) {
4260 if (parseNumber().empty())
4261 return nullptr;
4262 if (!consumeIf('p'))
4263 return nullptr;
4264 parseCVQualifiers();
4265 StringView Num = parseNumber();
4266 if (!consumeIf('_'))
4267 return nullptr;
4268 return make<FunctionParam>(Num);
4269 }
4270 return nullptr;
4271}
4272
Richard Smithc20d1442018-08-20 20:14:49 +00004273// cv <type> <expression> # conversion with one argument
4274// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004275template <typename Derived, typename Alloc>
4276Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004277 if (!consumeIf("cv"))
4278 return nullptr;
4279 Node *Ty;
4280 {
4281 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004282 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004283 }
4284
4285 if (Ty == nullptr)
4286 return nullptr;
4287
4288 if (consumeIf('_')) {
4289 size_t ExprsBegin = Names.size();
4290 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004291 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004292 if (E == nullptr)
4293 return E;
4294 Names.push_back(E);
4295 }
4296 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4297 return make<ConversionExpr>(Ty, Exprs);
4298 }
4299
Pavel Labathba825192018-10-16 14:29:14 +00004300 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004301 if (E[0] == nullptr)
4302 return nullptr;
4303 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4304}
4305
4306// <expr-primary> ::= L <type> <value number> E # integer literal
4307// ::= L <type> <value float> E # floating literal
4308// ::= L <string type> E # string literal
4309// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004310// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004311// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4312// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004313template <typename Derived, typename Alloc>
4314Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004315 if (!consumeIf('L'))
4316 return nullptr;
4317 switch (look()) {
4318 case 'w':
4319 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004320 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004321 case 'b':
4322 if (consumeIf("b0E"))
4323 return make<BoolExpr>(0);
4324 if (consumeIf("b1E"))
4325 return make<BoolExpr>(1);
4326 return nullptr;
4327 case 'c':
4328 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004329 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004330 case 'a':
4331 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004332 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004333 case 'h':
4334 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004335 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004336 case 's':
4337 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004338 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004339 case 't':
4340 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004341 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004342 case 'i':
4343 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004344 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004345 case 'j':
4346 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004347 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004348 case 'l':
4349 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004350 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004351 case 'm':
4352 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004353 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004354 case 'x':
4355 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004356 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004357 case 'y':
4358 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004359 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004360 case 'n':
4361 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004362 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004363 case 'o':
4364 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004365 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004366 case 'f':
4367 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004368 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004369 case 'd':
4370 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004371 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004372 case 'e':
4373 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004374#if defined(__powerpc__) || defined(__s390__)
4375 // Handle cases where long doubles encoded with e have the same size
4376 // and representation as doubles.
4377 return getDerived().template parseFloatingLiteral<double>();
4378#else
Pavel Labathba825192018-10-16 14:29:14 +00004379 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004380#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004381 case '_':
4382 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004383 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004384 if (R != nullptr && consumeIf('E'))
4385 return R;
4386 }
4387 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004388 case 'A': {
4389 Node *T = getDerived().parseType();
4390 if (T == nullptr)
4391 return nullptr;
4392 // FIXME: We need to include the string contents in the mangling.
4393 if (consumeIf('E'))
4394 return make<StringLiteral>(T);
4395 return nullptr;
4396 }
4397 case 'D':
4398 if (consumeIf("DnE"))
4399 return make<NameType>("nullptr");
4400 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004401 case 'T':
4402 // Invalid mangled name per
4403 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4404 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004405 case 'U': {
4406 // FIXME: Should we support LUb... for block literals?
4407 if (look(1) != 'l')
4408 return nullptr;
4409 Node *T = parseUnnamedTypeName(nullptr);
4410 if (!T || !consumeIf('E'))
4411 return nullptr;
4412 return make<LambdaExpr>(T);
4413 }
Richard Smithc20d1442018-08-20 20:14:49 +00004414 default: {
4415 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004416 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004417 if (T == nullptr)
4418 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004419 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004420 if (N.empty())
4421 return nullptr;
4422 if (!consumeIf('E'))
4423 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004424 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004425 }
4426 }
4427}
4428
4429// <braced-expression> ::= <expression>
4430// ::= di <field source-name> <braced-expression> # .name = expr
4431// ::= dx <index expression> <braced-expression> # [expr] = expr
4432// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004433template <typename Derived, typename Alloc>
4434Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004435 if (look() == 'd') {
4436 switch (look(1)) {
4437 case 'i': {
4438 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004439 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004440 if (Field == nullptr)
4441 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004442 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004443 if (Init == nullptr)
4444 return nullptr;
4445 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4446 }
4447 case 'x': {
4448 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004449 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004450 if (Index == nullptr)
4451 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004452 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004453 if (Init == nullptr)
4454 return nullptr;
4455 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4456 }
4457 case 'X': {
4458 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004459 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004460 if (RangeBegin == nullptr)
4461 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004462 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004463 if (RangeEnd == nullptr)
4464 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004465 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004466 if (Init == nullptr)
4467 return nullptr;
4468 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4469 }
4470 }
4471 }
Pavel Labathba825192018-10-16 14:29:14 +00004472 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004473}
4474
4475// (not yet in the spec)
4476// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4477// ::= fR <binary-operator-name> <expression> <expression>
4478// ::= fl <binary-operator-name> <expression>
4479// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004480template <typename Derived, typename Alloc>
4481Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004482 if (!consumeIf('f'))
4483 return nullptr;
4484
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004485 bool IsLeftFold = false, HasInitializer = false;
4486 switch (look()) {
4487 default:
Richard Smithc20d1442018-08-20 20:14:49 +00004488 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004489 case 'L':
4490 IsLeftFold = true;
4491 HasInitializer = true;
4492 break;
4493 case 'R':
4494 HasInitializer = true;
4495 break;
4496 case 'l':
4497 IsLeftFold = true;
4498 break;
4499 case 'r':
4500 break;
4501 }
Richard Smithc20d1442018-08-20 20:14:49 +00004502 ++First;
4503
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004504 const auto *Op = parseOperatorEncoding();
4505 if (!Op || Op->getKind() != OperatorInfo::Binary)
4506 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004507
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004508 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004509 if (Pack == nullptr)
4510 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004511
4512 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004513 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004514 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004515 if (Init == nullptr)
4516 return nullptr;
4517 }
4518
4519 if (IsLeftFold && Init)
4520 std::swap(Pack, Init);
4521
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004522 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004523}
4524
Richard Smith1865d2f2020-10-22 19:29:36 -07004525// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4526//
4527// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4528template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004529Node *
4530AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4531 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004532 Node *Ty = getDerived().parseType();
4533 if (!Ty)
4534 return nullptr;
4535 Node *Expr = getDerived().parseExpr();
4536 if (!Expr)
4537 return nullptr;
4538 StringView Offset = getDerived().parseNumber(true);
4539 if (!consumeIf('E'))
4540 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004541 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004542}
4543
4544// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4545// <union-selector> ::= _ [<number>]
4546//
4547// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4548template <typename Derived, typename Alloc>
4549Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4550 Node *Ty = getDerived().parseType();
4551 if (!Ty)
4552 return nullptr;
4553 Node *Expr = getDerived().parseExpr();
4554 if (!Expr)
4555 return nullptr;
4556 StringView Offset = getDerived().parseNumber(true);
4557 size_t SelectorsBegin = Names.size();
4558 while (consumeIf('_')) {
4559 Node *Selector = make<NameType>(parseNumber());
4560 if (!Selector)
4561 return nullptr;
4562 Names.push_back(Selector);
4563 }
4564 bool OnePastTheEnd = consumeIf('p');
4565 if (!consumeIf('E'))
4566 return nullptr;
4567 return make<SubobjectExpr>(
4568 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4569}
4570
Richard Smithc20d1442018-08-20 20:14:49 +00004571// <expression> ::= <unary operator-name> <expression>
4572// ::= <binary operator-name> <expression> <expression>
4573// ::= <ternary operator-name> <expression> <expression> <expression>
4574// ::= cl <expression>+ E # call
4575// ::= cv <type> <expression> # conversion with one argument
4576// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4577// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4578// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4579// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4580// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4581// ::= [gs] dl <expression> # delete expression
4582// ::= [gs] da <expression> # delete[] expression
4583// ::= pp_ <expression> # prefix ++
4584// ::= mm_ <expression> # prefix --
4585// ::= ti <type> # typeid (type)
4586// ::= te <expression> # typeid (expression)
4587// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4588// ::= sc <type> <expression> # static_cast<type> (expression)
4589// ::= cc <type> <expression> # const_cast<type> (expression)
4590// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4591// ::= st <type> # sizeof (a type)
4592// ::= sz <expression> # sizeof (an expression)
4593// ::= at <type> # alignof (a type)
4594// ::= az <expression> # alignof (an expression)
4595// ::= nx <expression> # noexcept (expression)
4596// ::= <template-param>
4597// ::= <function-param>
4598// ::= dt <expression> <unresolved-name> # expr.name
4599// ::= pt <expression> <unresolved-name> # expr->name
4600// ::= ds <expression> <expression> # expr.*expr
4601// ::= sZ <template-param> # size of a parameter pack
4602// ::= sZ <function-param> # size of a function parameter pack
4603// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4604// ::= sp <expression> # pack expansion
4605// ::= tw <expression> # throw expression
4606// ::= tr # throw with no operand (rethrow)
4607// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4608// # freestanding dependent name (e.g., T::x),
4609// # objectless nonstatic member reference
4610// ::= fL <binary-operator-name> <expression> <expression>
4611// ::= fR <binary-operator-name> <expression> <expression>
4612// ::= fl <binary-operator-name> <expression>
4613// ::= fr <binary-operator-name> <expression>
4614// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004615template <typename Derived, typename Alloc>
4616Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004617 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004618
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004619 const auto *Op = parseOperatorEncoding();
4620 if (Op) {
4621 auto Sym = Op->getSymbol();
4622 switch (Op->getKind()) {
4623 case OperatorInfo::Binary:
4624 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004625 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004626 case OperatorInfo::Prefix:
4627 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004628 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004629 case OperatorInfo::Postfix: {
4630 // Postfix unary operator: expr @
4631 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004632 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004633 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004634 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004635 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004636 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004637 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004638 case OperatorInfo::Array: {
4639 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004640 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004641 if (Base == nullptr)
4642 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004643 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004644 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004645 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004646 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004647 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004648 case OperatorInfo::Member: {
4649 // Member access lhs @ rhs
4650 Node *LHS = getDerived().parseExpr();
4651 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004652 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004653 Node *RHS = getDerived().parseExpr();
4654 if (RHS == nullptr)
4655 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004656 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004657 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004658 case OperatorInfo::New: {
4659 // New
4660 // # new (expr-list) type [(init)]
4661 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4662 // # new[] (expr-list) type [(init)]
4663 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004664 size_t Exprs = Names.size();
4665 while (!consumeIf('_')) {
4666 Node *Ex = getDerived().parseExpr();
4667 if (Ex == nullptr)
4668 return nullptr;
4669 Names.push_back(Ex);
4670 }
4671 NodeArray ExprList = popTrailingNodeArray(Exprs);
4672 Node *Ty = getDerived().parseType();
4673 if (Ty == nullptr)
4674 return nullptr;
4675 bool HaveInits = consumeIf("pi");
4676 size_t InitsBegin = Names.size();
4677 while (!consumeIf('E')) {
4678 if (!HaveInits)
4679 return nullptr;
4680 Node *Init = getDerived().parseExpr();
4681 if (Init == nullptr)
4682 return Init;
4683 Names.push_back(Init);
4684 }
4685 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004686 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004687 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004688 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004689 case OperatorInfo::Del: {
4690 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004691 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004692 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004693 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004694 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4695 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004696 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004697 case OperatorInfo::Call: {
4698 // Function Call
4699 Node *Callee = getDerived().parseExpr();
4700 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004701 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004702 size_t ExprsBegin = Names.size();
4703 while (!consumeIf('E')) {
4704 Node *E = getDerived().parseExpr();
4705 if (E == nullptr)
4706 return nullptr;
4707 Names.push_back(E);
4708 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004709 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4710 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004711 }
4712 case OperatorInfo::CCast: {
4713 // C Cast: (type)expr
4714 Node *Ty;
4715 {
4716 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
4717 Ty = getDerived().parseType();
4718 }
4719 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004720 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004721
4722 size_t ExprsBegin = Names.size();
4723 bool IsMany = consumeIf('_');
4724 while (!consumeIf('E')) {
4725 Node *E = getDerived().parseExpr();
4726 if (E == nullptr)
4727 return E;
4728 Names.push_back(E);
4729 if (!IsMany)
4730 break;
4731 }
4732 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4733 if (!IsMany && Exprs.size() != 1)
4734 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004735 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004736 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004737 case OperatorInfo::Conditional: {
4738 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004739 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004740 if (Cond == nullptr)
4741 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004742 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004743 if (LHS == nullptr)
4744 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004745 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004746 if (RHS == nullptr)
4747 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004748 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004749 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004750 case OperatorInfo::NamedCast: {
4751 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004752 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004753 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004754 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004755 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004756 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004757 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004758 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004759 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004760 case OperatorInfo::OfIdOp: {
4761 // [sizeof/alignof/typeid] ( <type>|<expr> )
4762 Node *Arg =
4763 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4764 if (!Arg)
4765 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004766 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004767 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004768 case OperatorInfo::NameOnly: {
4769 // Not valid as an expression operand.
4770 return nullptr;
4771 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004772 }
4773 DEMANGLE_UNREACHABLE;
4774 }
4775
4776 if (numLeft() < 2)
4777 return nullptr;
4778
4779 if (look() == 'L')
4780 return getDerived().parseExprPrimary();
4781 if (look() == 'T')
4782 return getDerived().parseTemplateParam();
4783 if (look() == 'f') {
4784 // Disambiguate a fold expression from a <function-param>.
4785 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4786 return getDerived().parseFunctionParam();
4787 return getDerived().parseFoldExpr();
4788 }
4789 if (consumeIf("il")) {
4790 size_t InitsBegin = Names.size();
4791 while (!consumeIf('E')) {
4792 Node *E = getDerived().parseBracedExpr();
4793 if (E == nullptr)
4794 return nullptr;
4795 Names.push_back(E);
4796 }
4797 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4798 }
4799 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004800 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004801 if (consumeIf("nx")) {
4802 Node *Ex = getDerived().parseExpr();
4803 if (Ex == nullptr)
4804 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004805 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004806 }
4807 if (consumeIf("so"))
4808 return parseSubobjectExpr();
4809 if (consumeIf("sp")) {
4810 Node *Child = getDerived().parseExpr();
4811 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004812 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004813 return make<ParameterPackExpansion>(Child);
4814 }
4815 if (consumeIf("sZ")) {
4816 if (look() == 'T') {
4817 Node *R = getDerived().parseTemplateParam();
4818 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004819 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004820 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004821 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004822 Node *FP = getDerived().parseFunctionParam();
4823 if (FP == nullptr)
4824 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004825 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004826 }
4827 if (consumeIf("sP")) {
4828 size_t ArgsBegin = Names.size();
4829 while (!consumeIf('E')) {
4830 Node *Arg = getDerived().parseTemplateArg();
4831 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004832 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004833 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004834 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004835 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4836 if (!Pack)
4837 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004838 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004839 }
4840 if (consumeIf("tl")) {
4841 Node *Ty = getDerived().parseType();
4842 if (Ty == nullptr)
4843 return nullptr;
4844 size_t InitsBegin = Names.size();
4845 while (!consumeIf('E')) {
4846 Node *E = getDerived().parseBracedExpr();
4847 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004848 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004849 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004850 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004851 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4852 }
4853 if (consumeIf("tr"))
4854 return make<NameType>("throw");
4855 if (consumeIf("tw")) {
4856 Node *Ex = getDerived().parseExpr();
4857 if (Ex == nullptr)
4858 return nullptr;
4859 return make<ThrowExpr>(Ex);
4860 }
4861 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004862 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4863 if (!Name)
4864 return nullptr;
4865 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4866 // standard encoding expects a <template-arg>, and would be otherwise be
4867 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4868 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4869 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004870 bool IsUUID = false;
4871 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004872 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004873 if (consumeIf('t')) {
4874 UUID = getDerived().parseType();
4875 IsUUID = true;
4876 } else if (consumeIf('z')) {
4877 UUID = getDerived().parseExpr();
4878 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004879 }
4880 }
4881 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004882 if (IsUUID) {
4883 if (UUID == nullptr)
4884 return nullptr;
4885 Names.push_back(UUID);
4886 } else {
4887 while (!consumeIf('E')) {
4888 Node *E = getDerived().parseTemplateArg();
4889 if (E == nullptr)
4890 return E;
4891 Names.push_back(E);
4892 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004893 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004894 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4895 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004896 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004897
4898 // Only unresolved names remain.
4899 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004900}
4901
4902// <call-offset> ::= h <nv-offset> _
4903// ::= v <v-offset> _
4904//
4905// <nv-offset> ::= <offset number>
4906// # non-virtual base override
4907//
4908// <v-offset> ::= <offset number> _ <virtual offset number>
4909// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004910template <typename Alloc, typename Derived>
4911bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004912 // Just scan through the call offset, we never add this information into the
4913 // output.
4914 if (consumeIf('h'))
4915 return parseNumber(true).empty() || !consumeIf('_');
4916 if (consumeIf('v'))
4917 return parseNumber(true).empty() || !consumeIf('_') ||
4918 parseNumber(true).empty() || !consumeIf('_');
4919 return true;
4920}
4921
4922// <special-name> ::= TV <type> # virtual table
4923// ::= TT <type> # VTT structure (construction vtable index)
4924// ::= TI <type> # typeinfo structure
4925// ::= TS <type> # typeinfo name (null-terminated byte string)
4926// ::= Tc <call-offset> <call-offset> <base encoding>
4927// # base is the nominal target function of thunk
4928// # first call-offset is 'this' adjustment
4929// # second call-offset is result adjustment
4930// ::= T <call-offset> <base encoding>
4931// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004932// # Guard variable for one-time initialization
4933// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004934// # No <type>
4935// ::= TW <object name> # Thread-local wrapper
4936// ::= TH <object name> # Thread-local initialization
4937// ::= GR <object name> _ # First temporary
4938// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004939// # construction vtable for second-in-first
4940// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004941// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004942// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004943template <typename Derived, typename Alloc>
4944Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004945 switch (look()) {
4946 case 'T':
4947 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004948 // TA <template-arg> # template parameter object
4949 //
4950 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4951 case 'A': {
4952 First += 2;
4953 Node *Arg = getDerived().parseTemplateArg();
4954 if (Arg == nullptr)
4955 return nullptr;
4956 return make<SpecialName>("template parameter object for ", Arg);
4957 }
Richard Smithc20d1442018-08-20 20:14:49 +00004958 // TV <type> # virtual table
4959 case 'V': {
4960 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004961 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004962 if (Ty == nullptr)
4963 return nullptr;
4964 return make<SpecialName>("vtable for ", Ty);
4965 }
4966 // TT <type> # VTT structure (construction vtable index)
4967 case 'T': {
4968 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004969 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004970 if (Ty == nullptr)
4971 return nullptr;
4972 return make<SpecialName>("VTT for ", Ty);
4973 }
4974 // TI <type> # typeinfo structure
4975 case 'I': {
4976 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004977 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004978 if (Ty == nullptr)
4979 return nullptr;
4980 return make<SpecialName>("typeinfo for ", Ty);
4981 }
4982 // TS <type> # typeinfo name (null-terminated byte string)
4983 case 'S': {
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 nullptr;
4988 return make<SpecialName>("typeinfo name for ", Ty);
4989 }
4990 // Tc <call-offset> <call-offset> <base encoding>
4991 case 'c': {
4992 First += 2;
4993 if (parseCallOffset() || parseCallOffset())
4994 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004995 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004996 if (Encoding == nullptr)
4997 return nullptr;
4998 return make<SpecialName>("covariant return thunk to ", Encoding);
4999 }
5000 // extension ::= TC <first type> <number> _ <second type>
5001 // # construction vtable for second-in-first
5002 case 'C': {
5003 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005004 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005005 if (FirstType == nullptr)
5006 return nullptr;
5007 if (parseNumber(true).empty() || !consumeIf('_'))
5008 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00005009 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005010 if (SecondType == nullptr)
5011 return nullptr;
5012 return make<CtorVtableSpecialName>(SecondType, FirstType);
5013 }
5014 // TW <object name> # Thread-local wrapper
5015 case 'W': {
5016 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005017 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005018 if (Name == nullptr)
5019 return nullptr;
5020 return make<SpecialName>("thread-local wrapper routine for ", Name);
5021 }
5022 // TH <object name> # Thread-local initialization
5023 case 'H': {
5024 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005025 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005026 if (Name == nullptr)
5027 return nullptr;
5028 return make<SpecialName>("thread-local initialization routine for ", Name);
5029 }
5030 // T <call-offset> <base encoding>
5031 default: {
5032 ++First;
5033 bool IsVirt = look() == 'v';
5034 if (parseCallOffset())
5035 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00005036 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005037 if (BaseEncoding == nullptr)
5038 return nullptr;
5039 if (IsVirt)
5040 return make<SpecialName>("virtual thunk to ", BaseEncoding);
5041 else
5042 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
5043 }
5044 }
5045 case 'G':
5046 switch (look(1)) {
5047 // GV <object name> # Guard variable for one-time initialization
5048 case 'V': {
5049 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005050 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005051 if (Name == nullptr)
5052 return nullptr;
5053 return make<SpecialName>("guard variable for ", Name);
5054 }
5055 // GR <object name> # reference temporary for object
5056 // GR <object name> _ # First temporary
5057 // GR <object name> <seq-id> _ # Subsequent temporaries
5058 case 'R': {
5059 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005060 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005061 if (Name == nullptr)
5062 return nullptr;
5063 size_t Count;
5064 bool ParsedSeqId = !parseSeqId(&Count);
5065 if (!consumeIf('_') && ParsedSeqId)
5066 return nullptr;
5067 return make<SpecialName>("reference temporary for ", Name);
5068 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08005069 // GI <module-name> v
5070 case 'I': {
5071 First += 2;
5072 ModuleName *Module = nullptr;
5073 if (getDerived().parseModuleNameOpt(Module))
5074 return nullptr;
5075 if (Module == nullptr)
5076 return nullptr;
5077 return make<SpecialName>("initializer for module ", Module);
5078 }
Richard Smithc20d1442018-08-20 20:14:49 +00005079 }
5080 }
5081 return nullptr;
5082}
5083
5084// <encoding> ::= <function name> <bare-function-type>
5085// ::= <data name>
5086// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005087template <typename Derived, typename Alloc>
5088Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005089 // The template parameters of an encoding are unrelated to those of the
5090 // enclosing context.
5091 class SaveTemplateParams {
5092 AbstractManglingParser *Parser;
5093 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005094 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005095
5096 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005097 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005098 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005099 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005100 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005101 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005102 }
5103 ~SaveTemplateParams() {
5104 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005105 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005106 }
5107 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005108
Richard Smithc20d1442018-08-20 20:14:49 +00005109 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005110 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005111
5112 auto IsEndOfEncoding = [&] {
5113 // The set of chars that can potentially follow an <encoding> (none of which
5114 // can start a <type>). Enumerating these allows us to avoid speculative
5115 // parsing.
5116 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5117 };
5118
5119 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005120 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005121 if (Name == nullptr)
5122 return nullptr;
5123
5124 if (resolveForwardTemplateRefs(NameInfo))
5125 return nullptr;
5126
5127 if (IsEndOfEncoding())
5128 return Name;
5129
5130 Node *Attrs = nullptr;
5131 if (consumeIf("Ua9enable_ifI")) {
5132 size_t BeforeArgs = Names.size();
5133 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005134 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005135 if (Arg == nullptr)
5136 return nullptr;
5137 Names.push_back(Arg);
5138 }
5139 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005140 if (!Attrs)
5141 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005142 }
5143
5144 Node *ReturnType = nullptr;
5145 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005146 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005147 if (ReturnType == nullptr)
5148 return nullptr;
5149 }
5150
5151 if (consumeIf('v'))
5152 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5153 Attrs, NameInfo.CVQualifiers,
5154 NameInfo.ReferenceQualifier);
5155
5156 size_t ParamsBegin = Names.size();
5157 do {
Pavel Labathba825192018-10-16 14:29:14 +00005158 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005159 if (Ty == nullptr)
5160 return nullptr;
5161 Names.push_back(Ty);
5162 } while (!IsEndOfEncoding());
5163
5164 return make<FunctionEncoding>(ReturnType, Name,
5165 popTrailingNodeArray(ParamsBegin),
5166 Attrs, NameInfo.CVQualifiers,
5167 NameInfo.ReferenceQualifier);
5168}
5169
5170template <class Float>
5171struct FloatData;
5172
5173template <>
5174struct FloatData<float>
5175{
5176 static const size_t mangled_size = 8;
5177 static const size_t max_demangled_size = 24;
5178 static constexpr const char* spec = "%af";
5179};
5180
5181template <>
5182struct FloatData<double>
5183{
5184 static const size_t mangled_size = 16;
5185 static const size_t max_demangled_size = 32;
5186 static constexpr const char* spec = "%a";
5187};
5188
5189template <>
5190struct FloatData<long double>
5191{
5192#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5193 defined(__wasm__)
5194 static const size_t mangled_size = 32;
5195#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5196 static const size_t mangled_size = 16;
5197#else
5198 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5199#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005200 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5201 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5202 // Negatives are one character longer than positives.
5203 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5204 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5205 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005206 static constexpr const char *spec = "%LaL";
5207};
5208
Pavel Labathba825192018-10-16 14:29:14 +00005209template <typename Alloc, typename Derived>
5210template <class Float>
5211Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005212 const size_t N = FloatData<Float>::mangled_size;
5213 if (numLeft() <= N)
5214 return nullptr;
5215 StringView Data(First, First + N);
5216 for (char C : Data)
5217 if (!std::isxdigit(C))
5218 return nullptr;
5219 First += N;
5220 if (!consumeIf('E'))
5221 return nullptr;
5222 return make<FloatLiteralImpl<Float>>(Data);
5223}
5224
5225// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005226template <typename Alloc, typename Derived>
5227bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005228 if (!(look() >= '0' && look() <= '9') &&
5229 !(look() >= 'A' && look() <= 'Z'))
5230 return true;
5231
5232 size_t Id = 0;
5233 while (true) {
5234 if (look() >= '0' && look() <= '9') {
5235 Id *= 36;
5236 Id += static_cast<size_t>(look() - '0');
5237 } else if (look() >= 'A' && look() <= 'Z') {
5238 Id *= 36;
5239 Id += static_cast<size_t>(look() - 'A') + 10;
5240 } else {
5241 *Out = Id;
5242 return false;
5243 }
5244 ++First;
5245 }
5246}
5247
5248// <substitution> ::= S <seq-id> _
5249// ::= S_
5250// <substitution> ::= Sa # ::std::allocator
5251// <substitution> ::= Sb # ::std::basic_string
5252// <substitution> ::= Ss # ::std::basic_string < char,
5253// ::std::char_traits<char>,
5254// ::std::allocator<char> >
5255// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5256// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5257// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005258// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005259template <typename Derived, typename Alloc>
5260Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005261 if (!consumeIf('S'))
5262 return nullptr;
5263
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005264 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005265 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005266 switch (look()) {
5267 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005268 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005269 break;
5270 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005271 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005272 break;
5273 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005274 Kind = SpecialSubKind::iostream;
5275 break;
5276 case 'i':
5277 Kind = SpecialSubKind::istream;
5278 break;
5279 case 'o':
5280 Kind = SpecialSubKind::ostream;
5281 break;
5282 case 's':
5283 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005284 break;
5285 default:
5286 return nullptr;
5287 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005288 ++First;
5289 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005290 if (!SpecialSub)
5291 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005292
Richard Smithc20d1442018-08-20 20:14:49 +00005293 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5294 // has ABI tags, the tags are appended to the substitution; the result is a
5295 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005296 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005297 if (WithTags != SpecialSub) {
5298 Subs.push_back(WithTags);
5299 SpecialSub = WithTags;
5300 }
5301 return SpecialSub;
5302 }
5303
5304 // ::= S_
5305 if (consumeIf('_')) {
5306 if (Subs.empty())
5307 return nullptr;
5308 return Subs[0];
5309 }
5310
5311 // ::= S <seq-id> _
5312 size_t Index = 0;
5313 if (parseSeqId(&Index))
5314 return nullptr;
5315 ++Index;
5316 if (!consumeIf('_') || Index >= Subs.size())
5317 return nullptr;
5318 return Subs[Index];
5319}
5320
5321// <template-param> ::= T_ # first template parameter
5322// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005323// ::= TL <level-1> __
5324// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005325template <typename Derived, typename Alloc>
5326Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005327 if (!consumeIf('T'))
5328 return nullptr;
5329
Richard Smithdf1c14c2019-09-06 23:53:21 +00005330 size_t Level = 0;
5331 if (consumeIf('L')) {
5332 if (parsePositiveInteger(&Level))
5333 return nullptr;
5334 ++Level;
5335 if (!consumeIf('_'))
5336 return nullptr;
5337 }
5338
Richard Smithc20d1442018-08-20 20:14:49 +00005339 size_t Index = 0;
5340 if (!consumeIf('_')) {
5341 if (parsePositiveInteger(&Index))
5342 return nullptr;
5343 ++Index;
5344 if (!consumeIf('_'))
5345 return nullptr;
5346 }
5347
Richard Smithc20d1442018-08-20 20:14:49 +00005348 // If we're in a context where this <template-param> refers to a
5349 // <template-arg> further ahead in the mangled name (currently just conversion
5350 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005351 // This can only happen at the outermost level.
5352 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005353 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5354 if (!ForwardRef)
5355 return nullptr;
5356 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5357 ForwardTemplateRefs.push_back(
5358 static_cast<ForwardTemplateReference *>(ForwardRef));
5359 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005360 }
5361
Richard Smithdf1c14c2019-09-06 23:53:21 +00005362 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5363 Index >= TemplateParams[Level]->size()) {
5364 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5365 // list are mangled as the corresponding artificial template type parameter.
5366 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5367 // This will be popped by the ScopedTemplateParamList in
5368 // parseUnnamedTypeName.
5369 if (Level == TemplateParams.size())
5370 TemplateParams.push_back(nullptr);
5371 return make<NameType>("auto");
5372 }
5373
Richard Smithc20d1442018-08-20 20:14:49 +00005374 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005375 }
5376
5377 return (*TemplateParams[Level])[Index];
5378}
5379
5380// <template-param-decl> ::= Ty # type parameter
5381// ::= Tn <type> # non-type parameter
5382// ::= Tt <template-param-decl>* E # template parameter
5383// ::= Tp <template-param-decl> # parameter pack
5384template <typename Derived, typename Alloc>
5385Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5386 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5387 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5388 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5389 if (N) TemplateParams.back()->push_back(N);
5390 return N;
5391 };
5392
5393 if (consumeIf("Ty")) {
5394 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5395 if (!Name)
5396 return nullptr;
5397 return make<TypeTemplateParamDecl>(Name);
5398 }
5399
5400 if (consumeIf("Tn")) {
5401 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5402 if (!Name)
5403 return nullptr;
5404 Node *Type = parseType();
5405 if (!Type)
5406 return nullptr;
5407 return make<NonTypeTemplateParamDecl>(Name, Type);
5408 }
5409
5410 if (consumeIf("Tt")) {
5411 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5412 if (!Name)
5413 return nullptr;
5414 size_t ParamsBegin = Names.size();
5415 ScopedTemplateParamList TemplateTemplateParamParams(this);
5416 while (!consumeIf("E")) {
5417 Node *P = parseTemplateParamDecl();
5418 if (!P)
5419 return nullptr;
5420 Names.push_back(P);
5421 }
5422 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5423 return make<TemplateTemplateParamDecl>(Name, Params);
5424 }
5425
5426 if (consumeIf("Tp")) {
5427 Node *P = parseTemplateParamDecl();
5428 if (!P)
5429 return nullptr;
5430 return make<TemplateParamPackDecl>(P);
5431 }
5432
5433 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005434}
5435
5436// <template-arg> ::= <type> # type or template
5437// ::= X <expression> E # expression
5438// ::= <expr-primary> # simple expressions
5439// ::= J <template-arg>* E # argument pack
5440// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005441template <typename Derived, typename Alloc>
5442Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005443 switch (look()) {
5444 case 'X': {
5445 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005446 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005447 if (Arg == nullptr || !consumeIf('E'))
5448 return nullptr;
5449 return Arg;
5450 }
5451 case 'J': {
5452 ++First;
5453 size_t ArgsBegin = Names.size();
5454 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005455 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005456 if (Arg == nullptr)
5457 return nullptr;
5458 Names.push_back(Arg);
5459 }
5460 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5461 return make<TemplateArgumentPack>(Args);
5462 }
5463 case 'L': {
5464 // ::= LZ <encoding> E # extension
5465 if (look(1) == 'Z') {
5466 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005467 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005468 if (Arg == nullptr || !consumeIf('E'))
5469 return nullptr;
5470 return Arg;
5471 }
5472 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005473 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005474 }
5475 default:
Pavel Labathba825192018-10-16 14:29:14 +00005476 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005477 }
5478}
5479
5480// <template-args> ::= I <template-arg>* E
5481// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005482template <typename Derived, typename Alloc>
5483Node *
5484AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005485 if (!consumeIf('I'))
5486 return nullptr;
5487
5488 // <template-params> refer to the innermost <template-args>. Clear out any
5489 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005490 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005491 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005492 TemplateParams.push_back(&OuterTemplateParams);
5493 OuterTemplateParams.clear();
5494 }
Richard Smithc20d1442018-08-20 20:14:49 +00005495
5496 size_t ArgsBegin = Names.size();
5497 while (!consumeIf('E')) {
5498 if (TagTemplates) {
5499 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005500 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005501 TemplateParams = std::move(OldParams);
5502 if (Arg == nullptr)
5503 return nullptr;
5504 Names.push_back(Arg);
5505 Node *TableEntry = Arg;
5506 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5507 TableEntry = make<ParameterPack>(
5508 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005509 if (!TableEntry)
5510 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005511 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005512 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005513 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005514 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005515 if (Arg == nullptr)
5516 return nullptr;
5517 Names.push_back(Arg);
5518 }
5519 }
5520 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5521}
5522
5523// <mangled-name> ::= _Z <encoding>
5524// ::= <type>
5525// extension ::= ___Z <encoding> _block_invoke
5526// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5527// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005528template <typename Derived, typename Alloc>
5529Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005530 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005531 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005532 if (Encoding == nullptr)
5533 return nullptr;
5534 if (look() == '.') {
5535 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5536 First = Last;
5537 }
5538 if (numLeft() != 0)
5539 return nullptr;
5540 return Encoding;
5541 }
5542
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005543 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005544 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005545 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5546 return nullptr;
5547 bool RequireNumber = consumeIf('_');
5548 if (parseNumber().empty() && RequireNumber)
5549 return nullptr;
5550 if (look() == '.')
5551 First = Last;
5552 if (numLeft() != 0)
5553 return nullptr;
5554 return make<SpecialName>("invocation function for block in ", Encoding);
5555 }
5556
Pavel Labathba825192018-10-16 14:29:14 +00005557 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005558 if (numLeft() != 0)
5559 return nullptr;
5560 return Ty;
5561}
5562
Pavel Labathba825192018-10-16 14:29:14 +00005563template <typename Alloc>
5564struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5565 using AbstractManglingParser<ManglingParser<Alloc>,
5566 Alloc>::AbstractManglingParser;
5567};
5568
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005569DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005570
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005571#endif // DEMANGLE_ITANIUMDEMANGLE_H