blob: 85b4923a21016daa1e4bf473dabfc06bcdb66fae [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
1059 template <typename Fn> void match(Fn F) const { F(Parent, Name); }
1060
1061 void printLeft(OutputBuffer &OB) const override {
1062 if (Parent)
1063 Parent->print(OB);
1064 if (Parent || IsPartition)
1065 OB += IsPartition ? ':' : '.';
1066 Name->print(OB);
1067 }
1068};
1069
1070struct ModuleEntity : Node {
1071 ModuleName *Module;
1072 Node *Name;
1073
1074 ModuleEntity(ModuleName *Module_, Node *Name_)
1075 : Node(KModuleEntity), Module(Module_), Name(Name_) {}
1076
1077 template <typename Fn> void match(Fn F) const { F(Module, Name); }
1078
1079 StringView getBaseName() const override { return Name->getBaseName(); }
1080
1081 void printLeft(OutputBuffer &OB) const override {
1082 Name->print(OB);
1083 OB += '@';
1084 Module->print(OB);
1085 }
1086};
1087
Richard Smithc20d1442018-08-20 20:14:49 +00001088struct LocalName : Node {
1089 Node *Encoding;
1090 Node *Entity;
1091
1092 LocalName(Node *Encoding_, Node *Entity_)
1093 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
1094
1095 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
1096
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001097 void printLeft(OutputBuffer &OB) const override {
1098 Encoding->print(OB);
1099 OB += "::";
1100 Entity->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001101 }
1102};
1103
1104class QualifiedName final : public Node {
1105 // qualifier::name
1106 const Node *Qualifier;
1107 const Node *Name;
1108
1109public:
1110 QualifiedName(const Node *Qualifier_, const Node *Name_)
1111 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
1112
1113 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
1114
1115 StringView getBaseName() const override { return Name->getBaseName(); }
1116
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001117 void printLeft(OutputBuffer &OB) const override {
1118 Qualifier->print(OB);
1119 OB += "::";
1120 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001121 }
1122};
1123
1124class VectorType final : public Node {
1125 const Node *BaseType;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001126 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001127
1128public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001129 VectorType(const Node *BaseType_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +00001130 : Node(KVectorType), BaseType(BaseType_),
1131 Dimension(Dimension_) {}
1132
1133 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
1134
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001135 void printLeft(OutputBuffer &OB) const override {
1136 BaseType->print(OB);
1137 OB += " vector[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001138 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001139 Dimension->print(OB);
1140 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001141 }
1142};
1143
1144class PixelVectorType final : public Node {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001145 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001146
1147public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001148 PixelVectorType(const Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +00001149 : Node(KPixelVectorType), Dimension(Dimension_) {}
1150
1151 template<typename Fn> void match(Fn F) const { F(Dimension); }
1152
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001153 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001154 // FIXME: This should demangle as "vector pixel".
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001155 OB += "pixel vector[";
1156 Dimension->print(OB);
1157 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001158 }
1159};
1160
Pengfei Wang50e90b82021-09-23 11:02:25 +08001161class BinaryFPType final : public Node {
1162 const Node *Dimension;
1163
1164public:
1165 BinaryFPType(const Node *Dimension_)
1166 : Node(KBinaryFPType), Dimension(Dimension_) {}
1167
1168 template<typename Fn> void match(Fn F) const { F(Dimension); }
1169
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001170 void printLeft(OutputBuffer &OB) const override {
1171 OB += "_Float";
1172 Dimension->print(OB);
Pengfei Wang50e90b82021-09-23 11:02:25 +08001173 }
1174};
1175
Richard Smithdf1c14c2019-09-06 23:53:21 +00001176enum class TemplateParamKind { Type, NonType, Template };
1177
1178/// An invented name for a template parameter for which we don't have a
1179/// corresponding template argument.
1180///
1181/// This node is created when parsing the <lambda-sig> for a lambda with
1182/// explicit template arguments, which might be referenced in the parameter
1183/// types appearing later in the <lambda-sig>.
1184class SyntheticTemplateParamName final : public Node {
1185 TemplateParamKind Kind;
1186 unsigned Index;
1187
1188public:
1189 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
1190 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
1191
1192 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
1193
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001194 void printLeft(OutputBuffer &OB) const override {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001195 switch (Kind) {
1196 case TemplateParamKind::Type:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001197 OB += "$T";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001198 break;
1199 case TemplateParamKind::NonType:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001200 OB += "$N";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001201 break;
1202 case TemplateParamKind::Template:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001203 OB += "$TT";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001204 break;
1205 }
1206 if (Index > 0)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001207 OB << Index - 1;
Richard Smithdf1c14c2019-09-06 23:53:21 +00001208 }
1209};
1210
1211/// A template type parameter declaration, 'typename T'.
1212class TypeTemplateParamDecl final : public Node {
1213 Node *Name;
1214
1215public:
1216 TypeTemplateParamDecl(Node *Name_)
1217 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
1218
1219 template<typename Fn> void match(Fn F) const { F(Name); }
1220
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001221 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001222
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001223 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001224};
1225
1226/// A non-type template parameter declaration, 'int N'.
1227class NonTypeTemplateParamDecl final : public Node {
1228 Node *Name;
1229 Node *Type;
1230
1231public:
1232 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
1233 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
1234
1235 template<typename Fn> void match(Fn F) const { F(Name, Type); }
1236
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001237 void printLeft(OutputBuffer &OB) const override {
1238 Type->printLeft(OB);
1239 if (!Type->hasRHSComponent(OB))
1240 OB += " ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001241 }
1242
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001243 void printRight(OutputBuffer &OB) const override {
1244 Name->print(OB);
1245 Type->printRight(OB);
Richard Smithdf1c14c2019-09-06 23:53:21 +00001246 }
1247};
1248
1249/// A template template parameter declaration,
1250/// 'template<typename T> typename N'.
1251class TemplateTemplateParamDecl final : public Node {
1252 Node *Name;
1253 NodeArray Params;
1254
1255public:
1256 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
1257 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1258 Params(Params_) {}
1259
1260 template<typename Fn> void match(Fn F) const { F(Name, Params); }
1261
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001262 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001263 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001264 OB += "template<";
1265 Params.printWithComma(OB);
1266 OB += "> typename ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001267 }
1268
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001269 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001270};
1271
1272/// A template parameter pack declaration, 'typename ...T'.
1273class TemplateParamPackDecl final : public Node {
1274 Node *Param;
1275
1276public:
1277 TemplateParamPackDecl(Node *Param_)
1278 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1279
1280 template<typename Fn> void match(Fn F) const { F(Param); }
1281
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001282 void printLeft(OutputBuffer &OB) const override {
1283 Param->printLeft(OB);
1284 OB += "...";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001285 }
1286
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001287 void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001288};
1289
Richard Smithc20d1442018-08-20 20:14:49 +00001290/// An unexpanded parameter pack (either in the expression or type context). If
1291/// this AST is correct, this node will have a ParameterPackExpansion node above
1292/// it.
1293///
1294/// This node is created when some <template-args> are found that apply to an
1295/// <encoding>, and is stored in the TemplateParams table. In order for this to
1296/// appear in the final AST, it has to referenced via a <template-param> (ie,
1297/// T_).
1298class ParameterPack final : public Node {
1299 NodeArray Data;
1300
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08001301 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1302 // one.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001303 void initializePackExpansion(OutputBuffer &OB) const {
1304 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1305 OB.CurrentPackMax = static_cast<unsigned>(Data.size());
1306 OB.CurrentPackIndex = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00001307 }
1308 }
1309
1310public:
1311 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1312 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
1313 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1314 return P->ArrayCache == Cache::No;
1315 }))
1316 ArrayCache = Cache::No;
1317 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1318 return P->FunctionCache == Cache::No;
1319 }))
1320 FunctionCache = Cache::No;
1321 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1322 return P->RHSComponentCache == Cache::No;
1323 }))
1324 RHSComponentCache = Cache::No;
1325 }
1326
1327 template<typename Fn> void match(Fn F) const { F(Data); }
1328
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001329 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1330 initializePackExpansion(OB);
1331 size_t Idx = OB.CurrentPackIndex;
1332 return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001333 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001334 bool hasArraySlow(OutputBuffer &OB) const override {
1335 initializePackExpansion(OB);
1336 size_t Idx = OB.CurrentPackIndex;
1337 return Idx < Data.size() && Data[Idx]->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001338 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001339 bool hasFunctionSlow(OutputBuffer &OB) const override {
1340 initializePackExpansion(OB);
1341 size_t Idx = OB.CurrentPackIndex;
1342 return Idx < Data.size() && Data[Idx]->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001343 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001344 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1345 initializePackExpansion(OB);
1346 size_t Idx = OB.CurrentPackIndex;
1347 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;
Richard Smithc20d1442018-08-20 20:14:49 +00001348 }
1349
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001350 void printLeft(OutputBuffer &OB) const override {
1351 initializePackExpansion(OB);
1352 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001353 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001354 Data[Idx]->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001355 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001356 void printRight(OutputBuffer &OB) const override {
1357 initializePackExpansion(OB);
1358 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001359 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001360 Data[Idx]->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001361 }
1362};
1363
1364/// A variadic template argument. This node represents an occurrence of
1365/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1366/// one of it's Elements is. The parser inserts a ParameterPack into the
1367/// TemplateParams table if the <template-args> this pack belongs to apply to an
1368/// <encoding>.
1369class TemplateArgumentPack final : public Node {
1370 NodeArray Elements;
1371public:
1372 TemplateArgumentPack(NodeArray Elements_)
1373 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1374
1375 template<typename Fn> void match(Fn F) const { F(Elements); }
1376
1377 NodeArray getElements() const { return Elements; }
1378
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001379 void printLeft(OutputBuffer &OB) const override {
1380 Elements.printWithComma(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001381 }
1382};
1383
1384/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1385/// which each have Child->ParameterPackSize elements.
1386class ParameterPackExpansion final : public Node {
1387 const Node *Child;
1388
1389public:
1390 ParameterPackExpansion(const Node *Child_)
1391 : Node(KParameterPackExpansion), Child(Child_) {}
1392
1393 template<typename Fn> void match(Fn F) const { F(Child); }
1394
1395 const Node *getChild() const { return Child; }
1396
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001397 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001398 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001399 SwapAndRestore<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1400 SwapAndRestore<unsigned> SavePackMax(OB.CurrentPackMax, Max);
1401 size_t StreamPos = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +00001402
1403 // Print the first element in the pack. If Child contains a ParameterPack,
1404 // it will set up S.CurrentPackMax and print the first element.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001405 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001406
1407 // No ParameterPack was found in Child. This can occur if we've found a pack
1408 // expansion on a <function-param>.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001409 if (OB.CurrentPackMax == Max) {
1410 OB += "...";
Richard Smithc20d1442018-08-20 20:14:49 +00001411 return;
1412 }
1413
1414 // We found a ParameterPack, but it has no elements. Erase whatever we may
1415 // of printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001416 if (OB.CurrentPackMax == 0) {
1417 OB.setCurrentPosition(StreamPos);
Richard Smithc20d1442018-08-20 20:14:49 +00001418 return;
1419 }
1420
1421 // Else, iterate through the rest of the elements in the pack.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001422 for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {
1423 OB += ", ";
1424 OB.CurrentPackIndex = I;
1425 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001426 }
1427 }
1428};
1429
1430class TemplateArgs final : public Node {
1431 NodeArray Params;
1432
1433public:
1434 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1435
1436 template<typename Fn> void match(Fn F) const { F(Params); }
1437
1438 NodeArray getParams() { return Params; }
1439
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001440 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001441 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001442 OB += "<";
1443 Params.printWithComma(OB);
1444 if (OB.back() == '>')
1445 OB += " ";
1446 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +00001447 }
1448};
1449
Richard Smithb485b352018-08-24 23:30:26 +00001450/// A forward-reference to a template argument that was not known at the point
1451/// where the template parameter name was parsed in a mangling.
1452///
1453/// This is created when demangling the name of a specialization of a
1454/// conversion function template:
1455///
1456/// \code
1457/// struct A {
1458/// template<typename T> operator T*();
1459/// };
1460/// \endcode
1461///
1462/// When demangling a specialization of the conversion function template, we
1463/// encounter the name of the template (including the \c T) before we reach
1464/// the template argument list, so we cannot substitute the parameter name
1465/// for the corresponding argument while parsing. Instead, we create a
1466/// \c ForwardTemplateReference node that is resolved after we parse the
1467/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001468struct ForwardTemplateReference : Node {
1469 size_t Index;
1470 Node *Ref = nullptr;
1471
1472 // If we're currently printing this node. It is possible (though invalid) for
1473 // a forward template reference to refer to itself via a substitution. This
1474 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1475 // out if more than one print* function is active.
1476 mutable bool Printing = false;
1477
1478 ForwardTemplateReference(size_t Index_)
1479 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1480 Cache::Unknown),
1481 Index(Index_) {}
1482
1483 // We don't provide a matcher for these, because the value of the node is
1484 // not determined by its construction parameters, and it generally needs
1485 // special handling.
1486 template<typename Fn> void match(Fn F) const = delete;
1487
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001488 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001489 if (Printing)
1490 return false;
1491 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001492 return Ref->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001493 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001494 bool hasArraySlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001495 if (Printing)
1496 return false;
1497 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001498 return Ref->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001499 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001500 bool hasFunctionSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001501 if (Printing)
1502 return false;
1503 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001504 return Ref->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001505 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001506 const Node *getSyntaxNode(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001507 if (Printing)
1508 return this;
1509 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001510 return Ref->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001511 }
1512
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001513 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001514 if (Printing)
1515 return;
1516 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001517 Ref->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001518 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001519 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001520 if (Printing)
1521 return;
1522 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001523 Ref->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001524 }
1525};
1526
1527struct NameWithTemplateArgs : Node {
1528 // name<template_args>
1529 Node *Name;
1530 Node *TemplateArgs;
1531
1532 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1533 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1534
1535 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1536
1537 StringView getBaseName() const override { return Name->getBaseName(); }
1538
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001539 void printLeft(OutputBuffer &OB) const override {
1540 Name->print(OB);
1541 TemplateArgs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001542 }
1543};
1544
1545class GlobalQualifiedName final : public Node {
1546 Node *Child;
1547
1548public:
1549 GlobalQualifiedName(Node* Child_)
1550 : Node(KGlobalQualifiedName), Child(Child_) {}
1551
1552 template<typename Fn> void match(Fn F) const { F(Child); }
1553
1554 StringView getBaseName() const override { return Child->getBaseName(); }
1555
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001556 void printLeft(OutputBuffer &OB) const override {
1557 OB += "::";
1558 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001559 }
1560};
1561
Richard Smithc20d1442018-08-20 20:14:49 +00001562enum class SpecialSubKind {
1563 allocator,
1564 basic_string,
1565 string,
1566 istream,
1567 ostream,
1568 iostream,
1569};
1570
1571class ExpandedSpecialSubstitution final : public Node {
1572 SpecialSubKind SSK;
1573
1574public:
1575 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1576 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1577
1578 template<typename Fn> void match(Fn F) const { F(SSK); }
1579
1580 StringView getBaseName() const override {
1581 switch (SSK) {
1582 case SpecialSubKind::allocator:
1583 return StringView("allocator");
1584 case SpecialSubKind::basic_string:
1585 return StringView("basic_string");
1586 case SpecialSubKind::string:
1587 return StringView("basic_string");
1588 case SpecialSubKind::istream:
1589 return StringView("basic_istream");
1590 case SpecialSubKind::ostream:
1591 return StringView("basic_ostream");
1592 case SpecialSubKind::iostream:
1593 return StringView("basic_iostream");
1594 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001595 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001596 }
1597
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001598 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001599 switch (SSK) {
1600 case SpecialSubKind::allocator:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001601 OB += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001602 break;
1603 case SpecialSubKind::basic_string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001604 OB += "std::basic_string";
Richard Smithb485b352018-08-24 23:30:26 +00001605 break;
Richard Smithc20d1442018-08-20 20:14:49 +00001606 case SpecialSubKind::string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001607 OB += "std::basic_string<char, std::char_traits<char>, "
1608 "std::allocator<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001609 break;
1610 case SpecialSubKind::istream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001611 OB += "std::basic_istream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001612 break;
1613 case SpecialSubKind::ostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001614 OB += "std::basic_ostream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001615 break;
1616 case SpecialSubKind::iostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001617 OB += "std::basic_iostream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001618 break;
1619 }
1620 }
1621};
1622
1623class SpecialSubstitution final : public Node {
1624public:
1625 SpecialSubKind SSK;
1626
1627 SpecialSubstitution(SpecialSubKind SSK_)
1628 : Node(KSpecialSubstitution), SSK(SSK_) {}
1629
1630 template<typename Fn> void match(Fn F) const { F(SSK); }
1631
1632 StringView getBaseName() const override {
1633 switch (SSK) {
1634 case SpecialSubKind::allocator:
1635 return StringView("allocator");
1636 case SpecialSubKind::basic_string:
1637 return StringView("basic_string");
1638 case SpecialSubKind::string:
1639 return StringView("string");
1640 case SpecialSubKind::istream:
1641 return StringView("istream");
1642 case SpecialSubKind::ostream:
1643 return StringView("ostream");
1644 case SpecialSubKind::iostream:
1645 return StringView("iostream");
1646 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001647 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001648 }
1649
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001650 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001651 switch (SSK) {
1652 case SpecialSubKind::allocator:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001653 OB += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001654 break;
1655 case SpecialSubKind::basic_string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001656 OB += "std::basic_string";
Richard Smithc20d1442018-08-20 20:14:49 +00001657 break;
1658 case SpecialSubKind::string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001659 OB += "std::string";
Richard Smithc20d1442018-08-20 20:14:49 +00001660 break;
1661 case SpecialSubKind::istream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001662 OB += "std::istream";
Richard Smithc20d1442018-08-20 20:14:49 +00001663 break;
1664 case SpecialSubKind::ostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001665 OB += "std::ostream";
Richard Smithc20d1442018-08-20 20:14:49 +00001666 break;
1667 case SpecialSubKind::iostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001668 OB += "std::iostream";
Richard Smithc20d1442018-08-20 20:14:49 +00001669 break;
1670 }
1671 }
1672};
1673
1674class CtorDtorName final : public Node {
1675 const Node *Basename;
1676 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001677 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001678
1679public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001680 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1681 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1682 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001683
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001684 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001685
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001686 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001687 if (IsDtor)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001688 OB += "~";
1689 OB += Basename->getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001690 }
1691};
1692
1693class DtorName : public Node {
1694 const Node *Base;
1695
1696public:
1697 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1698
1699 template<typename Fn> void match(Fn F) const { F(Base); }
1700
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001701 void printLeft(OutputBuffer &OB) const override {
1702 OB += "~";
1703 Base->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001704 }
1705};
1706
1707class UnnamedTypeName : public Node {
1708 const StringView Count;
1709
1710public:
1711 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1712
1713 template<typename Fn> void match(Fn F) const { F(Count); }
1714
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001715 void printLeft(OutputBuffer &OB) const override {
1716 OB += "'unnamed";
1717 OB += Count;
1718 OB += "\'";
Richard Smithc20d1442018-08-20 20:14:49 +00001719 }
1720};
1721
1722class ClosureTypeName : public Node {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001723 NodeArray TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00001724 NodeArray Params;
1725 StringView Count;
1726
1727public:
Richard Smithdf1c14c2019-09-06 23:53:21 +00001728 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1729 StringView Count_)
1730 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1731 Params(Params_), Count(Count_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001732
Richard Smithdf1c14c2019-09-06 23:53:21 +00001733 template<typename Fn> void match(Fn F) const {
1734 F(TemplateParams, Params, Count);
1735 }
1736
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001737 void printDeclarator(OutputBuffer &OB) const {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001738 if (!TemplateParams.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001739 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001740 OB += "<";
1741 TemplateParams.printWithComma(OB);
1742 OB += ">";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001743 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001744 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001745 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001746 OB.printClose();
Richard Smithdf1c14c2019-09-06 23:53:21 +00001747 }
Richard Smithc20d1442018-08-20 20:14:49 +00001748
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001749 void printLeft(OutputBuffer &OB) const override {
1750 OB += "\'lambda";
1751 OB += Count;
1752 OB += "\'";
1753 printDeclarator(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001754 }
1755};
1756
1757class StructuredBindingName : public Node {
1758 NodeArray Bindings;
1759public:
1760 StructuredBindingName(NodeArray Bindings_)
1761 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1762
1763 template<typename Fn> void match(Fn F) const { F(Bindings); }
1764
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001765 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001766 OB.printOpen('[');
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001767 Bindings.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001768 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001769 }
1770};
1771
1772// -- Expression Nodes --
1773
1774class BinaryExpr : public Node {
1775 const Node *LHS;
1776 const StringView InfixOperator;
1777 const Node *RHS;
1778
1779public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001780 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
1781 Prec Prec_)
1782 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
1783 RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001784
1785 template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }
1786
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001787 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001788 bool ParenAll = OB.isGtInsideTemplateArgs() && InfixOperator == ">";
1789 if (ParenAll)
1790 OB.printOpen();
1791 // Assignment is right associative, with special LHS precedence.
1792 bool IsAssign = getPrecedence() == Prec::Assign;
1793 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1794 // No space before comma operator
1795 if (!(InfixOperator == ","))
1796 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001797 OB += InfixOperator;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001798 OB += " ";
1799 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1800 if (ParenAll)
1801 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001802 }
1803};
1804
1805class ArraySubscriptExpr : public Node {
1806 const Node *Op1;
1807 const Node *Op2;
1808
1809public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001810 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1811 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001812
1813 template<typename Fn> void match(Fn F) const { F(Op1, Op2); }
1814
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001815 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001816 Op1->printAsOperand(OB, getPrecedence());
1817 OB.printOpen('[');
1818 Op2->printAsOperand(OB);
1819 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001820 }
1821};
1822
1823class PostfixExpr : public Node {
1824 const Node *Child;
1825 const StringView Operator;
1826
1827public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001828 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
1829 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001830
1831 template<typename Fn> void match(Fn F) const { F(Child, Operator); }
1832
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001833 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001834 Child->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001835 OB += Operator;
Richard Smithc20d1442018-08-20 20:14:49 +00001836 }
1837};
1838
1839class ConditionalExpr : public Node {
1840 const Node *Cond;
1841 const Node *Then;
1842 const Node *Else;
1843
1844public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001845 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1846 Prec Prec_)
1847 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001848
1849 template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }
1850
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001851 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001852 Cond->printAsOperand(OB, getPrecedence());
1853 OB += " ? ";
1854 Then->printAsOperand(OB);
1855 OB += " : ";
1856 Else->printAsOperand(OB, Prec::Assign, true);
Richard Smithc20d1442018-08-20 20:14:49 +00001857 }
1858};
1859
1860class MemberExpr : public Node {
1861 const Node *LHS;
1862 const StringView Kind;
1863 const Node *RHS;
1864
1865public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001866 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
1867 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001868
1869 template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }
1870
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001871 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001872 LHS->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001873 OB += Kind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001874 RHS->printAsOperand(OB, getPrecedence(), false);
Richard Smithc20d1442018-08-20 20:14:49 +00001875 }
1876};
1877
Richard Smith1865d2f2020-10-22 19:29:36 -07001878class SubobjectExpr : public Node {
1879 const Node *Type;
1880 const Node *SubExpr;
1881 StringView Offset;
1882 NodeArray UnionSelectors;
1883 bool OnePastTheEnd;
1884
1885public:
1886 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1887 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1888 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1889 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1890
1891 template<typename Fn> void match(Fn F) const {
1892 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1893 }
1894
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001895 void printLeft(OutputBuffer &OB) const override {
1896 SubExpr->print(OB);
1897 OB += ".<";
1898 Type->print(OB);
1899 OB += " at offset ";
Richard Smith1865d2f2020-10-22 19:29:36 -07001900 if (Offset.empty()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001901 OB += "0";
Richard Smith1865d2f2020-10-22 19:29:36 -07001902 } else if (Offset[0] == 'n') {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001903 OB += "-";
1904 OB += Offset.dropFront();
Richard Smith1865d2f2020-10-22 19:29:36 -07001905 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001906 OB += Offset;
Richard Smith1865d2f2020-10-22 19:29:36 -07001907 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001908 OB += ">";
Richard Smith1865d2f2020-10-22 19:29:36 -07001909 }
1910};
1911
Richard Smithc20d1442018-08-20 20:14:49 +00001912class EnclosingExpr : public Node {
1913 const StringView Prefix;
1914 const Node *Infix;
1915 const StringView Postfix;
1916
1917public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001918 EnclosingExpr(StringView Prefix_, Node *Infix_, Prec Prec_ = Prec::Primary)
1919 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001920
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001921 template <typename Fn> void match(Fn F) const { F(Prefix, Infix); }
Richard Smithc20d1442018-08-20 20:14:49 +00001922
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001923 void printLeft(OutputBuffer &OB) const override {
1924 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001925 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001926 Infix->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001927 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001928 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +00001929 }
1930};
1931
1932class CastExpr : public Node {
1933 // cast_kind<to>(from)
1934 const StringView CastKind;
1935 const Node *To;
1936 const Node *From;
1937
1938public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001939 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
1940 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001941
1942 template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }
1943
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001944 void printLeft(OutputBuffer &OB) const override {
1945 OB += CastKind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001946 {
1947 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
1948 OB += "<";
1949 To->printLeft(OB);
1950 if (OB.back() == '>')
1951 OB += " ";
1952 OB += ">";
1953 }
1954 OB.printOpen();
1955 From->printAsOperand(OB);
1956 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001957 }
1958};
1959
1960class SizeofParamPackExpr : public Node {
1961 const Node *Pack;
1962
1963public:
1964 SizeofParamPackExpr(const Node *Pack_)
1965 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1966
1967 template<typename Fn> void match(Fn F) const { F(Pack); }
1968
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001969 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001970 OB += "sizeof...";
1971 OB.printOpen();
Richard Smithc20d1442018-08-20 20:14:49 +00001972 ParameterPackExpansion PPE(Pack);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001973 PPE.printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001974 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001975 }
1976};
1977
1978class CallExpr : public Node {
1979 const Node *Callee;
1980 NodeArray Args;
1981
1982public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001983 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
1984 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001985
1986 template<typename Fn> void match(Fn F) const { F(Callee, Args); }
1987
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001988 void printLeft(OutputBuffer &OB) const override {
1989 Callee->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001990 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001991 Args.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001992 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001993 }
1994};
1995
1996class NewExpr : public Node {
1997 // new (expr_list) type(init_list)
1998 NodeArray ExprList;
1999 Node *Type;
2000 NodeArray InitList;
2001 bool IsGlobal; // ::operator new ?
2002 bool IsArray; // new[] ?
2003public:
2004 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002005 bool IsArray_, Prec Prec_)
2006 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
2007 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002008
2009 template<typename Fn> void match(Fn F) const {
2010 F(ExprList, Type, InitList, IsGlobal, IsArray);
2011 }
2012
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002013 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002014 if (IsGlobal)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08002015 OB += "::";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002016 OB += "new";
Richard Smithc20d1442018-08-20 20:14:49 +00002017 if (IsArray)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002018 OB += "[]";
Richard Smithc20d1442018-08-20 20:14:49 +00002019 if (!ExprList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002020 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002021 ExprList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002022 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002023 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002024 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002025 Type->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002026 if (!InitList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002027 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002028 InitList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002029 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002030 }
Richard Smithc20d1442018-08-20 20:14:49 +00002031 }
2032};
2033
2034class DeleteExpr : public Node {
2035 Node *Op;
2036 bool IsGlobal;
2037 bool IsArray;
2038
2039public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002040 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
2041 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
2042 IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002043
2044 template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }
2045
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002046 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002047 if (IsGlobal)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002048 OB += "::";
2049 OB += "delete";
Richard Smithc20d1442018-08-20 20:14:49 +00002050 if (IsArray)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08002051 OB += "[]";
2052 OB += ' ';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002053 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002054 }
2055};
2056
2057class PrefixExpr : public Node {
2058 StringView Prefix;
2059 Node *Child;
2060
2061public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002062 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
2063 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002064
2065 template<typename Fn> void match(Fn F) const { F(Prefix, Child); }
2066
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002067 void printLeft(OutputBuffer &OB) const override {
2068 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002069 Child->printAsOperand(OB, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00002070 }
2071};
2072
2073class FunctionParam : public Node {
2074 StringView Number;
2075
2076public:
2077 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
2078
2079 template<typename Fn> void match(Fn F) const { F(Number); }
2080
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002081 void printLeft(OutputBuffer &OB) const override {
2082 OB += "fp";
2083 OB += Number;
Richard Smithc20d1442018-08-20 20:14:49 +00002084 }
2085};
2086
2087class ConversionExpr : public Node {
2088 const Node *Type;
2089 NodeArray Expressions;
2090
2091public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002092 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2093 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002094
2095 template<typename Fn> void match(Fn F) const { F(Type, Expressions); }
2096
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002097 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002098 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002099 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002100 OB.printClose();
2101 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002102 Expressions.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002103 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002104 }
2105};
2106
Richard Smith1865d2f2020-10-22 19:29:36 -07002107class PointerToMemberConversionExpr : public Node {
2108 const Node *Type;
2109 const Node *SubExpr;
2110 StringView Offset;
2111
2112public:
2113 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002114 StringView Offset_, Prec Prec_)
2115 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2116 SubExpr(SubExpr_), Offset(Offset_) {}
Richard Smith1865d2f2020-10-22 19:29:36 -07002117
2118 template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); }
2119
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002120 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002121 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002122 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002123 OB.printClose();
2124 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002125 SubExpr->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002126 OB.printClose();
Richard Smith1865d2f2020-10-22 19:29:36 -07002127 }
2128};
2129
Richard Smithc20d1442018-08-20 20:14:49 +00002130class InitListExpr : public Node {
2131 const Node *Ty;
2132 NodeArray Inits;
2133public:
2134 InitListExpr(const Node *Ty_, NodeArray Inits_)
2135 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2136
2137 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2138
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002139 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002140 if (Ty)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002141 Ty->print(OB);
2142 OB += '{';
2143 Inits.printWithComma(OB);
2144 OB += '}';
Richard Smithc20d1442018-08-20 20:14:49 +00002145 }
2146};
2147
2148class BracedExpr : public Node {
2149 const Node *Elem;
2150 const Node *Init;
2151 bool IsArray;
2152public:
2153 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2154 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2155
2156 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
2157
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002158 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002159 if (IsArray) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002160 OB += '[';
2161 Elem->print(OB);
2162 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002163 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002164 OB += '.';
2165 Elem->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002166 }
2167 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002168 OB += " = ";
2169 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002170 }
2171};
2172
2173class BracedRangeExpr : public Node {
2174 const Node *First;
2175 const Node *Last;
2176 const Node *Init;
2177public:
2178 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2179 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2180
2181 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2182
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002183 void printLeft(OutputBuffer &OB) const override {
2184 OB += '[';
2185 First->print(OB);
2186 OB += " ... ";
2187 Last->print(OB);
2188 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002189 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002190 OB += " = ";
2191 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002192 }
2193};
2194
2195class FoldExpr : public Node {
2196 const Node *Pack, *Init;
2197 StringView OperatorName;
2198 bool IsLeftFold;
2199
2200public:
2201 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
2202 const Node *Init_)
2203 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2204 IsLeftFold(IsLeftFold_) {}
2205
2206 template<typename Fn> void match(Fn F) const {
2207 F(IsLeftFold, OperatorName, Pack, Init);
2208 }
2209
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002210 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002211 auto PrintPack = [&] {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002212 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002213 ParameterPackExpansion(Pack).print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002214 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002215 };
2216
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002217 OB.printOpen();
2218 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2219 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2220 // Fold expr operands are cast-expressions
2221 if (!IsLeftFold || Init != nullptr) {
2222 // '(init|pack) op '
2223 if (IsLeftFold)
2224 Init->printAsOperand(OB, Prec::Cast, true);
2225 else
2226 PrintPack();
2227 OB << " " << OperatorName << " ";
Richard Smithc20d1442018-08-20 20:14:49 +00002228 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002229 OB << "...";
2230 if (IsLeftFold || Init != nullptr) {
2231 // ' op (init|pack)'
2232 OB << " " << OperatorName << " ";
2233 if (IsLeftFold)
2234 PrintPack();
2235 else
2236 Init->printAsOperand(OB, Prec::Cast, true);
2237 }
2238 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002239 }
2240};
2241
2242class ThrowExpr : public Node {
2243 const Node *Op;
2244
2245public:
2246 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2247
2248 template<typename Fn> void match(Fn F) const { F(Op); }
2249
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002250 void printLeft(OutputBuffer &OB) const override {
2251 OB += "throw ";
2252 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002253 }
2254};
2255
2256class BoolExpr : public Node {
2257 bool Value;
2258
2259public:
2260 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2261
2262 template<typename Fn> void match(Fn F) const { F(Value); }
2263
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002264 void printLeft(OutputBuffer &OB) const override {
2265 OB += Value ? StringView("true") : StringView("false");
Richard Smithc20d1442018-08-20 20:14:49 +00002266 }
2267};
2268
Richard Smithdf1c14c2019-09-06 23:53:21 +00002269class StringLiteral : public Node {
2270 const Node *Type;
2271
2272public:
2273 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2274
2275 template<typename Fn> void match(Fn F) const { F(Type); }
2276
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002277 void printLeft(OutputBuffer &OB) const override {
2278 OB += "\"<";
2279 Type->print(OB);
2280 OB += ">\"";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002281 }
2282};
2283
2284class LambdaExpr : public Node {
2285 const Node *Type;
2286
Richard Smithdf1c14c2019-09-06 23:53:21 +00002287public:
2288 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2289
2290 template<typename Fn> void match(Fn F) const { F(Type); }
2291
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002292 void printLeft(OutputBuffer &OB) const override {
2293 OB += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002294 if (Type->getKind() == KClosureTypeName)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002295 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2296 OB += "{...}";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002297 }
2298};
2299
Erik Pilkington0a170f12020-05-13 14:13:37 -04002300class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002301 // ty(integer)
2302 const Node *Ty;
2303 StringView Integer;
2304
2305public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002306 EnumLiteral(const Node *Ty_, StringView Integer_)
2307 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002308
2309 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2310
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002311 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002312 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002313 Ty->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002314 OB.printClose();
Erik Pilkington0a170f12020-05-13 14:13:37 -04002315
2316 if (Integer[0] == 'n')
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002317 OB << "-" << Integer.dropFront(1);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002318 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002319 OB << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002320 }
2321};
2322
2323class IntegerLiteral : public Node {
2324 StringView Type;
2325 StringView Value;
2326
2327public:
2328 IntegerLiteral(StringView Type_, StringView Value_)
2329 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2330
2331 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2332
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002333 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002334 if (Type.size() > 3) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002335 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002336 OB += Type;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002337 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002338 }
2339
2340 if (Value[0] == 'n') {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002341 OB += '-';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002342 OB += Value.dropFront(1);
Richard Smithc20d1442018-08-20 20:14:49 +00002343 } else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002344 OB += Value;
Richard Smithc20d1442018-08-20 20:14:49 +00002345
2346 if (Type.size() <= 3)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002347 OB += Type;
Richard Smithc20d1442018-08-20 20:14:49 +00002348 }
2349};
2350
2351template <class Float> struct FloatData;
2352
2353namespace float_literal_impl {
2354constexpr Node::Kind getFloatLiteralKind(float *) {
2355 return Node::KFloatLiteral;
2356}
2357constexpr Node::Kind getFloatLiteralKind(double *) {
2358 return Node::KDoubleLiteral;
2359}
2360constexpr Node::Kind getFloatLiteralKind(long double *) {
2361 return Node::KLongDoubleLiteral;
2362}
2363}
2364
2365template <class Float> class FloatLiteralImpl : public Node {
2366 const StringView Contents;
2367
2368 static constexpr Kind KindForClass =
2369 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2370
2371public:
2372 FloatLiteralImpl(StringView Contents_)
2373 : Node(KindForClass), Contents(Contents_) {}
2374
2375 template<typename Fn> void match(Fn F) const { F(Contents); }
2376
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002377 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002378 const char *first = Contents.begin();
2379 const char *last = Contents.end() + 1;
2380
2381 const size_t N = FloatData<Float>::mangled_size;
2382 if (static_cast<std::size_t>(last - first) > N) {
2383 last = first + N;
2384 union {
2385 Float value;
2386 char buf[sizeof(Float)];
2387 };
2388 const char *t = first;
2389 char *e = buf;
2390 for (; t != last; ++t, ++e) {
2391 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2392 : static_cast<unsigned>(*t - 'a' + 10);
2393 ++t;
2394 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2395 : static_cast<unsigned>(*t - 'a' + 10);
2396 *e = static_cast<char>((d1 << 4) + d0);
2397 }
2398#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2399 std::reverse(buf, e);
2400#endif
2401 char num[FloatData<Float>::max_demangled_size] = {0};
2402 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002403 OB += StringView(num, num + n);
Richard Smithc20d1442018-08-20 20:14:49 +00002404 }
2405 }
2406};
2407
2408using FloatLiteral = FloatLiteralImpl<float>;
2409using DoubleLiteral = FloatLiteralImpl<double>;
2410using LongDoubleLiteral = FloatLiteralImpl<long double>;
2411
2412/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2413/// appropriate derived class.
2414template<typename Fn>
2415void Node::visit(Fn F) const {
2416 switch (K) {
2417#define CASE(X) case K ## X: return F(static_cast<const X*>(this));
2418 FOR_EACH_NODE_KIND(CASE)
2419#undef CASE
2420 }
2421 assert(0 && "unknown mangling node kind");
2422}
2423
2424/// Determine the kind of a node from its type.
2425template<typename NodeT> struct NodeKind;
2426#define SPECIALIZATION(X) \
2427 template<> struct NodeKind<X> { \
2428 static constexpr Node::Kind Kind = Node::K##X; \
2429 static constexpr const char *name() { return #X; } \
2430 };
2431FOR_EACH_NODE_KIND(SPECIALIZATION)
2432#undef SPECIALIZATION
2433
2434#undef FOR_EACH_NODE_KIND
2435
Pavel Labathba825192018-10-16 14:29:14 +00002436template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002437 const char *First;
2438 const char *Last;
2439
2440 // Name stack, this is used by the parser to hold temporary names that were
2441 // parsed. The parser collapses multiple names into new nodes to construct
2442 // the AST. Once the parser is finished, names.size() == 1.
2443 PODSmallVector<Node *, 32> Names;
2444
2445 // Substitution table. Itanium supports name substitutions as a means of
2446 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2447 // table.
2448 PODSmallVector<Node *, 32> Subs;
2449
Richard Smithdf1c14c2019-09-06 23:53:21 +00002450 using TemplateParamList = PODSmallVector<Node *, 8>;
2451
2452 class ScopedTemplateParamList {
2453 AbstractManglingParser *Parser;
2454 size_t OldNumTemplateParamLists;
2455 TemplateParamList Params;
2456
2457 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002458 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2459 : Parser(TheParser),
2460 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002461 Parser->TemplateParams.push_back(&Params);
2462 }
2463 ~ScopedTemplateParamList() {
2464 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2465 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2466 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002467 };
2468
Richard Smithc20d1442018-08-20 20:14:49 +00002469 // Template parameter table. Like the above, but referenced like "T42_".
2470 // This has a smaller size compared to Subs and Names because it can be
2471 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002472 TemplateParamList OuterTemplateParams;
2473
2474 // Lists of template parameters indexed by template parameter depth,
2475 // referenced like "TL2_4_". If nonempty, element 0 is always
2476 // OuterTemplateParams; inner elements are always template parameter lists of
2477 // lambda expressions. For a generic lambda with no explicit template
2478 // parameter list, the corresponding parameter list pointer will be null.
2479 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002480
2481 // Set of unresolved forward <template-param> references. These can occur in a
2482 // conversion operator's type, and are resolved in the enclosing <encoding>.
2483 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2484
Richard Smithc20d1442018-08-20 20:14:49 +00002485 bool TryToParseTemplateArgs = true;
2486 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002487 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2488
2489 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002490
2491 Alloc ASTAllocator;
2492
Pavel Labathba825192018-10-16 14:29:14 +00002493 AbstractManglingParser(const char *First_, const char *Last_)
2494 : First(First_), Last(Last_) {}
2495
2496 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002497
2498 void reset(const char *First_, const char *Last_) {
2499 First = First_;
2500 Last = Last_;
2501 Names.clear();
2502 Subs.clear();
2503 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002504 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002505 TryToParseTemplateArgs = true;
2506 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002507 for (int I = 0; I != 3; ++I)
2508 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002509 ASTAllocator.reset();
2510 }
2511
Richard Smithb485b352018-08-24 23:30:26 +00002512 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002513 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2514 }
2515
2516 template <class It> NodeArray makeNodeArray(It begin, It end) {
2517 size_t sz = static_cast<size_t>(end - begin);
2518 void *mem = ASTAllocator.allocateNodeArray(sz);
2519 Node **data = new (mem) Node *[sz];
2520 std::copy(begin, end, data);
2521 return NodeArray(data, sz);
2522 }
2523
2524 NodeArray popTrailingNodeArray(size_t FromPosition) {
2525 assert(FromPosition <= Names.size());
2526 NodeArray res =
2527 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2528 Names.dropBack(FromPosition);
2529 return res;
2530 }
2531
2532 bool consumeIf(StringView S) {
2533 if (StringView(First, Last).startsWith(S)) {
2534 First += S.size();
2535 return true;
2536 }
2537 return false;
2538 }
2539
2540 bool consumeIf(char C) {
2541 if (First != Last && *First == C) {
2542 ++First;
2543 return true;
2544 }
2545 return false;
2546 }
2547
2548 char consume() { return First != Last ? *First++ : '\0'; }
2549
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08002550 char look(unsigned Lookahead = 0) const {
Richard Smithc20d1442018-08-20 20:14:49 +00002551 if (static_cast<size_t>(Last - First) <= Lookahead)
2552 return '\0';
2553 return First[Lookahead];
2554 }
2555
2556 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2557
2558 StringView parseNumber(bool AllowNegative = false);
2559 Qualifiers parseCVQualifiers();
2560 bool parsePositiveInteger(size_t *Out);
2561 StringView parseBareSourceName();
2562
2563 bool parseSeqId(size_t *Out);
2564 Node *parseSubstitution();
2565 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002566 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002567 Node *parseTemplateArgs(bool TagTemplates = false);
2568 Node *parseTemplateArg();
2569
2570 /// Parse the <expr> production.
2571 Node *parseExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002572 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2573 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00002574 Node *parseIntegerLiteral(StringView Lit);
2575 Node *parseExprPrimary();
2576 template <class Float> Node *parseFloatingLiteral();
2577 Node *parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00002578 Node *parseConversionExpr();
2579 Node *parseBracedExpr();
2580 Node *parseFoldExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002581 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07002582 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002583
2584 /// Parse the <type> production.
2585 Node *parseType();
2586 Node *parseFunctionType();
2587 Node *parseVectorType();
2588 Node *parseDecltype();
2589 Node *parseArrayType();
2590 Node *parsePointerToMemberType();
2591 Node *parseClassEnumType();
2592 Node *parseQualifiedType();
2593
2594 Node *parseEncoding();
2595 bool parseCallOffset();
2596 Node *parseSpecialName();
2597
2598 /// Holds some extra information about a <name> that is being parsed. This
2599 /// information is only pertinent if the <name> refers to an <encoding>.
2600 struct NameState {
2601 bool CtorDtorConversion = false;
2602 bool EndsWithTemplateArgs = false;
2603 Qualifiers CVQualifiers = QualNone;
2604 FunctionRefQual ReferenceQualifier = FrefQualNone;
2605 size_t ForwardTemplateRefsBegin;
2606
Pavel Labathba825192018-10-16 14:29:14 +00002607 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002608 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2609 };
2610
2611 bool resolveForwardTemplateRefs(NameState &State) {
2612 size_t I = State.ForwardTemplateRefsBegin;
2613 size_t E = ForwardTemplateRefs.size();
2614 for (; I < E; ++I) {
2615 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002616 if (TemplateParams.empty() || !TemplateParams[0] ||
2617 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002618 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002619 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002620 }
2621 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2622 return false;
2623 }
2624
2625 /// Parse the <name> production>
2626 Node *parseName(NameState *State = nullptr);
2627 Node *parseLocalName(NameState *State);
2628 Node *parseOperatorName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002629 bool parseModuleNameOpt(ModuleName *&Module);
2630 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
Richard Smithc20d1442018-08-20 20:14:49 +00002631 Node *parseUnnamedTypeName(NameState *State);
2632 Node *parseSourceName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002633 Node *parseUnscopedName(NameState *State, bool *isSubstName);
Richard Smithc20d1442018-08-20 20:14:49 +00002634 Node *parseNestedName(NameState *State);
2635 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2636
2637 Node *parseAbiTags(Node *N);
2638
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002639 struct OperatorInfo {
2640 enum OIKind : unsigned char {
2641 Prefix, // Prefix unary: @ expr
2642 Postfix, // Postfix unary: expr @
2643 Binary, // Binary: lhs @ rhs
2644 Array, // Array index: lhs [ rhs ]
2645 Member, // Member access: lhs @ rhs
2646 New, // New
2647 Del, // Delete
2648 Call, // Function call: expr (expr*)
2649 CCast, // C cast: (type)expr
2650 Conditional, // Conditional: expr ? expr : expr
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08002651 NameOnly, // Overload only, not allowed in expression.
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002652 // Below do not have operator names
2653 NamedCast, // Named cast, @<type>(expr)
2654 OfIdOp, // alignof, sizeof, typeid
2655
2656 Unnameable = NamedCast,
2657 };
2658 char Enc[2]; // Encoding
2659 OIKind Kind; // Kind of operator
2660 bool Flag : 1; // Entry-specific flag
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002661 Node::Prec Prec : 7; // Precedence
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002662 const char *Name; // Spelling
2663
2664 public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002665 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2666 const char *N)
2667 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002668
2669 public:
2670 bool operator<(const OperatorInfo &Other) const {
2671 return *this < Other.Enc;
2672 }
2673 bool operator<(const char *Peek) const {
2674 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2675 }
2676 bool operator==(const char *Peek) const {
2677 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2678 }
2679 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2680
2681 public:
2682 StringView getSymbol() const {
2683 StringView Res = Name;
2684 if (Kind < Unnameable) {
2685 assert(Res.startsWith("operator") &&
2686 "operator name does not start with 'operator'");
2687 Res = Res.dropFront(sizeof("operator") - 1);
2688 Res.consumeFront(' ');
2689 }
2690 return Res;
2691 }
2692 StringView getName() const { return Name; }
2693 OIKind getKind() const { return Kind; }
2694 bool getFlag() const { return Flag; }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002695 Node::Prec getPrecedence() const { return Prec; }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002696 };
2697 const OperatorInfo *parseOperatorEncoding();
2698
Richard Smithc20d1442018-08-20 20:14:49 +00002699 /// Parse the <unresolved-name> production.
Nathan Sidwell77c52e22022-01-28 11:59:03 -08002700 Node *parseUnresolvedName(bool Global);
Richard Smithc20d1442018-08-20 20:14:49 +00002701 Node *parseSimpleId();
2702 Node *parseBaseUnresolvedName();
2703 Node *parseUnresolvedType();
2704 Node *parseDestructorName();
2705
2706 /// Top-level entry point into the parser.
2707 Node *parse();
2708};
2709
2710const char* parse_discriminator(const char* first, const char* last);
2711
2712// <name> ::= <nested-name> // N
2713// ::= <local-name> # See Scope Encoding below // Z
2714// ::= <unscoped-template-name> <template-args>
2715// ::= <unscoped-name>
2716//
2717// <unscoped-template-name> ::= <unscoped-name>
2718// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002719template <typename Derived, typename Alloc>
2720Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002721 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002722 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002723 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002724 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002725
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002726 Node *Result = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002727 bool IsSubst = false;
2728
2729 Result = getDerived().parseUnscopedName(State, &IsSubst);
2730 if (!Result)
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002731 return nullptr;
2732
2733 if (look() == 'I') {
2734 // ::= <unscoped-template-name> <template-args>
2735 if (!IsSubst)
2736 // An unscoped-template-name is substitutable.
2737 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00002738 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002739 if (TA == nullptr)
2740 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002741 if (State)
2742 State->EndsWithTemplateArgs = true;
2743 Result = make<NameWithTemplateArgs>(Result, TA);
2744 } else if (IsSubst) {
2745 // The substitution case must be followed by <template-args>.
2746 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002747 }
2748
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002749 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00002750}
2751
2752// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2753// := Z <function encoding> E s [<discriminator>]
2754// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002755template <typename Derived, typename Alloc>
2756Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002757 if (!consumeIf('Z'))
2758 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002759 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002760 if (Encoding == nullptr || !consumeIf('E'))
2761 return nullptr;
2762
2763 if (consumeIf('s')) {
2764 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002765 auto *StringLitName = make<NameType>("string literal");
2766 if (!StringLitName)
2767 return nullptr;
2768 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002769 }
2770
2771 if (consumeIf('d')) {
2772 parseNumber(true);
2773 if (!consumeIf('_'))
2774 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002775 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002776 if (N == nullptr)
2777 return nullptr;
2778 return make<LocalName>(Encoding, N);
2779 }
2780
Pavel Labathba825192018-10-16 14:29:14 +00002781 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002782 if (Entity == nullptr)
2783 return nullptr;
2784 First = parse_discriminator(First, Last);
2785 return make<LocalName>(Encoding, Entity);
2786}
2787
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08002788// <unscoped-name> ::= [L]* <unqualified-name>
2789// ::= St [L]* <unqualified-name> # ::std::
2790// [*] extension
Pavel Labathba825192018-10-16 14:29:14 +00002791template <typename Derived, typename Alloc>
2792Node *
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002793AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2794 bool *IsSubst) {
2795
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002796 Node *Std = nullptr;
2797 if (consumeIf("St")) {
2798 Std = make<NameType>("std");
2799 if (Std == nullptr)
Nathan Sidwell200e97c2022-01-21 11:37:01 -08002800 return nullptr;
2801 }
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002802 consumeIf('L');
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002803
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002804 Node *Res = nullptr;
2805 ModuleName *Module = nullptr;
2806 if (look() == 'S') {
2807 Node *S = getDerived().parseSubstitution();
2808 if (!S)
2809 return nullptr;
2810 if (S->getKind() == Node::KModuleName)
2811 Module = static_cast<ModuleName *>(S);
2812 else if (IsSubst && Std == nullptr) {
2813 Res = S;
2814 *IsSubst = true;
2815 } else {
2816 return nullptr;
2817 }
2818 }
2819
2820 if (Res == nullptr)
2821 Res = getDerived().parseUnqualifiedName(State, Std, Module);
2822
2823 return Res;
Richard Smithc20d1442018-08-20 20:14:49 +00002824}
2825
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002826// <unqualified-name> ::= [<module-name>] <operator-name> [<abi-tags>]
2827// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
2828// ::= [<module-name>] <source-name> [<abi-tags>]
2829// ::= [<module-name>] <unnamed-type-name> [<abi-tags>]
2830// # structured binding declaration
2831// ::= [<module-name>] DC <source-name>+ E
Pavel Labathba825192018-10-16 14:29:14 +00002832template <typename Derived, typename Alloc>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002833Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2834 NameState *State, Node *Scope, ModuleName *Module) {
2835 if (getDerived().parseModuleNameOpt(Module))
2836 return nullptr;
2837
Richard Smithc20d1442018-08-20 20:14:49 +00002838 Node *Result;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002839 if (look() == 'U') {
Pavel Labathba825192018-10-16 14:29:14 +00002840 Result = getDerived().parseUnnamedTypeName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002841 } else if (look() >= '1' && look() <= '9') {
Pavel Labathba825192018-10-16 14:29:14 +00002842 Result = getDerived().parseSourceName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002843 } else if (consumeIf("DC")) {
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002844 // Structured binding
Richard Smithc20d1442018-08-20 20:14:49 +00002845 size_t BindingsBegin = Names.size();
2846 do {
Pavel Labathba825192018-10-16 14:29:14 +00002847 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002848 if (Binding == nullptr)
2849 return nullptr;
2850 Names.push_back(Binding);
2851 } while (!consumeIf('E'));
2852 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002853 } else if (look() == 'C' || look() == 'D') {
2854 // A <ctor-dtor-name>.
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002855 if (Scope == nullptr || Module != nullptr)
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002856 return nullptr;
2857 Result = getDerived().parseCtorDtorName(Scope, State);
2858 } else {
Pavel Labathba825192018-10-16 14:29:14 +00002859 Result = getDerived().parseOperatorName(State);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002860 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002861
2862 if (Module)
2863 Result = make<ModuleEntity>(Module, Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002864 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002865 Result = getDerived().parseAbiTags(Result);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002866 if (Result != nullptr && Scope != nullptr)
2867 Result = make<NestedName>(Scope, Result);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002868
Richard Smithc20d1442018-08-20 20:14:49 +00002869 return Result;
2870}
2871
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002872// <module-name> ::= <module-subname>
2873// ::= <module-name> <module-subname>
2874// ::= <substitution> # passed in by caller
2875// <module-subname> ::= W <source-name>
2876// ::= W P <source-name>
2877template <typename Derived, typename Alloc>
2878bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2879 ModuleName *&Module) {
2880 while (consumeIf('W')) {
2881 bool IsPartition = consumeIf('P');
2882 Node *Sub = getDerived().parseSourceName(nullptr);
2883 if (!Sub)
2884 return true;
2885 Module =
2886 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2887 Subs.push_back(Module);
2888 }
2889
2890 return false;
2891}
2892
Richard Smithc20d1442018-08-20 20:14:49 +00002893// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2894// ::= <closure-type-name>
2895//
2896// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2897//
2898// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002899template <typename Derived, typename Alloc>
2900Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002901AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2902 // <template-params> refer to the innermost <template-args>. Clear out any
2903 // outer args that we may have inserted into TemplateParams.
2904 if (State != nullptr)
2905 TemplateParams.clear();
2906
Richard Smithc20d1442018-08-20 20:14:49 +00002907 if (consumeIf("Ut")) {
2908 StringView Count = parseNumber();
2909 if (!consumeIf('_'))
2910 return nullptr;
2911 return make<UnnamedTypeName>(Count);
2912 }
2913 if (consumeIf("Ul")) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002914 SwapAndRestore<size_t> SwapParams(ParsingLambdaParamsAtLevel,
2915 TemplateParams.size());
2916 ScopedTemplateParamList LambdaTemplateParams(this);
2917
2918 size_t ParamsBegin = Names.size();
2919 while (look() == 'T' &&
2920 StringView("yptn").find(look(1)) != StringView::npos) {
2921 Node *T = parseTemplateParamDecl();
2922 if (!T)
2923 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002924 Names.push_back(T);
2925 }
2926 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2927
2928 // FIXME: If TempParams is empty and none of the function parameters
2929 // includes 'auto', we should remove LambdaTemplateParams from the
2930 // TemplateParams list. Unfortunately, we don't find out whether there are
2931 // any 'auto' parameters until too late in an example such as:
2932 //
2933 // template<typename T> void f(
2934 // decltype([](decltype([]<typename T>(T v) {}),
2935 // auto) {})) {}
2936 // template<typename T> void f(
2937 // decltype([](decltype([]<typename T>(T w) {}),
2938 // int) {})) {}
2939 //
2940 // Here, the type of v is at level 2 but the type of w is at level 1. We
2941 // don't find this out until we encounter the type of the next parameter.
2942 //
2943 // However, compilers can't actually cope with the former example in
2944 // practice, and it's likely to be made ill-formed in future, so we don't
2945 // need to support it here.
2946 //
2947 // If we encounter an 'auto' in the function parameter types, we will
2948 // recreate a template parameter scope for it, but any intervening lambdas
2949 // will be parsed in the 'wrong' template parameter depth.
2950 if (TempParams.empty())
2951 TemplateParams.pop_back();
2952
Richard Smithc20d1442018-08-20 20:14:49 +00002953 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002954 do {
Pavel Labathba825192018-10-16 14:29:14 +00002955 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002956 if (P == nullptr)
2957 return nullptr;
2958 Names.push_back(P);
2959 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002960 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002961 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2962
Richard Smithc20d1442018-08-20 20:14:49 +00002963 StringView Count = parseNumber();
2964 if (!consumeIf('_'))
2965 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002966 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002967 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002968 if (consumeIf("Ub")) {
2969 (void)parseNumber();
2970 if (!consumeIf('_'))
2971 return nullptr;
2972 return make<NameType>("'block-literal'");
2973 }
Richard Smithc20d1442018-08-20 20:14:49 +00002974 return nullptr;
2975}
2976
2977// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002978template <typename Derived, typename Alloc>
2979Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002980 size_t Length = 0;
2981 if (parsePositiveInteger(&Length))
2982 return nullptr;
2983 if (numLeft() < Length || Length == 0)
2984 return nullptr;
2985 StringView Name(First, First + Length);
2986 First += Length;
2987 if (Name.startsWith("_GLOBAL__N"))
2988 return make<NameType>("(anonymous namespace)");
2989 return make<NameType>(Name);
2990}
2991
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002992// If the next 2 chars are an operator encoding, consume them and return their
2993// OperatorInfo. Otherwise return nullptr.
2994template <typename Derived, typename Alloc>
2995const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
2996AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
2997 static const OperatorInfo Ops[] = {
2998 // Keep ordered by encoding
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002999 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
3000 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
3001 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
3002 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
3003 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
3004 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary,
3005 "alignof "},
3006 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
3007 "operator co_await"},
3008 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
3009 "alignof "},
3010 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
3011 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
3012 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
3013 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
3014 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast,
3015 "operator"}, // C Cast
3016 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
3017 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
3018 "operator delete[]"},
3019 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3020 "dynamic_cast"},
3021 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
3022 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
3023 "operator delete"},
3024 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3025 "operator.*"},
3026 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
3027 "operator."},
3028 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
3029 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
3030 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
3031 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
3032 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
3033 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
3034 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
3035 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
3036 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
3037 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
3038 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
3039 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
3040 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
3041 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
3042 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3043 "operator*"},
3044 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
3045 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
3046 "operator new[]"},
3047 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
3048 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
3049 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
3050 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary,
3051 "operator new"},
3052 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
3053 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
3054 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
3055 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
3056 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
3057 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3058 "operator->*"},
3059 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
3060 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
3061 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
3062 "operator->"},
3063 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
3064 "operator?"},
3065 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
3066 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
3067 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3068 "reinterpret_cast"},
3069 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3070 "operator%"},
3071 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3072 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3073 "static_cast"},
3074 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3075 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3076 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
3077 "sizeof "},
3078 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3079 "typeid "},
3080 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix,
3081 "typeid "},
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003082 };
3083 const auto NumOps = sizeof(Ops) / sizeof(Ops[0]);
3084
3085#ifndef NDEBUG
3086 {
3087 // Verify table order.
3088 static bool Done;
3089 if (!Done) {
3090 Done = true;
3091 for (const auto *Op = &Ops[0]; Op != &Ops[NumOps - 1]; Op++)
3092 assert(Op[0] < Op[1] && "Operator table is not ordered");
3093 }
3094 }
3095#endif
3096
3097 if (numLeft() < 2)
3098 return nullptr;
3099
3100 auto Op = std::lower_bound(
3101 &Ops[0], &Ops[NumOps], First,
3102 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3103 if (Op == &Ops[NumOps] || *Op != First)
3104 return nullptr;
3105
3106 First += 2;
3107 return Op;
3108}
3109
3110// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003111// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003112// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003113template <typename Derived, typename Alloc>
3114Node *
3115AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003116 if (const auto *Op = parseOperatorEncoding()) {
3117 if (Op->getKind() == OperatorInfo::CCast) {
3118 // ::= cv <type> # (cast)
Richard Smithc20d1442018-08-20 20:14:49 +00003119 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
3120 // If we're parsing an encoding, State != nullptr and the conversion
3121 // operators' <type> could have a <template-param> that refers to some
3122 // <template-arg>s further ahead in the mangled name.
3123 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
3124 PermitForwardTemplateReferences ||
3125 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003126 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003127 if (Ty == nullptr)
3128 return nullptr;
3129 if (State) State->CtorDtorConversion = true;
3130 return make<ConversionOperatorType>(Ty);
3131 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003132
3133 if (Op->getKind() >= OperatorInfo::Unnameable)
3134 /* Not a nameable operator. */
3135 return nullptr;
3136 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3137 /* Not a nameable MemberExpr */
3138 return nullptr;
3139
3140 return make<NameType>(Op->getName());
3141 }
3142
3143 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003144 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003145 Node *SN = getDerived().parseSourceName(State);
3146 if (SN == nullptr)
3147 return nullptr;
3148 return make<LiteralOperator>(SN);
3149 }
3150
3151 if (consumeIf('v')) {
3152 // ::= v <digit> <source-name> # vendor extended operator
3153 if (look() >= '0' && look() <= '9') {
3154 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003155 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003156 if (SN == nullptr)
3157 return nullptr;
3158 return make<ConversionOperatorType>(SN);
3159 }
3160 return nullptr;
3161 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003162
Richard Smithc20d1442018-08-20 20:14:49 +00003163 return nullptr;
3164}
3165
3166// <ctor-dtor-name> ::= C1 # complete object constructor
3167// ::= C2 # base object constructor
3168// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003169// extension ::= C4 # gcc old-style "[unified]" constructor
3170// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003171// ::= D0 # deleting destructor
3172// ::= D1 # complete object destructor
3173// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003174// extension ::= D4 # gcc old-style "[unified]" destructor
3175// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003176template <typename Derived, typename Alloc>
3177Node *
3178AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3179 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003180 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3181 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3182 switch (SSK) {
3183 case SpecialSubKind::string:
3184 case SpecialSubKind::istream:
3185 case SpecialSubKind::ostream:
3186 case SpecialSubKind::iostream:
3187 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00003188 if (!SoFar)
3189 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00003190 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003191 default:
3192 break;
3193 }
3194 }
3195
3196 if (consumeIf('C')) {
3197 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003198 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3199 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003200 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003201 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003202 ++First;
3203 if (State) State->CtorDtorConversion = true;
3204 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003205 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003206 return nullptr;
3207 }
Nico Weber29294792019-04-03 23:14:33 +00003208 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003209 }
3210
Nico Weber29294792019-04-03 23:14:33 +00003211 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3212 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003213 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003214 First += 2;
3215 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003216 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003217 }
3218
3219 return nullptr;
3220}
3221
3222// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3223// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3224//
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003225// <prefix> ::= <prefix> [L]* <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003226// ::= <template-prefix> <template-args>
3227// ::= <template-param>
3228// ::= <decltype>
3229// ::= # empty
3230// ::= <substitution>
3231// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003232// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003233//
3234// <data-member-prefix> := <member source-name> [<template-args>] M
3235//
3236// <template-prefix> ::= <prefix> <template unqualified-name>
3237// ::= <template-param>
3238// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003239template <typename Derived, typename Alloc>
3240Node *
3241AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003242 if (!consumeIf('N'))
3243 return nullptr;
3244
3245 Qualifiers CVTmp = parseCVQualifiers();
3246 if (State) State->CVQualifiers = CVTmp;
3247
3248 if (consumeIf('O')) {
3249 if (State) State->ReferenceQualifier = FrefQualRValue;
3250 } else if (consumeIf('R')) {
3251 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003252 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003253 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003254 }
Richard Smithc20d1442018-08-20 20:14:49 +00003255
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003256 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003257 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003258 if (State)
3259 // Only set end-with-template on the case that does that.
3260 State->EndsWithTemplateArgs = false;
3261
Richard Smithc20d1442018-08-20 20:14:49 +00003262 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003263 // ::= <template-param>
3264 if (SoFar != nullptr)
3265 return nullptr; // Cannot have a prefix.
3266 SoFar = getDerived().parseTemplateParam();
3267 } else if (look() == 'I') {
3268 // ::= <template-prefix> <template-args>
3269 if (SoFar == nullptr)
3270 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003271 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003272 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003273 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003274 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3275 // Semantically <template-args> <template-args> cannot be generated by a
3276 // C++ entity. There will always be [something like] a name between
3277 // them.
3278 return nullptr;
3279 if (State)
3280 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003281 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003282 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3283 // ::= <decltype>
3284 if (SoFar != nullptr)
3285 return nullptr; // Cannot have a prefix.
3286 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003287 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003288 ModuleName *Module = nullptr;
3289 bool IsLocal = consumeIf('L'); // extension
3290
3291 if (look() == 'S') {
3292 // ::= <substitution>
3293 Node *S = nullptr;
3294 if (look(1) == 't') {
3295 First += 2;
3296 S = make<NameType>("std");
3297 } else {
3298 S = getDerived().parseSubstitution();
3299 }
3300 if (!S)
3301 return nullptr;
3302 if (S->getKind() == Node::KModuleName) {
3303 Module = static_cast<ModuleName *>(S);
3304 } else if (SoFar != nullptr || IsLocal) {
3305 return nullptr; // Cannot have a prefix.
3306 } else {
3307 SoFar = S;
3308 continue; // Do not push a new substitution.
3309 }
3310 }
3311
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003312 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003313 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003314 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003315
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003316 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003317 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003318 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003319
3320 // No longer used.
3321 // <data-member-prefix> := <member source-name> [<template-args>] M
3322 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003323 }
3324
3325 if (SoFar == nullptr || Subs.empty())
3326 return nullptr;
3327
3328 Subs.pop_back();
3329 return SoFar;
3330}
3331
3332// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003333template <typename Derived, typename Alloc>
3334Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3335 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003336 if (SN == nullptr)
3337 return nullptr;
3338 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003339 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003340 if (TA == nullptr)
3341 return nullptr;
3342 return make<NameWithTemplateArgs>(SN, TA);
3343 }
3344 return SN;
3345}
3346
3347// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3348// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003349template <typename Derived, typename Alloc>
3350Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003351 Node *Result;
3352 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003353 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003354 else
Pavel Labathba825192018-10-16 14:29:14 +00003355 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003356 if (Result == nullptr)
3357 return nullptr;
3358 return make<DtorName>(Result);
3359}
3360
3361// <unresolved-type> ::= <template-param>
3362// ::= <decltype>
3363// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003364template <typename Derived, typename Alloc>
3365Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003366 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003367 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003368 if (TP == nullptr)
3369 return nullptr;
3370 Subs.push_back(TP);
3371 return TP;
3372 }
3373 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003374 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003375 if (DT == nullptr)
3376 return nullptr;
3377 Subs.push_back(DT);
3378 return DT;
3379 }
Pavel Labathba825192018-10-16 14:29:14 +00003380 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003381}
3382
3383// <base-unresolved-name> ::= <simple-id> # unresolved name
3384// extension ::= <operator-name> # unresolved operator-function-id
3385// extension ::= <operator-name> <template-args> # unresolved operator template-id
3386// ::= on <operator-name> # unresolved operator-function-id
3387// ::= on <operator-name> <template-args> # unresolved operator template-id
3388// ::= dn <destructor-name> # destructor or pseudo-destructor;
3389// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003390template <typename Derived, typename Alloc>
3391Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003392 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003393 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003394
3395 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003396 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003397
3398 consumeIf("on");
3399
Pavel Labathba825192018-10-16 14:29:14 +00003400 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003401 if (Oper == nullptr)
3402 return nullptr;
3403 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003404 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003405 if (TA == nullptr)
3406 return nullptr;
3407 return make<NameWithTemplateArgs>(Oper, TA);
3408 }
3409 return Oper;
3410}
3411
3412// <unresolved-name>
3413// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3414// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3415// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3416// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003417// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003418// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3419// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3420// # T::N::x /decltype(p)::N::x
3421// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3422//
3423// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003424template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003425Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003426 Node *SoFar = nullptr;
3427
3428 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3429 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3430 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003431 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003432 if (SoFar == nullptr)
3433 return nullptr;
3434
3435 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003436 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003437 if (TA == nullptr)
3438 return nullptr;
3439 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003440 if (!SoFar)
3441 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003442 }
3443
3444 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003445 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003446 if (Qual == nullptr)
3447 return nullptr;
3448 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003449 if (!SoFar)
3450 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003451 }
3452
Pavel Labathba825192018-10-16 14:29:14 +00003453 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003454 if (Base == nullptr)
3455 return nullptr;
3456 return make<QualifiedName>(SoFar, Base);
3457 }
3458
Richard Smithc20d1442018-08-20 20:14:49 +00003459 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3460 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003461 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003462 if (SoFar == nullptr)
3463 return nullptr;
3464 if (Global)
3465 SoFar = make<GlobalQualifiedName>(SoFar);
3466 return SoFar;
3467 }
3468
3469 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3470 if (std::isdigit(look())) {
3471 do {
Pavel Labathba825192018-10-16 14:29:14 +00003472 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003473 if (Qual == nullptr)
3474 return nullptr;
3475 if (SoFar)
3476 SoFar = make<QualifiedName>(SoFar, Qual);
3477 else if (Global)
3478 SoFar = make<GlobalQualifiedName>(Qual);
3479 else
3480 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003481 if (!SoFar)
3482 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003483 } while (!consumeIf('E'));
3484 }
3485 // sr <unresolved-type> <base-unresolved-name>
3486 // sr <unresolved-type> <template-args> <base-unresolved-name>
3487 else {
Pavel Labathba825192018-10-16 14:29:14 +00003488 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003489 if (SoFar == nullptr)
3490 return nullptr;
3491
3492 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003493 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003494 if (TA == nullptr)
3495 return nullptr;
3496 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003497 if (!SoFar)
3498 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003499 }
3500 }
3501
3502 assert(SoFar != nullptr);
3503
Pavel Labathba825192018-10-16 14:29:14 +00003504 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003505 if (Base == nullptr)
3506 return nullptr;
3507 return make<QualifiedName>(SoFar, Base);
3508}
3509
3510// <abi-tags> ::= <abi-tag> [<abi-tags>]
3511// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003512template <typename Derived, typename Alloc>
3513Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003514 while (consumeIf('B')) {
3515 StringView SN = parseBareSourceName();
3516 if (SN.empty())
3517 return nullptr;
3518 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003519 if (!N)
3520 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003521 }
3522 return N;
3523}
3524
3525// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003526template <typename Alloc, typename Derived>
3527StringView
3528AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003529 const char *Tmp = First;
3530 if (AllowNegative)
3531 consumeIf('n');
3532 if (numLeft() == 0 || !std::isdigit(*First))
3533 return StringView();
3534 while (numLeft() != 0 && std::isdigit(*First))
3535 ++First;
3536 return StringView(Tmp, First);
3537}
3538
3539// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003540template <typename Alloc, typename Derived>
3541bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003542 *Out = 0;
3543 if (look() < '0' || look() > '9')
3544 return true;
3545 while (look() >= '0' && look() <= '9') {
3546 *Out *= 10;
3547 *Out += static_cast<size_t>(consume() - '0');
3548 }
3549 return false;
3550}
3551
Pavel Labathba825192018-10-16 14:29:14 +00003552template <typename Alloc, typename Derived>
3553StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003554 size_t Int = 0;
3555 if (parsePositiveInteger(&Int) || numLeft() < Int)
3556 return StringView();
3557 StringView R(First, First + Int);
3558 First += Int;
3559 return R;
3560}
3561
3562// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3563//
3564// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3565// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3566// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3567//
3568// <ref-qualifier> ::= R # & ref-qualifier
3569// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003570template <typename Derived, typename Alloc>
3571Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003572 Qualifiers CVQuals = parseCVQualifiers();
3573
3574 Node *ExceptionSpec = nullptr;
3575 if (consumeIf("Do")) {
3576 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003577 if (!ExceptionSpec)
3578 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003579 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003580 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003581 if (E == nullptr || !consumeIf('E'))
3582 return nullptr;
3583 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003584 if (!ExceptionSpec)
3585 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003586 } else if (consumeIf("Dw")) {
3587 size_t SpecsBegin = Names.size();
3588 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003589 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003590 if (T == nullptr)
3591 return nullptr;
3592 Names.push_back(T);
3593 }
3594 ExceptionSpec =
3595 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003596 if (!ExceptionSpec)
3597 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003598 }
3599
3600 consumeIf("Dx"); // transaction safe
3601
3602 if (!consumeIf('F'))
3603 return nullptr;
3604 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003605 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003606 if (ReturnType == nullptr)
3607 return nullptr;
3608
3609 FunctionRefQual ReferenceQualifier = FrefQualNone;
3610 size_t ParamsBegin = Names.size();
3611 while (true) {
3612 if (consumeIf('E'))
3613 break;
3614 if (consumeIf('v'))
3615 continue;
3616 if (consumeIf("RE")) {
3617 ReferenceQualifier = FrefQualLValue;
3618 break;
3619 }
3620 if (consumeIf("OE")) {
3621 ReferenceQualifier = FrefQualRValue;
3622 break;
3623 }
Pavel Labathba825192018-10-16 14:29:14 +00003624 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003625 if (T == nullptr)
3626 return nullptr;
3627 Names.push_back(T);
3628 }
3629
3630 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3631 return make<FunctionType>(ReturnType, Params, CVQuals,
3632 ReferenceQualifier, ExceptionSpec);
3633}
3634
3635// extension:
3636// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3637// ::= Dv [<dimension expression>] _ <element type>
3638// <extended element type> ::= <element type>
3639// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003640template <typename Derived, typename Alloc>
3641Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003642 if (!consumeIf("Dv"))
3643 return nullptr;
3644 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003645 Node *DimensionNumber = make<NameType>(parseNumber());
3646 if (!DimensionNumber)
3647 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003648 if (!consumeIf('_'))
3649 return nullptr;
3650 if (consumeIf('p'))
3651 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003652 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003653 if (ElemType == nullptr)
3654 return nullptr;
3655 return make<VectorType>(ElemType, DimensionNumber);
3656 }
3657
3658 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003659 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003660 if (!DimExpr)
3661 return nullptr;
3662 if (!consumeIf('_'))
3663 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003664 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003665 if (!ElemType)
3666 return nullptr;
3667 return make<VectorType>(ElemType, DimExpr);
3668 }
Pavel Labathba825192018-10-16 14:29:14 +00003669 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003670 if (!ElemType)
3671 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003672 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003673}
3674
3675// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3676// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003677template <typename Derived, typename Alloc>
3678Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003679 if (!consumeIf('D'))
3680 return nullptr;
3681 if (!consumeIf('t') && !consumeIf('T'))
3682 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003683 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003684 if (E == nullptr)
3685 return nullptr;
3686 if (!consumeIf('E'))
3687 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003688 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003689}
3690
3691// <array-type> ::= A <positive dimension number> _ <element type>
3692// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003693template <typename Derived, typename Alloc>
3694Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003695 if (!consumeIf('A'))
3696 return nullptr;
3697
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003698 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003699
Richard Smithc20d1442018-08-20 20:14:49 +00003700 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003701 Dimension = make<NameType>(parseNumber());
3702 if (!Dimension)
3703 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003704 if (!consumeIf('_'))
3705 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003706 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003707 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003708 if (DimExpr == nullptr)
3709 return nullptr;
3710 if (!consumeIf('_'))
3711 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003712 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003713 }
3714
Pavel Labathba825192018-10-16 14:29:14 +00003715 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003716 if (Ty == nullptr)
3717 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003718 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003719}
3720
3721// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003722template <typename Derived, typename Alloc>
3723Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003724 if (!consumeIf('M'))
3725 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003726 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003727 if (ClassType == nullptr)
3728 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003729 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003730 if (MemberType == nullptr)
3731 return nullptr;
3732 return make<PointerToMemberType>(ClassType, MemberType);
3733}
3734
3735// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3736// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3737// ::= Tu <name> # dependent elaborated type specifier using 'union'
3738// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003739template <typename Derived, typename Alloc>
3740Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003741 StringView ElabSpef;
3742 if (consumeIf("Ts"))
3743 ElabSpef = "struct";
3744 else if (consumeIf("Tu"))
3745 ElabSpef = "union";
3746 else if (consumeIf("Te"))
3747 ElabSpef = "enum";
3748
Pavel Labathba825192018-10-16 14:29:14 +00003749 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003750 if (Name == nullptr)
3751 return nullptr;
3752
3753 if (!ElabSpef.empty())
3754 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3755
3756 return Name;
3757}
3758
3759// <qualified-type> ::= <qualifiers> <type>
3760// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3761// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003762template <typename Derived, typename Alloc>
3763Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003764 if (consumeIf('U')) {
3765 StringView Qual = parseBareSourceName();
3766 if (Qual.empty())
3767 return nullptr;
3768
Richard Smithc20d1442018-08-20 20:14:49 +00003769 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3770 if (Qual.startsWith("objcproto")) {
3771 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3772 StringView Proto;
3773 {
3774 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3775 SaveLast(Last, ProtoSourceName.end());
3776 Proto = parseBareSourceName();
3777 }
3778 if (Proto.empty())
3779 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003780 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003781 if (Child == nullptr)
3782 return nullptr;
3783 return make<ObjCProtoName>(Child, Proto);
3784 }
3785
Alex Orlovf50df922021-03-24 10:21:32 +04003786 Node *TA = nullptr;
3787 if (look() == 'I') {
3788 TA = getDerived().parseTemplateArgs();
3789 if (TA == nullptr)
3790 return nullptr;
3791 }
3792
Pavel Labathba825192018-10-16 14:29:14 +00003793 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003794 if (Child == nullptr)
3795 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003796 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003797 }
3798
3799 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003800 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003801 if (Ty == nullptr)
3802 return nullptr;
3803 if (Quals != QualNone)
3804 Ty = make<QualType>(Ty, Quals);
3805 return Ty;
3806}
3807
3808// <type> ::= <builtin-type>
3809// ::= <qualified-type>
3810// ::= <function-type>
3811// ::= <class-enum-type>
3812// ::= <array-type>
3813// ::= <pointer-to-member-type>
3814// ::= <template-param>
3815// ::= <template-template-param> <template-args>
3816// ::= <decltype>
3817// ::= P <type> # pointer
3818// ::= R <type> # l-value reference
3819// ::= O <type> # r-value reference (C++11)
3820// ::= C <type> # complex pair (C99)
3821// ::= G <type> # imaginary (C99)
3822// ::= <substitution> # See Compression below
3823// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3824// extension ::= <vector-type> # <vector-type> starts with Dv
3825//
3826// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3827// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003828template <typename Derived, typename Alloc>
3829Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003830 Node *Result = nullptr;
3831
Richard Smithc20d1442018-08-20 20:14:49 +00003832 switch (look()) {
3833 // ::= <qualified-type>
3834 case 'r':
3835 case 'V':
3836 case 'K': {
3837 unsigned AfterQuals = 0;
3838 if (look(AfterQuals) == 'r') ++AfterQuals;
3839 if (look(AfterQuals) == 'V') ++AfterQuals;
3840 if (look(AfterQuals) == 'K') ++AfterQuals;
3841
3842 if (look(AfterQuals) == 'F' ||
3843 (look(AfterQuals) == 'D' &&
3844 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3845 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003846 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003847 break;
3848 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003849 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003850 }
3851 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003852 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003853 break;
3854 }
3855 // <builtin-type> ::= v # void
3856 case 'v':
3857 ++First;
3858 return make<NameType>("void");
3859 // ::= w # wchar_t
3860 case 'w':
3861 ++First;
3862 return make<NameType>("wchar_t");
3863 // ::= b # bool
3864 case 'b':
3865 ++First;
3866 return make<NameType>("bool");
3867 // ::= c # char
3868 case 'c':
3869 ++First;
3870 return make<NameType>("char");
3871 // ::= a # signed char
3872 case 'a':
3873 ++First;
3874 return make<NameType>("signed char");
3875 // ::= h # unsigned char
3876 case 'h':
3877 ++First;
3878 return make<NameType>("unsigned char");
3879 // ::= s # short
3880 case 's':
3881 ++First;
3882 return make<NameType>("short");
3883 // ::= t # unsigned short
3884 case 't':
3885 ++First;
3886 return make<NameType>("unsigned short");
3887 // ::= i # int
3888 case 'i':
3889 ++First;
3890 return make<NameType>("int");
3891 // ::= j # unsigned int
3892 case 'j':
3893 ++First;
3894 return make<NameType>("unsigned int");
3895 // ::= l # long
3896 case 'l':
3897 ++First;
3898 return make<NameType>("long");
3899 // ::= m # unsigned long
3900 case 'm':
3901 ++First;
3902 return make<NameType>("unsigned long");
3903 // ::= x # long long, __int64
3904 case 'x':
3905 ++First;
3906 return make<NameType>("long long");
3907 // ::= y # unsigned long long, __int64
3908 case 'y':
3909 ++First;
3910 return make<NameType>("unsigned long long");
3911 // ::= n # __int128
3912 case 'n':
3913 ++First;
3914 return make<NameType>("__int128");
3915 // ::= o # unsigned __int128
3916 case 'o':
3917 ++First;
3918 return make<NameType>("unsigned __int128");
3919 // ::= f # float
3920 case 'f':
3921 ++First;
3922 return make<NameType>("float");
3923 // ::= d # double
3924 case 'd':
3925 ++First;
3926 return make<NameType>("double");
3927 // ::= e # long double, __float80
3928 case 'e':
3929 ++First;
3930 return make<NameType>("long double");
3931 // ::= g # __float128
3932 case 'g':
3933 ++First;
3934 return make<NameType>("__float128");
3935 // ::= z # ellipsis
3936 case 'z':
3937 ++First;
3938 return make<NameType>("...");
3939
3940 // <builtin-type> ::= u <source-name> # vendor extended type
3941 case 'u': {
3942 ++First;
3943 StringView Res = parseBareSourceName();
3944 if (Res.empty())
3945 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003946 // Typically, <builtin-type>s are not considered substitution candidates,
3947 // but the exception to that exception is vendor extended types (Itanium C++
3948 // ABI 5.9.1).
3949 Result = make<NameType>(Res);
3950 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003951 }
3952 case 'D':
3953 switch (look(1)) {
3954 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3955 case 'd':
3956 First += 2;
3957 return make<NameType>("decimal64");
3958 // ::= De # IEEE 754r decimal floating point (128 bits)
3959 case 'e':
3960 First += 2;
3961 return make<NameType>("decimal128");
3962 // ::= Df # IEEE 754r decimal floating point (32 bits)
3963 case 'f':
3964 First += 2;
3965 return make<NameType>("decimal32");
3966 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3967 case 'h':
3968 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003969 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003970 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3971 case 'F': {
3972 First += 2;
3973 Node *DimensionNumber = make<NameType>(parseNumber());
3974 if (!DimensionNumber)
3975 return nullptr;
3976 if (!consumeIf('_'))
3977 return nullptr;
3978 return make<BinaryFPType>(DimensionNumber);
3979 }
Richard Smithc20d1442018-08-20 20:14:49 +00003980 // ::= Di # char32_t
3981 case 'i':
3982 First += 2;
3983 return make<NameType>("char32_t");
3984 // ::= Ds # char16_t
3985 case 's':
3986 First += 2;
3987 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003988 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3989 case 'u':
3990 First += 2;
3991 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003992 // ::= Da # auto (in dependent new-expressions)
3993 case 'a':
3994 First += 2;
3995 return make<NameType>("auto");
3996 // ::= Dc # decltype(auto)
3997 case 'c':
3998 First += 2;
3999 return make<NameType>("decltype(auto)");
4000 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
4001 case 'n':
4002 First += 2;
4003 return make<NameType>("std::nullptr_t");
4004
4005 // ::= <decltype>
4006 case 't':
4007 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00004008 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00004009 break;
4010 }
4011 // extension ::= <vector-type> # <vector-type> starts with Dv
4012 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00004013 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00004014 break;
4015 }
4016 // ::= Dp <type> # pack expansion (C++0x)
4017 case 'p': {
4018 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004019 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004020 if (!Child)
4021 return nullptr;
4022 Result = make<ParameterPackExpansion>(Child);
4023 break;
4024 }
4025 // Exception specifier on a function type.
4026 case 'o':
4027 case 'O':
4028 case 'w':
4029 // Transaction safe function type.
4030 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00004031 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00004032 break;
4033 }
4034 break;
4035 // ::= <function-type>
4036 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00004037 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00004038 break;
4039 }
4040 // ::= <array-type>
4041 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00004042 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00004043 break;
4044 }
4045 // ::= <pointer-to-member-type>
4046 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00004047 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00004048 break;
4049 }
4050 // ::= <template-param>
4051 case 'T': {
4052 // This could be an elaborate type specifier on a <class-enum-type>.
4053 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00004054 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004055 break;
4056 }
4057
Pavel Labathba825192018-10-16 14:29:14 +00004058 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004059 if (Result == nullptr)
4060 return nullptr;
4061
4062 // Result could be either of:
4063 // <type> ::= <template-param>
4064 // <type> ::= <template-template-param> <template-args>
4065 //
4066 // <template-template-param> ::= <template-param>
4067 // ::= <substitution>
4068 //
4069 // If this is followed by some <template-args>, and we're permitted to
4070 // parse them, take the second production.
4071
4072 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004073 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004074 if (TA == nullptr)
4075 return nullptr;
4076 Result = make<NameWithTemplateArgs>(Result, TA);
4077 }
4078 break;
4079 }
4080 // ::= P <type> # pointer
4081 case 'P': {
4082 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004083 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004084 if (Ptr == nullptr)
4085 return nullptr;
4086 Result = make<PointerType>(Ptr);
4087 break;
4088 }
4089 // ::= R <type> # l-value reference
4090 case 'R': {
4091 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004092 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004093 if (Ref == nullptr)
4094 return nullptr;
4095 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4096 break;
4097 }
4098 // ::= O <type> # r-value reference (C++11)
4099 case 'O': {
4100 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004101 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004102 if (Ref == nullptr)
4103 return nullptr;
4104 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4105 break;
4106 }
4107 // ::= C <type> # complex pair (C99)
4108 case 'C': {
4109 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004110 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004111 if (P == nullptr)
4112 return nullptr;
4113 Result = make<PostfixQualifiedType>(P, " complex");
4114 break;
4115 }
4116 // ::= G <type> # imaginary (C99)
4117 case 'G': {
4118 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004119 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004120 if (P == nullptr)
4121 return P;
4122 Result = make<PostfixQualifiedType>(P, " imaginary");
4123 break;
4124 }
4125 // ::= <substitution> # See Compression below
4126 case 'S': {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004127 if (look(1) != 't') {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004128 bool IsSubst = false;
4129 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4130 if (!Result)
Richard Smithc20d1442018-08-20 20:14:49 +00004131 return nullptr;
4132
4133 // Sub could be either of:
4134 // <type> ::= <substitution>
4135 // <type> ::= <template-template-param> <template-args>
4136 //
4137 // <template-template-param> ::= <template-param>
4138 // ::= <substitution>
4139 //
4140 // If this is followed by some <template-args>, and we're permitted to
4141 // parse them, take the second production.
4142
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004143 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4144 if (!IsSubst)
4145 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00004146 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004147 if (TA == nullptr)
4148 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004149 Result = make<NameWithTemplateArgs>(Result, TA);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004150 } else if (IsSubst) {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004151 // If all we parsed was a substitution, don't re-insert into the
4152 // substitution table.
4153 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00004154 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004155 break;
Richard Smithc20d1442018-08-20 20:14:49 +00004156 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004157 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004158 }
4159 // ::= <class-enum-type>
4160 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004161 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004162 break;
4163 }
4164 }
4165
4166 // If we parsed a type, insert it into the substitution table. Note that all
4167 // <builtin-type>s and <substitution>s have already bailed out, because they
4168 // don't get substitutions.
4169 if (Result != nullptr)
4170 Subs.push_back(Result);
4171 return Result;
4172}
4173
Pavel Labathba825192018-10-16 14:29:14 +00004174template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004175Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4176 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004177 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004178 if (E == nullptr)
4179 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004180 return make<PrefixExpr>(Kind, E, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004181}
4182
Pavel Labathba825192018-10-16 14:29:14 +00004183template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004184Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4185 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004186 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004187 if (LHS == nullptr)
4188 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004189 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004190 if (RHS == nullptr)
4191 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004192 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004193}
4194
Pavel Labathba825192018-10-16 14:29:14 +00004195template <typename Derived, typename Alloc>
4196Node *
4197AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004198 StringView Tmp = parseNumber(true);
4199 if (!Tmp.empty() && consumeIf('E'))
4200 return make<IntegerLiteral>(Lit, Tmp);
4201 return nullptr;
4202}
4203
4204// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004205template <typename Alloc, typename Derived>
4206Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004207 Qualifiers CVR = QualNone;
4208 if (consumeIf('r'))
4209 CVR |= QualRestrict;
4210 if (consumeIf('V'))
4211 CVR |= QualVolatile;
4212 if (consumeIf('K'))
4213 CVR |= QualConst;
4214 return CVR;
4215}
4216
4217// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4218// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4219// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4220// ::= 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 -04004221// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004222template <typename Derived, typename Alloc>
4223Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004224 if (consumeIf("fpT"))
4225 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004226 if (consumeIf("fp")) {
4227 parseCVQualifiers();
4228 StringView Num = parseNumber();
4229 if (!consumeIf('_'))
4230 return nullptr;
4231 return make<FunctionParam>(Num);
4232 }
4233 if (consumeIf("fL")) {
4234 if (parseNumber().empty())
4235 return nullptr;
4236 if (!consumeIf('p'))
4237 return nullptr;
4238 parseCVQualifiers();
4239 StringView Num = parseNumber();
4240 if (!consumeIf('_'))
4241 return nullptr;
4242 return make<FunctionParam>(Num);
4243 }
4244 return nullptr;
4245}
4246
Richard Smithc20d1442018-08-20 20:14:49 +00004247// cv <type> <expression> # conversion with one argument
4248// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004249template <typename Derived, typename Alloc>
4250Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004251 if (!consumeIf("cv"))
4252 return nullptr;
4253 Node *Ty;
4254 {
4255 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004256 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004257 }
4258
4259 if (Ty == nullptr)
4260 return nullptr;
4261
4262 if (consumeIf('_')) {
4263 size_t ExprsBegin = Names.size();
4264 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004265 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004266 if (E == nullptr)
4267 return E;
4268 Names.push_back(E);
4269 }
4270 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4271 return make<ConversionExpr>(Ty, Exprs);
4272 }
4273
Pavel Labathba825192018-10-16 14:29:14 +00004274 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004275 if (E[0] == nullptr)
4276 return nullptr;
4277 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4278}
4279
4280// <expr-primary> ::= L <type> <value number> E # integer literal
4281// ::= L <type> <value float> E # floating literal
4282// ::= L <string type> E # string literal
4283// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004284// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004285// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4286// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004287template <typename Derived, typename Alloc>
4288Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004289 if (!consumeIf('L'))
4290 return nullptr;
4291 switch (look()) {
4292 case 'w':
4293 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004294 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004295 case 'b':
4296 if (consumeIf("b0E"))
4297 return make<BoolExpr>(0);
4298 if (consumeIf("b1E"))
4299 return make<BoolExpr>(1);
4300 return nullptr;
4301 case 'c':
4302 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004303 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004304 case 'a':
4305 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004306 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004307 case 'h':
4308 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004309 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004310 case 's':
4311 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004312 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004313 case 't':
4314 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004315 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004316 case 'i':
4317 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004318 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004319 case 'j':
4320 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004321 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004322 case 'l':
4323 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004324 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004325 case 'm':
4326 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004327 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004328 case 'x':
4329 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004330 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004331 case 'y':
4332 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004333 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004334 case 'n':
4335 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004336 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004337 case 'o':
4338 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004339 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004340 case 'f':
4341 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004342 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004343 case 'd':
4344 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004345 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004346 case 'e':
4347 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004348#if defined(__powerpc__) || defined(__s390__)
4349 // Handle cases where long doubles encoded with e have the same size
4350 // and representation as doubles.
4351 return getDerived().template parseFloatingLiteral<double>();
4352#else
Pavel Labathba825192018-10-16 14:29:14 +00004353 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004354#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004355 case '_':
4356 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004357 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004358 if (R != nullptr && consumeIf('E'))
4359 return R;
4360 }
4361 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004362 case 'A': {
4363 Node *T = getDerived().parseType();
4364 if (T == nullptr)
4365 return nullptr;
4366 // FIXME: We need to include the string contents in the mangling.
4367 if (consumeIf('E'))
4368 return make<StringLiteral>(T);
4369 return nullptr;
4370 }
4371 case 'D':
4372 if (consumeIf("DnE"))
4373 return make<NameType>("nullptr");
4374 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004375 case 'T':
4376 // Invalid mangled name per
4377 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4378 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004379 case 'U': {
4380 // FIXME: Should we support LUb... for block literals?
4381 if (look(1) != 'l')
4382 return nullptr;
4383 Node *T = parseUnnamedTypeName(nullptr);
4384 if (!T || !consumeIf('E'))
4385 return nullptr;
4386 return make<LambdaExpr>(T);
4387 }
Richard Smithc20d1442018-08-20 20:14:49 +00004388 default: {
4389 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004390 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004391 if (T == nullptr)
4392 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004393 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004394 if (N.empty())
4395 return nullptr;
4396 if (!consumeIf('E'))
4397 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004398 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004399 }
4400 }
4401}
4402
4403// <braced-expression> ::= <expression>
4404// ::= di <field source-name> <braced-expression> # .name = expr
4405// ::= dx <index expression> <braced-expression> # [expr] = expr
4406// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004407template <typename Derived, typename Alloc>
4408Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004409 if (look() == 'd') {
4410 switch (look(1)) {
4411 case 'i': {
4412 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004413 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004414 if (Field == nullptr)
4415 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004416 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004417 if (Init == nullptr)
4418 return nullptr;
4419 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4420 }
4421 case 'x': {
4422 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004423 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004424 if (Index == nullptr)
4425 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004426 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004427 if (Init == nullptr)
4428 return nullptr;
4429 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4430 }
4431 case 'X': {
4432 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004433 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004434 if (RangeBegin == nullptr)
4435 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004436 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004437 if (RangeEnd == nullptr)
4438 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004439 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004440 if (Init == nullptr)
4441 return nullptr;
4442 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4443 }
4444 }
4445 }
Pavel Labathba825192018-10-16 14:29:14 +00004446 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004447}
4448
4449// (not yet in the spec)
4450// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4451// ::= fR <binary-operator-name> <expression> <expression>
4452// ::= fl <binary-operator-name> <expression>
4453// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004454template <typename Derived, typename Alloc>
4455Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004456 if (!consumeIf('f'))
4457 return nullptr;
4458
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004459 bool IsLeftFold = false, HasInitializer = false;
4460 switch (look()) {
4461 default:
Richard Smithc20d1442018-08-20 20:14:49 +00004462 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004463 case 'L':
4464 IsLeftFold = true;
4465 HasInitializer = true;
4466 break;
4467 case 'R':
4468 HasInitializer = true;
4469 break;
4470 case 'l':
4471 IsLeftFold = true;
4472 break;
4473 case 'r':
4474 break;
4475 }
Richard Smithc20d1442018-08-20 20:14:49 +00004476 ++First;
4477
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004478 const auto *Op = parseOperatorEncoding();
4479 if (!Op || Op->getKind() != OperatorInfo::Binary)
4480 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004481
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004482 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004483 if (Pack == nullptr)
4484 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004485
4486 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004487 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004488 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004489 if (Init == nullptr)
4490 return nullptr;
4491 }
4492
4493 if (IsLeftFold && Init)
4494 std::swap(Pack, Init);
4495
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004496 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004497}
4498
Richard Smith1865d2f2020-10-22 19:29:36 -07004499// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4500//
4501// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4502template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004503Node *
4504AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4505 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004506 Node *Ty = getDerived().parseType();
4507 if (!Ty)
4508 return nullptr;
4509 Node *Expr = getDerived().parseExpr();
4510 if (!Expr)
4511 return nullptr;
4512 StringView Offset = getDerived().parseNumber(true);
4513 if (!consumeIf('E'))
4514 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004515 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004516}
4517
4518// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4519// <union-selector> ::= _ [<number>]
4520//
4521// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4522template <typename Derived, typename Alloc>
4523Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4524 Node *Ty = getDerived().parseType();
4525 if (!Ty)
4526 return nullptr;
4527 Node *Expr = getDerived().parseExpr();
4528 if (!Expr)
4529 return nullptr;
4530 StringView Offset = getDerived().parseNumber(true);
4531 size_t SelectorsBegin = Names.size();
4532 while (consumeIf('_')) {
4533 Node *Selector = make<NameType>(parseNumber());
4534 if (!Selector)
4535 return nullptr;
4536 Names.push_back(Selector);
4537 }
4538 bool OnePastTheEnd = consumeIf('p');
4539 if (!consumeIf('E'))
4540 return nullptr;
4541 return make<SubobjectExpr>(
4542 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4543}
4544
Richard Smithc20d1442018-08-20 20:14:49 +00004545// <expression> ::= <unary operator-name> <expression>
4546// ::= <binary operator-name> <expression> <expression>
4547// ::= <ternary operator-name> <expression> <expression> <expression>
4548// ::= cl <expression>+ E # call
4549// ::= cv <type> <expression> # conversion with one argument
4550// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4551// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4552// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4553// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4554// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4555// ::= [gs] dl <expression> # delete expression
4556// ::= [gs] da <expression> # delete[] expression
4557// ::= pp_ <expression> # prefix ++
4558// ::= mm_ <expression> # prefix --
4559// ::= ti <type> # typeid (type)
4560// ::= te <expression> # typeid (expression)
4561// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4562// ::= sc <type> <expression> # static_cast<type> (expression)
4563// ::= cc <type> <expression> # const_cast<type> (expression)
4564// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4565// ::= st <type> # sizeof (a type)
4566// ::= sz <expression> # sizeof (an expression)
4567// ::= at <type> # alignof (a type)
4568// ::= az <expression> # alignof (an expression)
4569// ::= nx <expression> # noexcept (expression)
4570// ::= <template-param>
4571// ::= <function-param>
4572// ::= dt <expression> <unresolved-name> # expr.name
4573// ::= pt <expression> <unresolved-name> # expr->name
4574// ::= ds <expression> <expression> # expr.*expr
4575// ::= sZ <template-param> # size of a parameter pack
4576// ::= sZ <function-param> # size of a function parameter pack
4577// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4578// ::= sp <expression> # pack expansion
4579// ::= tw <expression> # throw expression
4580// ::= tr # throw with no operand (rethrow)
4581// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4582// # freestanding dependent name (e.g., T::x),
4583// # objectless nonstatic member reference
4584// ::= fL <binary-operator-name> <expression> <expression>
4585// ::= fR <binary-operator-name> <expression> <expression>
4586// ::= fl <binary-operator-name> <expression>
4587// ::= fr <binary-operator-name> <expression>
4588// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004589template <typename Derived, typename Alloc>
4590Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004591 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004592
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004593 const auto *Op = parseOperatorEncoding();
4594 if (Op) {
4595 auto Sym = Op->getSymbol();
4596 switch (Op->getKind()) {
4597 case OperatorInfo::Binary:
4598 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004599 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004600 case OperatorInfo::Prefix:
4601 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004602 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004603 case OperatorInfo::Postfix: {
4604 // Postfix unary operator: expr @
4605 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004606 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004607 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004608 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004609 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004610 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004611 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004612 case OperatorInfo::Array: {
4613 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004614 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004615 if (Base == nullptr)
4616 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004617 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004618 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004619 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004620 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004621 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004622 case OperatorInfo::Member: {
4623 // Member access lhs @ rhs
4624 Node *LHS = getDerived().parseExpr();
4625 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004626 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004627 Node *RHS = getDerived().parseExpr();
4628 if (RHS == nullptr)
4629 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004630 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004631 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004632 case OperatorInfo::New: {
4633 // New
4634 // # new (expr-list) type [(init)]
4635 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4636 // # new[] (expr-list) type [(init)]
4637 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004638 size_t Exprs = Names.size();
4639 while (!consumeIf('_')) {
4640 Node *Ex = getDerived().parseExpr();
4641 if (Ex == nullptr)
4642 return nullptr;
4643 Names.push_back(Ex);
4644 }
4645 NodeArray ExprList = popTrailingNodeArray(Exprs);
4646 Node *Ty = getDerived().parseType();
4647 if (Ty == nullptr)
4648 return nullptr;
4649 bool HaveInits = consumeIf("pi");
4650 size_t InitsBegin = Names.size();
4651 while (!consumeIf('E')) {
4652 if (!HaveInits)
4653 return nullptr;
4654 Node *Init = getDerived().parseExpr();
4655 if (Init == nullptr)
4656 return Init;
4657 Names.push_back(Init);
4658 }
4659 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004660 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004661 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004662 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004663 case OperatorInfo::Del: {
4664 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004665 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004666 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004667 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004668 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4669 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004670 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004671 case OperatorInfo::Call: {
4672 // Function Call
4673 Node *Callee = getDerived().parseExpr();
4674 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004675 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004676 size_t ExprsBegin = Names.size();
4677 while (!consumeIf('E')) {
4678 Node *E = getDerived().parseExpr();
4679 if (E == nullptr)
4680 return nullptr;
4681 Names.push_back(E);
4682 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004683 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4684 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004685 }
4686 case OperatorInfo::CCast: {
4687 // C Cast: (type)expr
4688 Node *Ty;
4689 {
4690 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
4691 Ty = getDerived().parseType();
4692 }
4693 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004694 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004695
4696 size_t ExprsBegin = Names.size();
4697 bool IsMany = consumeIf('_');
4698 while (!consumeIf('E')) {
4699 Node *E = getDerived().parseExpr();
4700 if (E == nullptr)
4701 return E;
4702 Names.push_back(E);
4703 if (!IsMany)
4704 break;
4705 }
4706 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4707 if (!IsMany && Exprs.size() != 1)
4708 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004709 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004710 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004711 case OperatorInfo::Conditional: {
4712 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004713 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004714 if (Cond == nullptr)
4715 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004716 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004717 if (LHS == nullptr)
4718 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004719 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004720 if (RHS == nullptr)
4721 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004722 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004723 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004724 case OperatorInfo::NamedCast: {
4725 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004726 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004727 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004728 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004729 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004730 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004731 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004732 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004733 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004734 case OperatorInfo::OfIdOp: {
4735 // [sizeof/alignof/typeid] ( <type>|<expr> )
4736 Node *Arg =
4737 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4738 if (!Arg)
4739 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004740 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004741 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004742 case OperatorInfo::NameOnly: {
4743 // Not valid as an expression operand.
4744 return nullptr;
4745 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004746 }
4747 DEMANGLE_UNREACHABLE;
4748 }
4749
4750 if (numLeft() < 2)
4751 return nullptr;
4752
4753 if (look() == 'L')
4754 return getDerived().parseExprPrimary();
4755 if (look() == 'T')
4756 return getDerived().parseTemplateParam();
4757 if (look() == 'f') {
4758 // Disambiguate a fold expression from a <function-param>.
4759 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4760 return getDerived().parseFunctionParam();
4761 return getDerived().parseFoldExpr();
4762 }
4763 if (consumeIf("il")) {
4764 size_t InitsBegin = Names.size();
4765 while (!consumeIf('E')) {
4766 Node *E = getDerived().parseBracedExpr();
4767 if (E == nullptr)
4768 return nullptr;
4769 Names.push_back(E);
4770 }
4771 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4772 }
4773 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004774 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004775 if (consumeIf("nx")) {
4776 Node *Ex = getDerived().parseExpr();
4777 if (Ex == nullptr)
4778 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004779 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004780 }
4781 if (consumeIf("so"))
4782 return parseSubobjectExpr();
4783 if (consumeIf("sp")) {
4784 Node *Child = getDerived().parseExpr();
4785 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004786 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004787 return make<ParameterPackExpansion>(Child);
4788 }
4789 if (consumeIf("sZ")) {
4790 if (look() == 'T') {
4791 Node *R = getDerived().parseTemplateParam();
4792 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004793 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004794 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004795 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004796 Node *FP = getDerived().parseFunctionParam();
4797 if (FP == nullptr)
4798 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004799 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004800 }
4801 if (consumeIf("sP")) {
4802 size_t ArgsBegin = Names.size();
4803 while (!consumeIf('E')) {
4804 Node *Arg = getDerived().parseTemplateArg();
4805 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004806 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004807 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004808 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004809 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4810 if (!Pack)
4811 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004812 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004813 }
4814 if (consumeIf("tl")) {
4815 Node *Ty = getDerived().parseType();
4816 if (Ty == nullptr)
4817 return nullptr;
4818 size_t InitsBegin = Names.size();
4819 while (!consumeIf('E')) {
4820 Node *E = getDerived().parseBracedExpr();
4821 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004822 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004823 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004824 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004825 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4826 }
4827 if (consumeIf("tr"))
4828 return make<NameType>("throw");
4829 if (consumeIf("tw")) {
4830 Node *Ex = getDerived().parseExpr();
4831 if (Ex == nullptr)
4832 return nullptr;
4833 return make<ThrowExpr>(Ex);
4834 }
4835 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004836 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4837 if (!Name)
4838 return nullptr;
4839 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4840 // standard encoding expects a <template-arg>, and would be otherwise be
4841 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4842 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4843 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004844 bool IsUUID = false;
4845 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004846 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004847 if (consumeIf('t')) {
4848 UUID = getDerived().parseType();
4849 IsUUID = true;
4850 } else if (consumeIf('z')) {
4851 UUID = getDerived().parseExpr();
4852 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004853 }
4854 }
4855 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004856 if (IsUUID) {
4857 if (UUID == nullptr)
4858 return nullptr;
4859 Names.push_back(UUID);
4860 } else {
4861 while (!consumeIf('E')) {
4862 Node *E = getDerived().parseTemplateArg();
4863 if (E == nullptr)
4864 return E;
4865 Names.push_back(E);
4866 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004867 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004868 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4869 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004870 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004871
4872 // Only unresolved names remain.
4873 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004874}
4875
4876// <call-offset> ::= h <nv-offset> _
4877// ::= v <v-offset> _
4878//
4879// <nv-offset> ::= <offset number>
4880// # non-virtual base override
4881//
4882// <v-offset> ::= <offset number> _ <virtual offset number>
4883// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004884template <typename Alloc, typename Derived>
4885bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004886 // Just scan through the call offset, we never add this information into the
4887 // output.
4888 if (consumeIf('h'))
4889 return parseNumber(true).empty() || !consumeIf('_');
4890 if (consumeIf('v'))
4891 return parseNumber(true).empty() || !consumeIf('_') ||
4892 parseNumber(true).empty() || !consumeIf('_');
4893 return true;
4894}
4895
4896// <special-name> ::= TV <type> # virtual table
4897// ::= TT <type> # VTT structure (construction vtable index)
4898// ::= TI <type> # typeinfo structure
4899// ::= TS <type> # typeinfo name (null-terminated byte string)
4900// ::= Tc <call-offset> <call-offset> <base encoding>
4901// # base is the nominal target function of thunk
4902// # first call-offset is 'this' adjustment
4903// # second call-offset is result adjustment
4904// ::= T <call-offset> <base encoding>
4905// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004906// # Guard variable for one-time initialization
4907// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004908// # No <type>
4909// ::= TW <object name> # Thread-local wrapper
4910// ::= TH <object name> # Thread-local initialization
4911// ::= GR <object name> _ # First temporary
4912// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004913// # construction vtable for second-in-first
4914// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004915// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004916// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004917template <typename Derived, typename Alloc>
4918Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004919 switch (look()) {
4920 case 'T':
4921 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004922 // TA <template-arg> # template parameter object
4923 //
4924 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4925 case 'A': {
4926 First += 2;
4927 Node *Arg = getDerived().parseTemplateArg();
4928 if (Arg == nullptr)
4929 return nullptr;
4930 return make<SpecialName>("template parameter object for ", Arg);
4931 }
Richard Smithc20d1442018-08-20 20:14:49 +00004932 // TV <type> # virtual table
4933 case 'V': {
4934 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004935 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004936 if (Ty == nullptr)
4937 return nullptr;
4938 return make<SpecialName>("vtable for ", Ty);
4939 }
4940 // TT <type> # VTT structure (construction vtable index)
4941 case 'T': {
4942 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004943 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004944 if (Ty == nullptr)
4945 return nullptr;
4946 return make<SpecialName>("VTT for ", Ty);
4947 }
4948 // TI <type> # typeinfo structure
4949 case 'I': {
4950 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004951 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004952 if (Ty == nullptr)
4953 return nullptr;
4954 return make<SpecialName>("typeinfo for ", Ty);
4955 }
4956 // TS <type> # typeinfo name (null-terminated byte string)
4957 case 'S': {
4958 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004959 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004960 if (Ty == nullptr)
4961 return nullptr;
4962 return make<SpecialName>("typeinfo name for ", Ty);
4963 }
4964 // Tc <call-offset> <call-offset> <base encoding>
4965 case 'c': {
4966 First += 2;
4967 if (parseCallOffset() || parseCallOffset())
4968 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004969 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004970 if (Encoding == nullptr)
4971 return nullptr;
4972 return make<SpecialName>("covariant return thunk to ", Encoding);
4973 }
4974 // extension ::= TC <first type> <number> _ <second type>
4975 // # construction vtable for second-in-first
4976 case 'C': {
4977 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004978 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004979 if (FirstType == nullptr)
4980 return nullptr;
4981 if (parseNumber(true).empty() || !consumeIf('_'))
4982 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004983 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004984 if (SecondType == nullptr)
4985 return nullptr;
4986 return make<CtorVtableSpecialName>(SecondType, FirstType);
4987 }
4988 // TW <object name> # Thread-local wrapper
4989 case 'W': {
4990 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004991 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004992 if (Name == nullptr)
4993 return nullptr;
4994 return make<SpecialName>("thread-local wrapper routine for ", Name);
4995 }
4996 // TH <object name> # Thread-local initialization
4997 case 'H': {
4998 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004999 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005000 if (Name == nullptr)
5001 return nullptr;
5002 return make<SpecialName>("thread-local initialization routine for ", Name);
5003 }
5004 // T <call-offset> <base encoding>
5005 default: {
5006 ++First;
5007 bool IsVirt = look() == 'v';
5008 if (parseCallOffset())
5009 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00005010 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005011 if (BaseEncoding == nullptr)
5012 return nullptr;
5013 if (IsVirt)
5014 return make<SpecialName>("virtual thunk to ", BaseEncoding);
5015 else
5016 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
5017 }
5018 }
5019 case 'G':
5020 switch (look(1)) {
5021 // GV <object name> # Guard variable for one-time initialization
5022 case 'V': {
5023 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005024 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005025 if (Name == nullptr)
5026 return nullptr;
5027 return make<SpecialName>("guard variable for ", Name);
5028 }
5029 // GR <object name> # reference temporary for object
5030 // GR <object name> _ # First temporary
5031 // GR <object name> <seq-id> _ # Subsequent temporaries
5032 case 'R': {
5033 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005034 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005035 if (Name == nullptr)
5036 return nullptr;
5037 size_t Count;
5038 bool ParsedSeqId = !parseSeqId(&Count);
5039 if (!consumeIf('_') && ParsedSeqId)
5040 return nullptr;
5041 return make<SpecialName>("reference temporary for ", Name);
5042 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08005043 // GI <module-name> v
5044 case 'I': {
5045 First += 2;
5046 ModuleName *Module = nullptr;
5047 if (getDerived().parseModuleNameOpt(Module))
5048 return nullptr;
5049 if (Module == nullptr)
5050 return nullptr;
5051 return make<SpecialName>("initializer for module ", Module);
5052 }
Richard Smithc20d1442018-08-20 20:14:49 +00005053 }
5054 }
5055 return nullptr;
5056}
5057
5058// <encoding> ::= <function name> <bare-function-type>
5059// ::= <data name>
5060// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005061template <typename Derived, typename Alloc>
5062Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005063 // The template parameters of an encoding are unrelated to those of the
5064 // enclosing context.
5065 class SaveTemplateParams {
5066 AbstractManglingParser *Parser;
5067 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005068 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005069
5070 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005071 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005072 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005073 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005074 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005075 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005076 }
5077 ~SaveTemplateParams() {
5078 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005079 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005080 }
5081 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005082
Richard Smithc20d1442018-08-20 20:14:49 +00005083 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005084 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005085
5086 auto IsEndOfEncoding = [&] {
5087 // The set of chars that can potentially follow an <encoding> (none of which
5088 // can start a <type>). Enumerating these allows us to avoid speculative
5089 // parsing.
5090 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5091 };
5092
5093 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005094 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005095 if (Name == nullptr)
5096 return nullptr;
5097
5098 if (resolveForwardTemplateRefs(NameInfo))
5099 return nullptr;
5100
5101 if (IsEndOfEncoding())
5102 return Name;
5103
5104 Node *Attrs = nullptr;
5105 if (consumeIf("Ua9enable_ifI")) {
5106 size_t BeforeArgs = Names.size();
5107 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005108 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005109 if (Arg == nullptr)
5110 return nullptr;
5111 Names.push_back(Arg);
5112 }
5113 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005114 if (!Attrs)
5115 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005116 }
5117
5118 Node *ReturnType = nullptr;
5119 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005120 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005121 if (ReturnType == nullptr)
5122 return nullptr;
5123 }
5124
5125 if (consumeIf('v'))
5126 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5127 Attrs, NameInfo.CVQualifiers,
5128 NameInfo.ReferenceQualifier);
5129
5130 size_t ParamsBegin = Names.size();
5131 do {
Pavel Labathba825192018-10-16 14:29:14 +00005132 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005133 if (Ty == nullptr)
5134 return nullptr;
5135 Names.push_back(Ty);
5136 } while (!IsEndOfEncoding());
5137
5138 return make<FunctionEncoding>(ReturnType, Name,
5139 popTrailingNodeArray(ParamsBegin),
5140 Attrs, NameInfo.CVQualifiers,
5141 NameInfo.ReferenceQualifier);
5142}
5143
5144template <class Float>
5145struct FloatData;
5146
5147template <>
5148struct FloatData<float>
5149{
5150 static const size_t mangled_size = 8;
5151 static const size_t max_demangled_size = 24;
5152 static constexpr const char* spec = "%af";
5153};
5154
5155template <>
5156struct FloatData<double>
5157{
5158 static const size_t mangled_size = 16;
5159 static const size_t max_demangled_size = 32;
5160 static constexpr const char* spec = "%a";
5161};
5162
5163template <>
5164struct FloatData<long double>
5165{
5166#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5167 defined(__wasm__)
5168 static const size_t mangled_size = 32;
5169#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5170 static const size_t mangled_size = 16;
5171#else
5172 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5173#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005174 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5175 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5176 // Negatives are one character longer than positives.
5177 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5178 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5179 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005180 static constexpr const char *spec = "%LaL";
5181};
5182
Pavel Labathba825192018-10-16 14:29:14 +00005183template <typename Alloc, typename Derived>
5184template <class Float>
5185Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005186 const size_t N = FloatData<Float>::mangled_size;
5187 if (numLeft() <= N)
5188 return nullptr;
5189 StringView Data(First, First + N);
5190 for (char C : Data)
5191 if (!std::isxdigit(C))
5192 return nullptr;
5193 First += N;
5194 if (!consumeIf('E'))
5195 return nullptr;
5196 return make<FloatLiteralImpl<Float>>(Data);
5197}
5198
5199// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005200template <typename Alloc, typename Derived>
5201bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005202 if (!(look() >= '0' && look() <= '9') &&
5203 !(look() >= 'A' && look() <= 'Z'))
5204 return true;
5205
5206 size_t Id = 0;
5207 while (true) {
5208 if (look() >= '0' && look() <= '9') {
5209 Id *= 36;
5210 Id += static_cast<size_t>(look() - '0');
5211 } else if (look() >= 'A' && look() <= 'Z') {
5212 Id *= 36;
5213 Id += static_cast<size_t>(look() - 'A') + 10;
5214 } else {
5215 *Out = Id;
5216 return false;
5217 }
5218 ++First;
5219 }
5220}
5221
5222// <substitution> ::= S <seq-id> _
5223// ::= S_
5224// <substitution> ::= Sa # ::std::allocator
5225// <substitution> ::= Sb # ::std::basic_string
5226// <substitution> ::= Ss # ::std::basic_string < char,
5227// ::std::char_traits<char>,
5228// ::std::allocator<char> >
5229// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5230// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5231// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005232// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005233template <typename Derived, typename Alloc>
5234Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005235 if (!consumeIf('S'))
5236 return nullptr;
5237
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005238 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005239 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005240 switch (look()) {
5241 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005242 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005243 break;
5244 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005245 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005246 break;
5247 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005248 Kind = SpecialSubKind::iostream;
5249 break;
5250 case 'i':
5251 Kind = SpecialSubKind::istream;
5252 break;
5253 case 'o':
5254 Kind = SpecialSubKind::ostream;
5255 break;
5256 case 's':
5257 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005258 break;
5259 default:
5260 return nullptr;
5261 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005262 ++First;
5263 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005264 if (!SpecialSub)
5265 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005266
Richard Smithc20d1442018-08-20 20:14:49 +00005267 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5268 // has ABI tags, the tags are appended to the substitution; the result is a
5269 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005270 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005271 if (WithTags != SpecialSub) {
5272 Subs.push_back(WithTags);
5273 SpecialSub = WithTags;
5274 }
5275 return SpecialSub;
5276 }
5277
5278 // ::= S_
5279 if (consumeIf('_')) {
5280 if (Subs.empty())
5281 return nullptr;
5282 return Subs[0];
5283 }
5284
5285 // ::= S <seq-id> _
5286 size_t Index = 0;
5287 if (parseSeqId(&Index))
5288 return nullptr;
5289 ++Index;
5290 if (!consumeIf('_') || Index >= Subs.size())
5291 return nullptr;
5292 return Subs[Index];
5293}
5294
5295// <template-param> ::= T_ # first template parameter
5296// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005297// ::= TL <level-1> __
5298// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005299template <typename Derived, typename Alloc>
5300Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005301 if (!consumeIf('T'))
5302 return nullptr;
5303
Richard Smithdf1c14c2019-09-06 23:53:21 +00005304 size_t Level = 0;
5305 if (consumeIf('L')) {
5306 if (parsePositiveInteger(&Level))
5307 return nullptr;
5308 ++Level;
5309 if (!consumeIf('_'))
5310 return nullptr;
5311 }
5312
Richard Smithc20d1442018-08-20 20:14:49 +00005313 size_t Index = 0;
5314 if (!consumeIf('_')) {
5315 if (parsePositiveInteger(&Index))
5316 return nullptr;
5317 ++Index;
5318 if (!consumeIf('_'))
5319 return nullptr;
5320 }
5321
Richard Smithc20d1442018-08-20 20:14:49 +00005322 // If we're in a context where this <template-param> refers to a
5323 // <template-arg> further ahead in the mangled name (currently just conversion
5324 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005325 // This can only happen at the outermost level.
5326 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005327 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5328 if (!ForwardRef)
5329 return nullptr;
5330 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5331 ForwardTemplateRefs.push_back(
5332 static_cast<ForwardTemplateReference *>(ForwardRef));
5333 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005334 }
5335
Richard Smithdf1c14c2019-09-06 23:53:21 +00005336 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5337 Index >= TemplateParams[Level]->size()) {
5338 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5339 // list are mangled as the corresponding artificial template type parameter.
5340 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5341 // This will be popped by the ScopedTemplateParamList in
5342 // parseUnnamedTypeName.
5343 if (Level == TemplateParams.size())
5344 TemplateParams.push_back(nullptr);
5345 return make<NameType>("auto");
5346 }
5347
Richard Smithc20d1442018-08-20 20:14:49 +00005348 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005349 }
5350
5351 return (*TemplateParams[Level])[Index];
5352}
5353
5354// <template-param-decl> ::= Ty # type parameter
5355// ::= Tn <type> # non-type parameter
5356// ::= Tt <template-param-decl>* E # template parameter
5357// ::= Tp <template-param-decl> # parameter pack
5358template <typename Derived, typename Alloc>
5359Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5360 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5361 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5362 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5363 if (N) TemplateParams.back()->push_back(N);
5364 return N;
5365 };
5366
5367 if (consumeIf("Ty")) {
5368 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5369 if (!Name)
5370 return nullptr;
5371 return make<TypeTemplateParamDecl>(Name);
5372 }
5373
5374 if (consumeIf("Tn")) {
5375 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5376 if (!Name)
5377 return nullptr;
5378 Node *Type = parseType();
5379 if (!Type)
5380 return nullptr;
5381 return make<NonTypeTemplateParamDecl>(Name, Type);
5382 }
5383
5384 if (consumeIf("Tt")) {
5385 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5386 if (!Name)
5387 return nullptr;
5388 size_t ParamsBegin = Names.size();
5389 ScopedTemplateParamList TemplateTemplateParamParams(this);
5390 while (!consumeIf("E")) {
5391 Node *P = parseTemplateParamDecl();
5392 if (!P)
5393 return nullptr;
5394 Names.push_back(P);
5395 }
5396 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5397 return make<TemplateTemplateParamDecl>(Name, Params);
5398 }
5399
5400 if (consumeIf("Tp")) {
5401 Node *P = parseTemplateParamDecl();
5402 if (!P)
5403 return nullptr;
5404 return make<TemplateParamPackDecl>(P);
5405 }
5406
5407 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005408}
5409
5410// <template-arg> ::= <type> # type or template
5411// ::= X <expression> E # expression
5412// ::= <expr-primary> # simple expressions
5413// ::= J <template-arg>* E # argument pack
5414// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005415template <typename Derived, typename Alloc>
5416Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005417 switch (look()) {
5418 case 'X': {
5419 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005420 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005421 if (Arg == nullptr || !consumeIf('E'))
5422 return nullptr;
5423 return Arg;
5424 }
5425 case 'J': {
5426 ++First;
5427 size_t ArgsBegin = Names.size();
5428 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005429 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005430 if (Arg == nullptr)
5431 return nullptr;
5432 Names.push_back(Arg);
5433 }
5434 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5435 return make<TemplateArgumentPack>(Args);
5436 }
5437 case 'L': {
5438 // ::= LZ <encoding> E # extension
5439 if (look(1) == 'Z') {
5440 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005441 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005442 if (Arg == nullptr || !consumeIf('E'))
5443 return nullptr;
5444 return Arg;
5445 }
5446 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005447 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005448 }
5449 default:
Pavel Labathba825192018-10-16 14:29:14 +00005450 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005451 }
5452}
5453
5454// <template-args> ::= I <template-arg>* E
5455// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005456template <typename Derived, typename Alloc>
5457Node *
5458AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005459 if (!consumeIf('I'))
5460 return nullptr;
5461
5462 // <template-params> refer to the innermost <template-args>. Clear out any
5463 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005464 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005465 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005466 TemplateParams.push_back(&OuterTemplateParams);
5467 OuterTemplateParams.clear();
5468 }
Richard Smithc20d1442018-08-20 20:14:49 +00005469
5470 size_t ArgsBegin = Names.size();
5471 while (!consumeIf('E')) {
5472 if (TagTemplates) {
5473 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005474 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005475 TemplateParams = std::move(OldParams);
5476 if (Arg == nullptr)
5477 return nullptr;
5478 Names.push_back(Arg);
5479 Node *TableEntry = Arg;
5480 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5481 TableEntry = make<ParameterPack>(
5482 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005483 if (!TableEntry)
5484 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005485 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005486 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005487 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005488 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005489 if (Arg == nullptr)
5490 return nullptr;
5491 Names.push_back(Arg);
5492 }
5493 }
5494 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5495}
5496
5497// <mangled-name> ::= _Z <encoding>
5498// ::= <type>
5499// extension ::= ___Z <encoding> _block_invoke
5500// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5501// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005502template <typename Derived, typename Alloc>
5503Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005504 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005505 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005506 if (Encoding == nullptr)
5507 return nullptr;
5508 if (look() == '.') {
5509 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5510 First = Last;
5511 }
5512 if (numLeft() != 0)
5513 return nullptr;
5514 return Encoding;
5515 }
5516
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005517 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005518 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005519 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5520 return nullptr;
5521 bool RequireNumber = consumeIf('_');
5522 if (parseNumber().empty() && RequireNumber)
5523 return nullptr;
5524 if (look() == '.')
5525 First = Last;
5526 if (numLeft() != 0)
5527 return nullptr;
5528 return make<SpecialName>("invocation function for block in ", Encoding);
5529 }
5530
Pavel Labathba825192018-10-16 14:29:14 +00005531 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005532 if (numLeft() != 0)
5533 return nullptr;
5534 return Ty;
5535}
5536
Pavel Labathba825192018-10-16 14:29:14 +00005537template <typename Alloc>
5538struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5539 using AbstractManglingParser<ManglingParser<Alloc>,
5540 Alloc>::AbstractManglingParser;
5541};
5542
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005543DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005544
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005545#endif // DEMANGLE_ITANIUMDEMANGLE_H