blob: fa12a0a6d78217825c1029d91fa117c7991844db [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
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000031DEMANGLE_NAMESPACE_BEGIN
32
Mikhail Borisov8452f062021-08-17 18:06:53 -040033template <class T, size_t N> class PODSmallVector {
34 static_assert(std::is_pod<T>::value,
35 "T is required to be a plain old data type");
36
37 T *First = nullptr;
38 T *Last = nullptr;
39 T *Cap = nullptr;
40 T Inline[N] = {0};
41
42 bool isInline() const { return First == Inline; }
43
44 void clearInline() {
45 First = Inline;
46 Last = Inline;
47 Cap = Inline + N;
48 }
49
50 void reserve(size_t NewCap) {
51 size_t S = size();
52 if (isInline()) {
53 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
54 if (Tmp == nullptr)
55 std::terminate();
56 std::copy(First, Last, Tmp);
57 First = Tmp;
58 } else {
59 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
60 if (First == nullptr)
61 std::terminate();
62 }
63 Last = First + S;
64 Cap = First + NewCap;
65 }
66
67public:
68 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
69
70 PODSmallVector(const PODSmallVector &) = delete;
71 PODSmallVector &operator=(const PODSmallVector &) = delete;
72
73 PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {
74 if (Other.isInline()) {
75 std::copy(Other.begin(), Other.end(), First);
76 Last = First + Other.size();
77 Other.clear();
78 return;
79 }
80
81 First = Other.First;
82 Last = Other.Last;
83 Cap = Other.Cap;
84 Other.clearInline();
85 }
86
87 PODSmallVector &operator=(PODSmallVector &&Other) {
88 if (Other.isInline()) {
89 if (!isInline()) {
90 std::free(First);
91 clearInline();
92 }
93 std::copy(Other.begin(), Other.end(), First);
94 Last = First + Other.size();
95 Other.clear();
96 return *this;
97 }
98
99 if (isInline()) {
100 First = Other.First;
101 Last = Other.Last;
102 Cap = Other.Cap;
103 Other.clearInline();
104 return *this;
105 }
106
107 std::swap(First, Other.First);
108 std::swap(Last, Other.Last);
109 std::swap(Cap, Other.Cap);
110 Other.clear();
111 return *this;
112 }
113
114 // NOLINTNEXTLINE(readability-identifier-naming)
115 void push_back(const T &Elem) {
116 if (Last == Cap)
117 reserve(size() * 2);
118 *Last++ = Elem;
119 }
120
121 // NOLINTNEXTLINE(readability-identifier-naming)
122 void pop_back() {
123 assert(Last != First && "Popping empty vector!");
124 --Last;
125 }
126
127 void dropBack(size_t Index) {
128 assert(Index <= size() && "dropBack() can't expand!");
129 Last = First + Index;
130 }
131
132 T *begin() { return First; }
133 T *end() { return Last; }
134
135 bool empty() const { return First == Last; }
136 size_t size() const { return static_cast<size_t>(Last - First); }
137 T &back() {
138 assert(Last != First && "Calling back() on empty vector!");
139 return *(Last - 1);
140 }
141 T &operator[](size_t Index) {
142 assert(Index < size() && "Invalid access!");
143 return *(begin() + Index);
144 }
145 void clear() { Last = First; }
146
147 ~PODSmallVector() {
148 if (!isInline())
149 std::free(First);
150 }
151};
152
Richard Smithc20d1442018-08-20 20:14:49 +0000153// Base class of all AST nodes. The AST is built by the parser, then is
154// traversed by the printLeft/Right functions to produce a demangled string.
155class Node {
156public:
157 enum Kind : unsigned char {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -0700158#define NODE(NodeKind) K##NodeKind,
159#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +0000160 };
161
162 /// Three-way bool to track a cached value. Unknown is possible if this node
163 /// has an unexpanded parameter pack below it that may affect this cache.
164 enum class Cache : unsigned char { Yes, No, Unknown, };
165
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800166 /// Operator precedence for expression nodes. Used to determine required
167 /// parens in expression emission.
168 enum class Prec {
169 Primary,
170 Postfix,
171 Unary,
172 Cast,
173 PtrMem,
174 Multiplicative,
175 Additive,
176 Shift,
177 Spaceship,
178 Relational,
179 Equality,
180 And,
181 Xor,
182 Ior,
183 AndIf,
184 OrIf,
185 Conditional,
186 Assign,
187 Comma,
188 Default,
189 };
190
Richard Smithc20d1442018-08-20 20:14:49 +0000191private:
192 Kind K;
193
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800194 Prec Precedence : 6;
195
Richard Smithc20d1442018-08-20 20:14:49 +0000196 // FIXME: Make these protected.
197public:
198 /// Tracks if this node has a component on its right side, in which case we
199 /// need to call printRight.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800200 Cache RHSComponentCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000201
202 /// Track if this node is a (possibly qualified) array type. This can affect
203 /// how we format the output string.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800204 Cache ArrayCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000205
206 /// Track if this node is a (possibly qualified) function type. This can
207 /// affect how we format the output string.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800208 Cache FunctionCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000209
210public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800211 Node(Kind K_, Prec Precedence_ = Prec::Primary,
212 Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,
213 Cache FunctionCache_ = Cache::No)
214 : K(K_), Precedence(Precedence_), RHSComponentCache(RHSComponentCache_),
215 ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {}
216 Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_ = Cache::No,
217 Cache FunctionCache_ = Cache::No)
218 : Node(K_, Prec::Primary, RHSComponentCache_, ArrayCache_,
219 FunctionCache_) {}
Richard Smithc20d1442018-08-20 20:14:49 +0000220
221 /// Visit the most-derived object corresponding to this object.
222 template<typename Fn> void visit(Fn F) const;
223
224 // The following function is provided by all derived classes:
225 //
226 // Call F with arguments that, when passed to the constructor of this node,
227 // would construct an equivalent node.
228 //template<typename Fn> void match(Fn F) const;
229
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700230 bool hasRHSComponent(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000231 if (RHSComponentCache != Cache::Unknown)
232 return RHSComponentCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700233 return hasRHSComponentSlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000234 }
235
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700236 bool hasArray(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000237 if (ArrayCache != Cache::Unknown)
238 return ArrayCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700239 return hasArraySlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000240 }
241
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700242 bool hasFunction(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000243 if (FunctionCache != Cache::Unknown)
244 return FunctionCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700245 return hasFunctionSlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000246 }
247
248 Kind getKind() const { return K; }
249
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800250 Prec getPrecedence() const { return Precedence; }
251
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700252 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
253 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
254 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
Richard Smithc20d1442018-08-20 20:14:49 +0000255
256 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
257 // get at a node that actually represents some concrete syntax.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700258 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }
Richard Smithc20d1442018-08-20 20:14:49 +0000259
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800260 // Print this node as an expression operand, surrounding it in parentheses if
261 // its precedence is [Strictly] weaker than P.
262 void printAsOperand(OutputBuffer &OB, Prec P = Prec::Default,
263 bool StrictlyWorse = false) const {
264 bool Paren =
265 unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse);
266 if (Paren)
267 OB.printOpen();
268 print(OB);
269 if (Paren)
270 OB.printClose();
271 }
272
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700273 void print(OutputBuffer &OB) const {
274 printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000275 if (RHSComponentCache != Cache::No)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700276 printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000277 }
278
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -0800279 // Print the "left" side of this Node into OutputBuffer.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700280 virtual void printLeft(OutputBuffer &) const = 0;
Richard Smithc20d1442018-08-20 20:14:49 +0000281
282 // Print the "right". This distinction is necessary to represent C++ types
283 // that appear on the RHS of their subtype, such as arrays or functions.
284 // Since most types don't have such a component, provide a default
285 // implementation.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700286 virtual void printRight(OutputBuffer &) const {}
Richard Smithc20d1442018-08-20 20:14:49 +0000287
288 virtual StringView getBaseName() const { return StringView(); }
289
290 // Silence compiler warnings, this dtor will never be called.
291 virtual ~Node() = default;
292
293#ifndef NDEBUG
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000294 DEMANGLE_DUMP_METHOD void dump() const;
Richard Smithc20d1442018-08-20 20:14:49 +0000295#endif
296};
297
298class NodeArray {
299 Node **Elements;
300 size_t NumElements;
301
302public:
303 NodeArray() : Elements(nullptr), NumElements(0) {}
304 NodeArray(Node **Elements_, size_t NumElements_)
305 : Elements(Elements_), NumElements(NumElements_) {}
306
307 bool empty() const { return NumElements == 0; }
308 size_t size() const { return NumElements; }
309
310 Node **begin() const { return Elements; }
311 Node **end() const { return Elements + NumElements; }
312
313 Node *operator[](size_t Idx) const { return Elements[Idx]; }
314
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700315 void printWithComma(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000316 bool FirstElement = true;
317 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700318 size_t BeforeComma = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +0000319 if (!FirstElement)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700320 OB += ", ";
321 size_t AfterComma = OB.getCurrentPosition();
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800322 Elements[Idx]->printAsOperand(OB, Node::Prec::Comma);
Richard Smithc20d1442018-08-20 20:14:49 +0000323
324 // Elements[Idx] is an empty parameter pack expansion, we should erase the
325 // comma we just printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700326 if (AfterComma == OB.getCurrentPosition()) {
327 OB.setCurrentPosition(BeforeComma);
Richard Smithc20d1442018-08-20 20:14:49 +0000328 continue;
329 }
330
331 FirstElement = false;
332 }
333 }
334};
335
336struct NodeArrayNode : Node {
337 NodeArray Array;
338 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
339
340 template<typename Fn> void match(Fn F) const { F(Array); }
341
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700342 void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000343};
344
345class DotSuffix final : public Node {
346 const Node *Prefix;
347 const StringView Suffix;
348
349public:
350 DotSuffix(const Node *Prefix_, StringView Suffix_)
351 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
352
353 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
354
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700355 void printLeft(OutputBuffer &OB) const override {
356 Prefix->print(OB);
357 OB += " (";
358 OB += Suffix;
359 OB += ")";
Richard Smithc20d1442018-08-20 20:14:49 +0000360 }
361};
362
363class VendorExtQualType final : public Node {
364 const Node *Ty;
365 StringView Ext;
Alex Orlovf50df922021-03-24 10:21:32 +0400366 const Node *TA;
Richard Smithc20d1442018-08-20 20:14:49 +0000367
368public:
Alex Orlovf50df922021-03-24 10:21:32 +0400369 VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)
370 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
Richard Smithc20d1442018-08-20 20:14:49 +0000371
Alex Orlovf50df922021-03-24 10:21:32 +0400372 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
Richard Smithc20d1442018-08-20 20:14:49 +0000373
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700374 void printLeft(OutputBuffer &OB) const override {
375 Ty->print(OB);
376 OB += " ";
377 OB += Ext;
Alex Orlovf50df922021-03-24 10:21:32 +0400378 if (TA != nullptr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700379 TA->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000380 }
381};
382
383enum FunctionRefQual : unsigned char {
384 FrefQualNone,
385 FrefQualLValue,
386 FrefQualRValue,
387};
388
389enum Qualifiers {
390 QualNone = 0,
391 QualConst = 0x1,
392 QualVolatile = 0x2,
393 QualRestrict = 0x4,
394};
395
396inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
397 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
398}
399
Richard Smithdf1c14c2019-09-06 23:53:21 +0000400class QualType final : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +0000401protected:
402 const Qualifiers Quals;
403 const Node *Child;
404
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700405 void printQuals(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000406 if (Quals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700407 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000408 if (Quals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700409 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000410 if (Quals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700411 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000412 }
413
414public:
415 QualType(const Node *Child_, Qualifiers Quals_)
416 : Node(KQualType, Child_->RHSComponentCache,
417 Child_->ArrayCache, Child_->FunctionCache),
418 Quals(Quals_), Child(Child_) {}
419
420 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
421
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700422 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
423 return Child->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000424 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700425 bool hasArraySlow(OutputBuffer &OB) const override {
426 return Child->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000427 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700428 bool hasFunctionSlow(OutputBuffer &OB) const override {
429 return Child->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000430 }
431
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700432 void printLeft(OutputBuffer &OB) const override {
433 Child->printLeft(OB);
434 printQuals(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000435 }
436
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700437 void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000438};
439
440class ConversionOperatorType final : public Node {
441 const Node *Ty;
442
443public:
444 ConversionOperatorType(const Node *Ty_)
445 : Node(KConversionOperatorType), Ty(Ty_) {}
446
447 template<typename Fn> void match(Fn F) const { F(Ty); }
448
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700449 void printLeft(OutputBuffer &OB) const override {
450 OB += "operator ";
451 Ty->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000452 }
453};
454
455class PostfixQualifiedType final : public Node {
456 const Node *Ty;
457 const StringView Postfix;
458
459public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -0700460 PostfixQualifiedType(const Node *Ty_, StringView Postfix_)
Richard Smithc20d1442018-08-20 20:14:49 +0000461 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
462
463 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
464
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700465 void printLeft(OutputBuffer &OB) const override {
466 Ty->printLeft(OB);
467 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +0000468 }
469};
470
471class NameType final : public Node {
472 const StringView Name;
473
474public:
475 NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
476
477 template<typename Fn> void match(Fn F) const { F(Name); }
478
479 StringView getName() const { return Name; }
480 StringView getBaseName() const override { return Name; }
481
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700482 void printLeft(OutputBuffer &OB) const override { OB += Name; }
Richard Smithc20d1442018-08-20 20:14:49 +0000483};
484
Senran Zhange025ba52022-03-27 00:04:23 +0800485class BitIntType final : public Node {
486 const Node *Size;
487 bool Signed;
488
489public:
490 BitIntType(const Node *Size_, bool Signed_)
491 : Node(KBitIntType), Size(Size_), Signed(Signed_) {}
492
493 template <typename Fn> void match(Fn F) const { F(Size, Signed); }
494
495 void printLeft(OutputBuffer &OB) const override {
496 if (!Signed)
497 OB += "unsigned ";
498 OB += "_BitInt";
499 OB.printOpen();
500 Size->printAsOperand(OB);
501 OB.printClose();
502 }
503};
504
Richard Smithc20d1442018-08-20 20:14:49 +0000505class ElaboratedTypeSpefType : public Node {
506 StringView Kind;
507 Node *Child;
508public:
509 ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
510 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
511
512 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
513
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700514 void printLeft(OutputBuffer &OB) const override {
515 OB += Kind;
516 OB += ' ';
517 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000518 }
519};
520
521struct AbiTagAttr : Node {
522 Node *Base;
523 StringView Tag;
524
525 AbiTagAttr(Node* Base_, StringView Tag_)
526 : Node(KAbiTagAttr, Base_->RHSComponentCache,
527 Base_->ArrayCache, Base_->FunctionCache),
528 Base(Base_), Tag(Tag_) {}
529
530 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
531
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700532 void printLeft(OutputBuffer &OB) const override {
533 Base->printLeft(OB);
534 OB += "[abi:";
535 OB += Tag;
536 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +0000537 }
538};
539
540class EnableIfAttr : public Node {
541 NodeArray Conditions;
542public:
543 EnableIfAttr(NodeArray Conditions_)
544 : Node(KEnableIfAttr), Conditions(Conditions_) {}
545
546 template<typename Fn> void match(Fn F) const { F(Conditions); }
547
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700548 void printLeft(OutputBuffer &OB) const override {
549 OB += " [enable_if:";
550 Conditions.printWithComma(OB);
551 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +0000552 }
553};
554
555class ObjCProtoName : public Node {
556 const Node *Ty;
557 StringView Protocol;
558
559 friend class PointerType;
560
561public:
562 ObjCProtoName(const Node *Ty_, StringView Protocol_)
563 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
564
565 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
566
567 bool isObjCObject() const {
568 return Ty->getKind() == KNameType &&
569 static_cast<const NameType *>(Ty)->getName() == "objc_object";
570 }
571
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700572 void printLeft(OutputBuffer &OB) const override {
573 Ty->print(OB);
574 OB += "<";
575 OB += Protocol;
576 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +0000577 }
578};
579
580class PointerType final : public Node {
581 const Node *Pointee;
582
583public:
584 PointerType(const Node *Pointee_)
585 : Node(KPointerType, Pointee_->RHSComponentCache),
586 Pointee(Pointee_) {}
587
588 template<typename Fn> void match(Fn F) const { F(Pointee); }
589
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700590 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
591 return Pointee->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000592 }
593
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700594 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000595 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
596 if (Pointee->getKind() != KObjCProtoName ||
597 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700598 Pointee->printLeft(OB);
599 if (Pointee->hasArray(OB))
600 OB += " ";
601 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
602 OB += "(";
603 OB += "*";
Richard Smithc20d1442018-08-20 20:14:49 +0000604 } else {
605 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700606 OB += "id<";
607 OB += objcProto->Protocol;
608 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +0000609 }
610 }
611
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700612 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000613 if (Pointee->getKind() != KObjCProtoName ||
614 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700615 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
616 OB += ")";
617 Pointee->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000618 }
619 }
620};
621
622enum class ReferenceKind {
623 LValue,
624 RValue,
625};
626
627// Represents either a LValue or an RValue reference type.
628class ReferenceType : public Node {
629 const Node *Pointee;
630 ReferenceKind RK;
631
632 mutable bool Printing = false;
633
634 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
635 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
636 // other combination collapses to a lvalue ref.
Mikhail Borisov05f77222021-08-17 18:10:57 -0400637 //
638 // A combination of a TemplateForwardReference and a back-ref Substitution
639 // from an ill-formed string may have created a cycle; use cycle detection to
640 // avoid looping forever.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700641 std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000642 auto SoFar = std::make_pair(RK, Pointee);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400643 // Track the chain of nodes for the Floyd's 'tortoise and hare'
644 // cycle-detection algorithm, since getSyntaxNode(S) is impure
645 PODSmallVector<const Node *, 8> Prev;
Richard Smithc20d1442018-08-20 20:14:49 +0000646 for (;;) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700647 const Node *SN = SoFar.second->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000648 if (SN->getKind() != KReferenceType)
649 break;
650 auto *RT = static_cast<const ReferenceType *>(SN);
651 SoFar.second = RT->Pointee;
652 SoFar.first = std::min(SoFar.first, RT->RK);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400653
654 // The middle of Prev is the 'slow' pointer moving at half speed
655 Prev.push_back(SoFar.second);
656 if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {
657 // Cycle detected
658 SoFar.second = nullptr;
659 break;
660 }
Richard Smithc20d1442018-08-20 20:14:49 +0000661 }
662 return SoFar;
663 }
664
665public:
666 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
667 : Node(KReferenceType, Pointee_->RHSComponentCache),
668 Pointee(Pointee_), RK(RK_) {}
669
670 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
671
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700672 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
673 return Pointee->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000674 }
675
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700676 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000677 if (Printing)
678 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -0800679 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700680 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400681 if (!Collapsed.second)
682 return;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700683 Collapsed.second->printLeft(OB);
684 if (Collapsed.second->hasArray(OB))
685 OB += " ";
686 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
687 OB += "(";
Richard Smithc20d1442018-08-20 20:14:49 +0000688
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700689 OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
Richard Smithc20d1442018-08-20 20:14:49 +0000690 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700691 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000692 if (Printing)
693 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -0800694 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700695 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400696 if (!Collapsed.second)
697 return;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700698 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
699 OB += ")";
700 Collapsed.second->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000701 }
702};
703
704class PointerToMemberType final : public Node {
705 const Node *ClassType;
706 const Node *MemberType;
707
708public:
709 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
710 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
711 ClassType(ClassType_), MemberType(MemberType_) {}
712
713 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
714
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700715 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
716 return MemberType->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000717 }
718
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700719 void printLeft(OutputBuffer &OB) const override {
720 MemberType->printLeft(OB);
721 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
722 OB += "(";
Richard Smithc20d1442018-08-20 20:14:49 +0000723 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700724 OB += " ";
725 ClassType->print(OB);
726 OB += "::*";
Richard Smithc20d1442018-08-20 20:14:49 +0000727 }
728
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700729 void printRight(OutputBuffer &OB) const override {
730 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
731 OB += ")";
732 MemberType->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000733 }
734};
735
Richard Smithc20d1442018-08-20 20:14:49 +0000736class ArrayType final : public Node {
737 const Node *Base;
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800738 Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000739
740public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800741 ArrayType(const Node *Base_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000742 : Node(KArrayType,
743 /*RHSComponentCache=*/Cache::Yes,
744 /*ArrayCache=*/Cache::Yes),
745 Base(Base_), Dimension(Dimension_) {}
746
747 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
748
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700749 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
750 bool hasArraySlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000751
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700752 void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000753
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700754 void printRight(OutputBuffer &OB) const override {
755 if (OB.back() != ']')
756 OB += " ";
757 OB += "[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800758 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700759 Dimension->print(OB);
760 OB += "]";
761 Base->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000762 }
763};
764
765class FunctionType final : public Node {
766 const Node *Ret;
767 NodeArray Params;
768 Qualifiers CVQuals;
769 FunctionRefQual RefQual;
770 const Node *ExceptionSpec;
771
772public:
773 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
774 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
775 : Node(KFunctionType,
776 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
777 /*FunctionCache=*/Cache::Yes),
778 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
779 ExceptionSpec(ExceptionSpec_) {}
780
781 template<typename Fn> void match(Fn F) const {
782 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
783 }
784
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700785 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
786 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000787
788 // Handle C++'s ... quirky decl grammar by using the left & right
789 // distinction. Consider:
790 // int (*f(float))(char) {}
791 // f is a function that takes a float and returns a pointer to a function
792 // that takes a char and returns an int. If we're trying to print f, start
793 // by printing out the return types's left, then print our parameters, then
794 // finally print right of the return type.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700795 void printLeft(OutputBuffer &OB) const override {
796 Ret->printLeft(OB);
797 OB += " ";
Richard Smithc20d1442018-08-20 20:14:49 +0000798 }
799
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700800 void printRight(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800801 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700802 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800803 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700804 Ret->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000805
806 if (CVQuals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700807 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000808 if (CVQuals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700809 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000810 if (CVQuals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700811 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000812
813 if (RefQual == FrefQualLValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700814 OB += " &";
Richard Smithc20d1442018-08-20 20:14:49 +0000815 else if (RefQual == FrefQualRValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700816 OB += " &&";
Richard Smithc20d1442018-08-20 20:14:49 +0000817
818 if (ExceptionSpec != nullptr) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700819 OB += ' ';
820 ExceptionSpec->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000821 }
822 }
823};
824
825class NoexceptSpec : public Node {
826 const Node *E;
827public:
828 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
829
830 template<typename Fn> void match(Fn F) const { F(E); }
831
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700832 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800833 OB += "noexcept";
834 OB.printOpen();
835 E->printAsOperand(OB);
836 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000837 }
838};
839
840class DynamicExceptionSpec : public Node {
841 NodeArray Types;
842public:
843 DynamicExceptionSpec(NodeArray Types_)
844 : Node(KDynamicExceptionSpec), Types(Types_) {}
845
846 template<typename Fn> void match(Fn F) const { F(Types); }
847
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700848 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800849 OB += "throw";
850 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700851 Types.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800852 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000853 }
854};
855
856class FunctionEncoding final : public Node {
857 const Node *Ret;
858 const Node *Name;
859 NodeArray Params;
860 const Node *Attrs;
861 Qualifiers CVQuals;
862 FunctionRefQual RefQual;
863
864public:
865 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
866 const Node *Attrs_, Qualifiers CVQuals_,
867 FunctionRefQual RefQual_)
868 : Node(KFunctionEncoding,
869 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
870 /*FunctionCache=*/Cache::Yes),
871 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
872 CVQuals(CVQuals_), RefQual(RefQual_) {}
873
874 template<typename Fn> void match(Fn F) const {
875 F(Ret, Name, Params, Attrs, CVQuals, RefQual);
876 }
877
878 Qualifiers getCVQuals() const { return CVQuals; }
879 FunctionRefQual getRefQual() const { return RefQual; }
880 NodeArray getParams() const { return Params; }
881 const Node *getReturnType() const { return Ret; }
882
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700883 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
884 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000885
886 const Node *getName() const { return Name; }
887
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700888 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000889 if (Ret) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700890 Ret->printLeft(OB);
891 if (!Ret->hasRHSComponent(OB))
892 OB += " ";
Richard Smithc20d1442018-08-20 20:14:49 +0000893 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700894 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000895 }
896
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700897 void printRight(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800898 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700899 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800900 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000901 if (Ret)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700902 Ret->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000903
904 if (CVQuals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700905 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000906 if (CVQuals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700907 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000908 if (CVQuals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700909 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000910
911 if (RefQual == FrefQualLValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700912 OB += " &";
Richard Smithc20d1442018-08-20 20:14:49 +0000913 else if (RefQual == FrefQualRValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700914 OB += " &&";
Richard Smithc20d1442018-08-20 20:14:49 +0000915
916 if (Attrs != nullptr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700917 Attrs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000918 }
919};
920
921class LiteralOperator : public Node {
922 const Node *OpName;
923
924public:
925 LiteralOperator(const Node *OpName_)
926 : Node(KLiteralOperator), OpName(OpName_) {}
927
928 template<typename Fn> void match(Fn F) const { F(OpName); }
929
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700930 void printLeft(OutputBuffer &OB) const override {
931 OB += "operator\"\" ";
932 OpName->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000933 }
934};
935
936class SpecialName final : public Node {
937 const StringView Special;
938 const Node *Child;
939
940public:
941 SpecialName(StringView Special_, const Node *Child_)
942 : Node(KSpecialName), Special(Special_), Child(Child_) {}
943
944 template<typename Fn> void match(Fn F) const { F(Special, Child); }
945
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700946 void printLeft(OutputBuffer &OB) const override {
947 OB += Special;
948 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000949 }
950};
951
952class CtorVtableSpecialName final : public Node {
953 const Node *FirstType;
954 const Node *SecondType;
955
956public:
957 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
958 : Node(KCtorVtableSpecialName),
959 FirstType(FirstType_), SecondType(SecondType_) {}
960
961 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
962
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700963 void printLeft(OutputBuffer &OB) const override {
964 OB += "construction vtable for ";
965 FirstType->print(OB);
966 OB += "-in-";
967 SecondType->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000968 }
969};
970
971struct NestedName : Node {
972 Node *Qual;
973 Node *Name;
974
975 NestedName(Node *Qual_, Node *Name_)
976 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
977
978 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
979
980 StringView getBaseName() const override { return Name->getBaseName(); }
981
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700982 void printLeft(OutputBuffer &OB) const override {
983 Qual->print(OB);
984 OB += "::";
985 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000986 }
987};
988
Nathan Sidwelledde7bb2022-01-26 07:22:04 -0800989struct ModuleName : Node {
990 ModuleName *Parent;
991 Node *Name;
992 bool IsPartition;
993
994 ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false)
995 : Node(KModuleName), Parent(Parent_), Name(Name_),
996 IsPartition(IsPartition_) {}
997
Nathan Sidwelldafcca22022-03-29 04:43:16 -0700998 template <typename Fn> void match(Fn F) const {
999 F(Parent, Name, IsPartition);
1000 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08001001
1002 void printLeft(OutputBuffer &OB) const override {
1003 if (Parent)
1004 Parent->print(OB);
1005 if (Parent || IsPartition)
1006 OB += IsPartition ? ':' : '.';
1007 Name->print(OB);
1008 }
1009};
1010
1011struct ModuleEntity : Node {
1012 ModuleName *Module;
1013 Node *Name;
1014
1015 ModuleEntity(ModuleName *Module_, Node *Name_)
1016 : Node(KModuleEntity), Module(Module_), Name(Name_) {}
1017
1018 template <typename Fn> void match(Fn F) const { F(Module, Name); }
1019
1020 StringView getBaseName() const override { return Name->getBaseName(); }
1021
1022 void printLeft(OutputBuffer &OB) const override {
1023 Name->print(OB);
1024 OB += '@';
1025 Module->print(OB);
1026 }
1027};
1028
Richard Smithc20d1442018-08-20 20:14:49 +00001029struct LocalName : Node {
1030 Node *Encoding;
1031 Node *Entity;
1032
1033 LocalName(Node *Encoding_, Node *Entity_)
1034 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
1035
1036 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
1037
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001038 void printLeft(OutputBuffer &OB) const override {
1039 Encoding->print(OB);
1040 OB += "::";
1041 Entity->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001042 }
1043};
1044
1045class QualifiedName final : public Node {
1046 // qualifier::name
1047 const Node *Qualifier;
1048 const Node *Name;
1049
1050public:
1051 QualifiedName(const Node *Qualifier_, const Node *Name_)
1052 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
1053
1054 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
1055
1056 StringView getBaseName() const override { return Name->getBaseName(); }
1057
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001058 void printLeft(OutputBuffer &OB) const override {
1059 Qualifier->print(OB);
1060 OB += "::";
1061 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001062 }
1063};
1064
1065class VectorType final : public Node {
1066 const Node *BaseType;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001067 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001068
1069public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001070 VectorType(const Node *BaseType_, const Node *Dimension_)
1071 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001072
1073 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
1074
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001075 void printLeft(OutputBuffer &OB) const override {
1076 BaseType->print(OB);
1077 OB += " vector[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001078 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001079 Dimension->print(OB);
1080 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001081 }
1082};
1083
1084class PixelVectorType final : public Node {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001085 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001086
1087public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001088 PixelVectorType(const Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +00001089 : Node(KPixelVectorType), Dimension(Dimension_) {}
1090
1091 template<typename Fn> void match(Fn F) const { F(Dimension); }
1092
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001093 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001094 // FIXME: This should demangle as "vector pixel".
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001095 OB += "pixel vector[";
1096 Dimension->print(OB);
1097 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001098 }
1099};
1100
Pengfei Wang50e90b82021-09-23 11:02:25 +08001101class BinaryFPType final : public Node {
1102 const Node *Dimension;
1103
1104public:
1105 BinaryFPType(const Node *Dimension_)
1106 : Node(KBinaryFPType), Dimension(Dimension_) {}
1107
1108 template<typename Fn> void match(Fn F) const { F(Dimension); }
1109
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001110 void printLeft(OutputBuffer &OB) const override {
1111 OB += "_Float";
1112 Dimension->print(OB);
Pengfei Wang50e90b82021-09-23 11:02:25 +08001113 }
1114};
1115
Richard Smithdf1c14c2019-09-06 23:53:21 +00001116enum class TemplateParamKind { Type, NonType, Template };
1117
1118/// An invented name for a template parameter for which we don't have a
1119/// corresponding template argument.
1120///
1121/// This node is created when parsing the <lambda-sig> for a lambda with
1122/// explicit template arguments, which might be referenced in the parameter
1123/// types appearing later in the <lambda-sig>.
1124class SyntheticTemplateParamName final : public Node {
1125 TemplateParamKind Kind;
1126 unsigned Index;
1127
1128public:
1129 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
1130 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
1131
1132 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
1133
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001134 void printLeft(OutputBuffer &OB) const override {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001135 switch (Kind) {
1136 case TemplateParamKind::Type:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001137 OB += "$T";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001138 break;
1139 case TemplateParamKind::NonType:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001140 OB += "$N";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001141 break;
1142 case TemplateParamKind::Template:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001143 OB += "$TT";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001144 break;
1145 }
1146 if (Index > 0)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001147 OB << Index - 1;
Richard Smithdf1c14c2019-09-06 23:53:21 +00001148 }
1149};
1150
1151/// A template type parameter declaration, 'typename T'.
1152class TypeTemplateParamDecl final : public Node {
1153 Node *Name;
1154
1155public:
1156 TypeTemplateParamDecl(Node *Name_)
1157 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
1158
1159 template<typename Fn> void match(Fn F) const { F(Name); }
1160
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001161 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001162
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001163 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001164};
1165
1166/// A non-type template parameter declaration, 'int N'.
1167class NonTypeTemplateParamDecl final : public Node {
1168 Node *Name;
1169 Node *Type;
1170
1171public:
1172 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
1173 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
1174
1175 template<typename Fn> void match(Fn F) const { F(Name, Type); }
1176
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001177 void printLeft(OutputBuffer &OB) const override {
1178 Type->printLeft(OB);
1179 if (!Type->hasRHSComponent(OB))
1180 OB += " ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001181 }
1182
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001183 void printRight(OutputBuffer &OB) const override {
1184 Name->print(OB);
1185 Type->printRight(OB);
Richard Smithdf1c14c2019-09-06 23:53:21 +00001186 }
1187};
1188
1189/// A template template parameter declaration,
1190/// 'template<typename T> typename N'.
1191class TemplateTemplateParamDecl final : public Node {
1192 Node *Name;
1193 NodeArray Params;
1194
1195public:
1196 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
1197 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1198 Params(Params_) {}
1199
1200 template<typename Fn> void match(Fn F) const { F(Name, Params); }
1201
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001202 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001203 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001204 OB += "template<";
1205 Params.printWithComma(OB);
1206 OB += "> typename ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001207 }
1208
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001209 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001210};
1211
1212/// A template parameter pack declaration, 'typename ...T'.
1213class TemplateParamPackDecl final : public Node {
1214 Node *Param;
1215
1216public:
1217 TemplateParamPackDecl(Node *Param_)
1218 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1219
1220 template<typename Fn> void match(Fn F) const { F(Param); }
1221
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001222 void printLeft(OutputBuffer &OB) const override {
1223 Param->printLeft(OB);
1224 OB += "...";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001225 }
1226
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001227 void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001228};
1229
Richard Smithc20d1442018-08-20 20:14:49 +00001230/// An unexpanded parameter pack (either in the expression or type context). If
1231/// this AST is correct, this node will have a ParameterPackExpansion node above
1232/// it.
1233///
1234/// This node is created when some <template-args> are found that apply to an
1235/// <encoding>, and is stored in the TemplateParams table. In order for this to
1236/// appear in the final AST, it has to referenced via a <template-param> (ie,
1237/// T_).
1238class ParameterPack final : public Node {
1239 NodeArray Data;
1240
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08001241 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1242 // one.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001243 void initializePackExpansion(OutputBuffer &OB) const {
1244 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1245 OB.CurrentPackMax = static_cast<unsigned>(Data.size());
1246 OB.CurrentPackIndex = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00001247 }
1248 }
1249
1250public:
1251 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1252 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
1253 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1254 return P->ArrayCache == Cache::No;
1255 }))
1256 ArrayCache = Cache::No;
1257 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1258 return P->FunctionCache == Cache::No;
1259 }))
1260 FunctionCache = Cache::No;
1261 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1262 return P->RHSComponentCache == Cache::No;
1263 }))
1264 RHSComponentCache = Cache::No;
1265 }
1266
1267 template<typename Fn> void match(Fn F) const { F(Data); }
1268
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001269 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1270 initializePackExpansion(OB);
1271 size_t Idx = OB.CurrentPackIndex;
1272 return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001273 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001274 bool hasArraySlow(OutputBuffer &OB) const override {
1275 initializePackExpansion(OB);
1276 size_t Idx = OB.CurrentPackIndex;
1277 return Idx < Data.size() && Data[Idx]->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001278 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001279 bool hasFunctionSlow(OutputBuffer &OB) const override {
1280 initializePackExpansion(OB);
1281 size_t Idx = OB.CurrentPackIndex;
1282 return Idx < Data.size() && Data[Idx]->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001283 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001284 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1285 initializePackExpansion(OB);
1286 size_t Idx = OB.CurrentPackIndex;
1287 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;
Richard Smithc20d1442018-08-20 20:14:49 +00001288 }
1289
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001290 void printLeft(OutputBuffer &OB) const override {
1291 initializePackExpansion(OB);
1292 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001293 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001294 Data[Idx]->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001295 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001296 void printRight(OutputBuffer &OB) const override {
1297 initializePackExpansion(OB);
1298 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001299 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001300 Data[Idx]->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001301 }
1302};
1303
1304/// A variadic template argument. This node represents an occurrence of
1305/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1306/// one of it's Elements is. The parser inserts a ParameterPack into the
1307/// TemplateParams table if the <template-args> this pack belongs to apply to an
1308/// <encoding>.
1309class TemplateArgumentPack final : public Node {
1310 NodeArray Elements;
1311public:
1312 TemplateArgumentPack(NodeArray Elements_)
1313 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1314
1315 template<typename Fn> void match(Fn F) const { F(Elements); }
1316
1317 NodeArray getElements() const { return Elements; }
1318
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001319 void printLeft(OutputBuffer &OB) const override {
1320 Elements.printWithComma(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001321 }
1322};
1323
1324/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1325/// which each have Child->ParameterPackSize elements.
1326class ParameterPackExpansion final : public Node {
1327 const Node *Child;
1328
1329public:
1330 ParameterPackExpansion(const Node *Child_)
1331 : Node(KParameterPackExpansion), Child(Child_) {}
1332
1333 template<typename Fn> void match(Fn F) const { F(Child); }
1334
1335 const Node *getChild() const { return Child; }
1336
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001337 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001338 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001339 ScopedOverride<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1340 ScopedOverride<unsigned> SavePackMax(OB.CurrentPackMax, Max);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001341 size_t StreamPos = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +00001342
1343 // Print the first element in the pack. If Child contains a ParameterPack,
1344 // it will set up S.CurrentPackMax and print the first element.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001345 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001346
1347 // No ParameterPack was found in Child. This can occur if we've found a pack
1348 // expansion on a <function-param>.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001349 if (OB.CurrentPackMax == Max) {
1350 OB += "...";
Richard Smithc20d1442018-08-20 20:14:49 +00001351 return;
1352 }
1353
1354 // We found a ParameterPack, but it has no elements. Erase whatever we may
1355 // of printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001356 if (OB.CurrentPackMax == 0) {
1357 OB.setCurrentPosition(StreamPos);
Richard Smithc20d1442018-08-20 20:14:49 +00001358 return;
1359 }
1360
1361 // Else, iterate through the rest of the elements in the pack.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001362 for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {
1363 OB += ", ";
1364 OB.CurrentPackIndex = I;
1365 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001366 }
1367 }
1368};
1369
1370class TemplateArgs final : public Node {
1371 NodeArray Params;
1372
1373public:
1374 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1375
1376 template<typename Fn> void match(Fn F) const { F(Params); }
1377
1378 NodeArray getParams() { return Params; }
1379
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001380 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001381 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001382 OB += "<";
1383 Params.printWithComma(OB);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001384 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +00001385 }
1386};
1387
Richard Smithb485b352018-08-24 23:30:26 +00001388/// A forward-reference to a template argument that was not known at the point
1389/// where the template parameter name was parsed in a mangling.
1390///
1391/// This is created when demangling the name of a specialization of a
1392/// conversion function template:
1393///
1394/// \code
1395/// struct A {
1396/// template<typename T> operator T*();
1397/// };
1398/// \endcode
1399///
1400/// When demangling a specialization of the conversion function template, we
1401/// encounter the name of the template (including the \c T) before we reach
1402/// the template argument list, so we cannot substitute the parameter name
1403/// for the corresponding argument while parsing. Instead, we create a
1404/// \c ForwardTemplateReference node that is resolved after we parse the
1405/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001406struct ForwardTemplateReference : Node {
1407 size_t Index;
1408 Node *Ref = nullptr;
1409
1410 // If we're currently printing this node. It is possible (though invalid) for
1411 // a forward template reference to refer to itself via a substitution. This
1412 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1413 // out if more than one print* function is active.
1414 mutable bool Printing = false;
1415
1416 ForwardTemplateReference(size_t Index_)
1417 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1418 Cache::Unknown),
1419 Index(Index_) {}
1420
1421 // We don't provide a matcher for these, because the value of the node is
1422 // not determined by its construction parameters, and it generally needs
1423 // special handling.
1424 template<typename Fn> void match(Fn F) const = delete;
1425
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001426 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001427 if (Printing)
1428 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001429 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001430 return Ref->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001431 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001432 bool hasArraySlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001433 if (Printing)
1434 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001435 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001436 return Ref->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001437 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001438 bool hasFunctionSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001439 if (Printing)
1440 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001441 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001442 return Ref->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001443 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001444 const Node *getSyntaxNode(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001445 if (Printing)
1446 return this;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001447 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001448 return Ref->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001449 }
1450
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001451 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001452 if (Printing)
1453 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001454 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001455 Ref->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001456 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001457 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001458 if (Printing)
1459 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001460 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001461 Ref->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001462 }
1463};
1464
1465struct NameWithTemplateArgs : Node {
1466 // name<template_args>
1467 Node *Name;
1468 Node *TemplateArgs;
1469
1470 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1471 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1472
1473 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1474
1475 StringView getBaseName() const override { return Name->getBaseName(); }
1476
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001477 void printLeft(OutputBuffer &OB) const override {
1478 Name->print(OB);
1479 TemplateArgs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001480 }
1481};
1482
1483class GlobalQualifiedName final : public Node {
1484 Node *Child;
1485
1486public:
1487 GlobalQualifiedName(Node* Child_)
1488 : Node(KGlobalQualifiedName), Child(Child_) {}
1489
1490 template<typename Fn> void match(Fn F) const { F(Child); }
1491
1492 StringView getBaseName() const override { return Child->getBaseName(); }
1493
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001494 void printLeft(OutputBuffer &OB) const override {
1495 OB += "::";
1496 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001497 }
1498};
1499
Richard Smithc20d1442018-08-20 20:14:49 +00001500enum class SpecialSubKind {
1501 allocator,
1502 basic_string,
1503 string,
1504 istream,
1505 ostream,
1506 iostream,
1507};
1508
1509class ExpandedSpecialSubstitution final : public Node {
1510 SpecialSubKind SSK;
1511
1512public:
1513 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1514 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1515
1516 template<typename Fn> void match(Fn F) const { F(SSK); }
1517
1518 StringView getBaseName() const override {
1519 switch (SSK) {
1520 case SpecialSubKind::allocator:
1521 return StringView("allocator");
1522 case SpecialSubKind::basic_string:
1523 return StringView("basic_string");
1524 case SpecialSubKind::string:
1525 return StringView("basic_string");
1526 case SpecialSubKind::istream:
1527 return StringView("basic_istream");
1528 case SpecialSubKind::ostream:
1529 return StringView("basic_ostream");
1530 case SpecialSubKind::iostream:
1531 return StringView("basic_iostream");
1532 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001533 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001534 }
1535
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001536 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001537 switch (SSK) {
1538 case SpecialSubKind::allocator:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001539 OB += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001540 break;
1541 case SpecialSubKind::basic_string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001542 OB += "std::basic_string";
Richard Smithb485b352018-08-24 23:30:26 +00001543 break;
Richard Smithc20d1442018-08-20 20:14:49 +00001544 case SpecialSubKind::string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001545 OB += "std::basic_string<char, std::char_traits<char>, "
Nathan Sidwell558c0f02022-03-28 12:38:24 -07001546 "std::allocator<char>>";
Richard Smithc20d1442018-08-20 20:14:49 +00001547 break;
1548 case SpecialSubKind::istream:
Nathan Sidwell558c0f02022-03-28 12:38:24 -07001549 OB += "std::basic_istream<char, std::char_traits<char>>";
Richard Smithc20d1442018-08-20 20:14:49 +00001550 break;
1551 case SpecialSubKind::ostream:
Nathan Sidwell558c0f02022-03-28 12:38:24 -07001552 OB += "std::basic_ostream<char, std::char_traits<char>>";
Richard Smithc20d1442018-08-20 20:14:49 +00001553 break;
1554 case SpecialSubKind::iostream:
Nathan Sidwell558c0f02022-03-28 12:38:24 -07001555 OB += "std::basic_iostream<char, std::char_traits<char>>";
Richard Smithc20d1442018-08-20 20:14:49 +00001556 break;
1557 }
1558 }
1559};
1560
1561class SpecialSubstitution final : public Node {
1562public:
1563 SpecialSubKind SSK;
1564
1565 SpecialSubstitution(SpecialSubKind SSK_)
1566 : Node(KSpecialSubstitution), SSK(SSK_) {}
1567
1568 template<typename Fn> void match(Fn F) const { F(SSK); }
1569
1570 StringView getBaseName() const override {
1571 switch (SSK) {
1572 case SpecialSubKind::allocator:
1573 return StringView("allocator");
1574 case SpecialSubKind::basic_string:
1575 return StringView("basic_string");
1576 case SpecialSubKind::string:
1577 return StringView("string");
1578 case SpecialSubKind::istream:
1579 return StringView("istream");
1580 case SpecialSubKind::ostream:
1581 return StringView("ostream");
1582 case SpecialSubKind::iostream:
1583 return StringView("iostream");
1584 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001585 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001586 }
1587
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001588 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001589 switch (SSK) {
1590 case SpecialSubKind::allocator:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001591 OB += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001592 break;
1593 case SpecialSubKind::basic_string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001594 OB += "std::basic_string";
Richard Smithc20d1442018-08-20 20:14:49 +00001595 break;
1596 case SpecialSubKind::string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001597 OB += "std::string";
Richard Smithc20d1442018-08-20 20:14:49 +00001598 break;
1599 case SpecialSubKind::istream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001600 OB += "std::istream";
Richard Smithc20d1442018-08-20 20:14:49 +00001601 break;
1602 case SpecialSubKind::ostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001603 OB += "std::ostream";
Richard Smithc20d1442018-08-20 20:14:49 +00001604 break;
1605 case SpecialSubKind::iostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001606 OB += "std::iostream";
Richard Smithc20d1442018-08-20 20:14:49 +00001607 break;
1608 }
1609 }
1610};
1611
1612class CtorDtorName final : public Node {
1613 const Node *Basename;
1614 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001615 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001616
1617public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001618 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1619 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1620 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001621
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001622 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001623
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001624 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001625 if (IsDtor)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001626 OB += "~";
1627 OB += Basename->getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001628 }
1629};
1630
1631class DtorName : public Node {
1632 const Node *Base;
1633
1634public:
1635 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1636
1637 template<typename Fn> void match(Fn F) const { F(Base); }
1638
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001639 void printLeft(OutputBuffer &OB) const override {
1640 OB += "~";
1641 Base->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001642 }
1643};
1644
1645class UnnamedTypeName : public Node {
1646 const StringView Count;
1647
1648public:
1649 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1650
1651 template<typename Fn> void match(Fn F) const { F(Count); }
1652
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001653 void printLeft(OutputBuffer &OB) const override {
1654 OB += "'unnamed";
1655 OB += Count;
1656 OB += "\'";
Richard Smithc20d1442018-08-20 20:14:49 +00001657 }
1658};
1659
1660class ClosureTypeName : public Node {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001661 NodeArray TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00001662 NodeArray Params;
1663 StringView Count;
1664
1665public:
Richard Smithdf1c14c2019-09-06 23:53:21 +00001666 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1667 StringView Count_)
1668 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1669 Params(Params_), Count(Count_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001670
Richard Smithdf1c14c2019-09-06 23:53:21 +00001671 template<typename Fn> void match(Fn F) const {
1672 F(TemplateParams, Params, Count);
1673 }
1674
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001675 void printDeclarator(OutputBuffer &OB) const {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001676 if (!TemplateParams.empty()) {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001677 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001678 OB += "<";
1679 TemplateParams.printWithComma(OB);
1680 OB += ">";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001681 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001682 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001683 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001684 OB.printClose();
Richard Smithdf1c14c2019-09-06 23:53:21 +00001685 }
Richard Smithc20d1442018-08-20 20:14:49 +00001686
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001687 void printLeft(OutputBuffer &OB) const override {
1688 OB += "\'lambda";
1689 OB += Count;
1690 OB += "\'";
1691 printDeclarator(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001692 }
1693};
1694
1695class StructuredBindingName : public Node {
1696 NodeArray Bindings;
1697public:
1698 StructuredBindingName(NodeArray Bindings_)
1699 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1700
1701 template<typename Fn> void match(Fn F) const { F(Bindings); }
1702
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001703 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001704 OB.printOpen('[');
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001705 Bindings.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001706 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001707 }
1708};
1709
1710// -- Expression Nodes --
1711
1712class BinaryExpr : public Node {
1713 const Node *LHS;
1714 const StringView InfixOperator;
1715 const Node *RHS;
1716
1717public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001718 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
1719 Prec Prec_)
1720 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
1721 RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001722
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001723 template <typename Fn> void match(Fn F) const {
1724 F(LHS, InfixOperator, RHS, getPrecedence());
1725 }
Richard Smithc20d1442018-08-20 20:14:49 +00001726
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001727 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell18505102022-03-25 04:34:19 -07001728 bool ParenAll = OB.isGtInsideTemplateArgs() &&
1729 (InfixOperator == ">" || InfixOperator == ">>");
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001730 if (ParenAll)
1731 OB.printOpen();
1732 // Assignment is right associative, with special LHS precedence.
1733 bool IsAssign = getPrecedence() == Prec::Assign;
1734 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1735 // No space before comma operator
1736 if (!(InfixOperator == ","))
1737 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001738 OB += InfixOperator;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001739 OB += " ";
1740 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1741 if (ParenAll)
1742 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001743 }
1744};
1745
1746class ArraySubscriptExpr : public Node {
1747 const Node *Op1;
1748 const Node *Op2;
1749
1750public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001751 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1752 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001753
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001754 template <typename Fn> void match(Fn F) const {
1755 F(Op1, Op2, getPrecedence());
1756 }
Richard Smithc20d1442018-08-20 20:14:49 +00001757
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001758 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001759 Op1->printAsOperand(OB, getPrecedence());
1760 OB.printOpen('[');
1761 Op2->printAsOperand(OB);
1762 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001763 }
1764};
1765
1766class PostfixExpr : public Node {
1767 const Node *Child;
1768 const StringView Operator;
1769
1770public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001771 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
1772 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001773
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001774 template <typename Fn> void match(Fn F) const {
1775 F(Child, Operator, getPrecedence());
1776 }
Richard Smithc20d1442018-08-20 20:14:49 +00001777
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001778 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001779 Child->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001780 OB += Operator;
Richard Smithc20d1442018-08-20 20:14:49 +00001781 }
1782};
1783
1784class ConditionalExpr : public Node {
1785 const Node *Cond;
1786 const Node *Then;
1787 const Node *Else;
1788
1789public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001790 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1791 Prec Prec_)
1792 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001793
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001794 template <typename Fn> void match(Fn F) const {
1795 F(Cond, Then, Else, getPrecedence());
1796 }
Richard Smithc20d1442018-08-20 20:14:49 +00001797
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001798 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001799 Cond->printAsOperand(OB, getPrecedence());
1800 OB += " ? ";
1801 Then->printAsOperand(OB);
1802 OB += " : ";
1803 Else->printAsOperand(OB, Prec::Assign, true);
Richard Smithc20d1442018-08-20 20:14:49 +00001804 }
1805};
1806
1807class MemberExpr : public Node {
1808 const Node *LHS;
1809 const StringView Kind;
1810 const Node *RHS;
1811
1812public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001813 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
1814 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001815
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001816 template <typename Fn> void match(Fn F) const {
1817 F(LHS, Kind, RHS, getPrecedence());
1818 }
Richard Smithc20d1442018-08-20 20:14:49 +00001819
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001820 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001821 LHS->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001822 OB += Kind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001823 RHS->printAsOperand(OB, getPrecedence(), false);
Richard Smithc20d1442018-08-20 20:14:49 +00001824 }
1825};
1826
Richard Smith1865d2f2020-10-22 19:29:36 -07001827class SubobjectExpr : public Node {
1828 const Node *Type;
1829 const Node *SubExpr;
1830 StringView Offset;
1831 NodeArray UnionSelectors;
1832 bool OnePastTheEnd;
1833
1834public:
1835 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1836 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1837 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1838 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1839
1840 template<typename Fn> void match(Fn F) const {
1841 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1842 }
1843
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001844 void printLeft(OutputBuffer &OB) const override {
1845 SubExpr->print(OB);
1846 OB += ".<";
1847 Type->print(OB);
1848 OB += " at offset ";
Richard Smith1865d2f2020-10-22 19:29:36 -07001849 if (Offset.empty()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001850 OB += "0";
Richard Smith1865d2f2020-10-22 19:29:36 -07001851 } else if (Offset[0] == 'n') {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001852 OB += "-";
1853 OB += Offset.dropFront();
Richard Smith1865d2f2020-10-22 19:29:36 -07001854 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001855 OB += Offset;
Richard Smith1865d2f2020-10-22 19:29:36 -07001856 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001857 OB += ">";
Richard Smith1865d2f2020-10-22 19:29:36 -07001858 }
1859};
1860
Richard Smithc20d1442018-08-20 20:14:49 +00001861class EnclosingExpr : public Node {
1862 const StringView Prefix;
1863 const Node *Infix;
1864 const StringView Postfix;
1865
1866public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001867 EnclosingExpr(StringView Prefix_, const Node *Infix_,
1868 Prec Prec_ = Prec::Primary)
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001869 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001870
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001871 template <typename Fn> void match(Fn F) const {
1872 F(Prefix, Infix, getPrecedence());
1873 }
Richard Smithc20d1442018-08-20 20:14:49 +00001874
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001875 void printLeft(OutputBuffer &OB) const override {
1876 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001877 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001878 Infix->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001879 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001880 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +00001881 }
1882};
1883
1884class CastExpr : public Node {
1885 // cast_kind<to>(from)
1886 const StringView CastKind;
1887 const Node *To;
1888 const Node *From;
1889
1890public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001891 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
1892 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001893
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001894 template <typename Fn> void match(Fn F) const {
1895 F(CastKind, To, From, getPrecedence());
1896 }
Richard Smithc20d1442018-08-20 20:14:49 +00001897
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001898 void printLeft(OutputBuffer &OB) const override {
1899 OB += CastKind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001900 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001901 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001902 OB += "<";
1903 To->printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001904 OB += ">";
1905 }
1906 OB.printOpen();
1907 From->printAsOperand(OB);
1908 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001909 }
1910};
1911
1912class SizeofParamPackExpr : public Node {
1913 const Node *Pack;
1914
1915public:
1916 SizeofParamPackExpr(const Node *Pack_)
1917 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1918
1919 template<typename Fn> void match(Fn F) const { F(Pack); }
1920
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001921 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001922 OB += "sizeof...";
1923 OB.printOpen();
Richard Smithc20d1442018-08-20 20:14:49 +00001924 ParameterPackExpansion PPE(Pack);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001925 PPE.printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001926 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001927 }
1928};
1929
1930class CallExpr : public Node {
1931 const Node *Callee;
1932 NodeArray Args;
1933
1934public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001935 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
1936 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001937
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001938 template <typename Fn> void match(Fn F) const {
1939 F(Callee, Args, getPrecedence());
1940 }
Richard Smithc20d1442018-08-20 20:14:49 +00001941
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001942 void printLeft(OutputBuffer &OB) const override {
1943 Callee->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001944 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001945 Args.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001946 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001947 }
1948};
1949
1950class NewExpr : public Node {
1951 // new (expr_list) type(init_list)
1952 NodeArray ExprList;
1953 Node *Type;
1954 NodeArray InitList;
1955 bool IsGlobal; // ::operator new ?
1956 bool IsArray; // new[] ?
1957public:
1958 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001959 bool IsArray_, Prec Prec_)
1960 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
1961 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001962
1963 template<typename Fn> void match(Fn F) const {
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001964 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00001965 }
1966
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001967 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001968 if (IsGlobal)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001969 OB += "::";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001970 OB += "new";
Richard Smithc20d1442018-08-20 20:14:49 +00001971 if (IsArray)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001972 OB += "[]";
Richard Smithc20d1442018-08-20 20:14:49 +00001973 if (!ExprList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001974 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001975 ExprList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001976 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001977 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001978 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001979 Type->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001980 if (!InitList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001981 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001982 InitList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001983 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001984 }
Richard Smithc20d1442018-08-20 20:14:49 +00001985 }
1986};
1987
1988class DeleteExpr : public Node {
1989 Node *Op;
1990 bool IsGlobal;
1991 bool IsArray;
1992
1993public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001994 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
1995 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
1996 IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001997
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001998 template <typename Fn> void match(Fn F) const {
1999 F(Op, IsGlobal, IsArray, getPrecedence());
2000 }
Richard Smithc20d1442018-08-20 20:14:49 +00002001
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002002 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002003 if (IsGlobal)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002004 OB += "::";
2005 OB += "delete";
Richard Smithc20d1442018-08-20 20:14:49 +00002006 if (IsArray)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08002007 OB += "[]";
2008 OB += ' ';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002009 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002010 }
2011};
2012
2013class PrefixExpr : public Node {
2014 StringView Prefix;
2015 Node *Child;
2016
2017public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002018 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
2019 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002020
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002021 template <typename Fn> void match(Fn F) const {
2022 F(Prefix, Child, getPrecedence());
2023 }
Richard Smithc20d1442018-08-20 20:14:49 +00002024
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002025 void printLeft(OutputBuffer &OB) const override {
2026 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002027 Child->printAsOperand(OB, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00002028 }
2029};
2030
2031class FunctionParam : public Node {
2032 StringView Number;
2033
2034public:
2035 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
2036
2037 template<typename Fn> void match(Fn F) const { F(Number); }
2038
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002039 void printLeft(OutputBuffer &OB) const override {
2040 OB += "fp";
2041 OB += Number;
Richard Smithc20d1442018-08-20 20:14:49 +00002042 }
2043};
2044
2045class ConversionExpr : public Node {
2046 const Node *Type;
2047 NodeArray Expressions;
2048
2049public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002050 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2051 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002052
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002053 template <typename Fn> void match(Fn F) const {
2054 F(Type, Expressions, getPrecedence());
2055 }
Richard Smithc20d1442018-08-20 20:14:49 +00002056
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002057 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002058 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002059 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002060 OB.printClose();
2061 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002062 Expressions.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002063 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002064 }
2065};
2066
Richard Smith1865d2f2020-10-22 19:29:36 -07002067class PointerToMemberConversionExpr : public Node {
2068 const Node *Type;
2069 const Node *SubExpr;
2070 StringView Offset;
2071
2072public:
2073 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002074 StringView Offset_, Prec Prec_)
2075 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2076 SubExpr(SubExpr_), Offset(Offset_) {}
Richard Smith1865d2f2020-10-22 19:29:36 -07002077
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002078 template <typename Fn> void match(Fn F) const {
2079 F(Type, SubExpr, Offset, getPrecedence());
2080 }
Richard Smith1865d2f2020-10-22 19:29:36 -07002081
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002082 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002083 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002084 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002085 OB.printClose();
2086 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002087 SubExpr->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002088 OB.printClose();
Richard Smith1865d2f2020-10-22 19:29:36 -07002089 }
2090};
2091
Richard Smithc20d1442018-08-20 20:14:49 +00002092class InitListExpr : public Node {
2093 const Node *Ty;
2094 NodeArray Inits;
2095public:
2096 InitListExpr(const Node *Ty_, NodeArray Inits_)
2097 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2098
2099 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2100
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002101 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002102 if (Ty)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002103 Ty->print(OB);
2104 OB += '{';
2105 Inits.printWithComma(OB);
2106 OB += '}';
Richard Smithc20d1442018-08-20 20:14:49 +00002107 }
2108};
2109
2110class BracedExpr : public Node {
2111 const Node *Elem;
2112 const Node *Init;
2113 bool IsArray;
2114public:
2115 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2116 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2117
2118 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
2119
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002120 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002121 if (IsArray) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002122 OB += '[';
2123 Elem->print(OB);
2124 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002125 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002126 OB += '.';
2127 Elem->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002128 }
2129 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002130 OB += " = ";
2131 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002132 }
2133};
2134
2135class BracedRangeExpr : public Node {
2136 const Node *First;
2137 const Node *Last;
2138 const Node *Init;
2139public:
2140 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2141 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2142
2143 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2144
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002145 void printLeft(OutputBuffer &OB) const override {
2146 OB += '[';
2147 First->print(OB);
2148 OB += " ... ";
2149 Last->print(OB);
2150 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002151 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002152 OB += " = ";
2153 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002154 }
2155};
2156
2157class FoldExpr : public Node {
2158 const Node *Pack, *Init;
2159 StringView OperatorName;
2160 bool IsLeftFold;
2161
2162public:
2163 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
2164 const Node *Init_)
2165 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2166 IsLeftFold(IsLeftFold_) {}
2167
2168 template<typename Fn> void match(Fn F) const {
2169 F(IsLeftFold, OperatorName, Pack, Init);
2170 }
2171
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002172 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002173 auto PrintPack = [&] {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002174 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002175 ParameterPackExpansion(Pack).print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002176 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002177 };
2178
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002179 OB.printOpen();
2180 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2181 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2182 // Fold expr operands are cast-expressions
2183 if (!IsLeftFold || Init != nullptr) {
2184 // '(init|pack) op '
2185 if (IsLeftFold)
2186 Init->printAsOperand(OB, Prec::Cast, true);
2187 else
2188 PrintPack();
2189 OB << " " << OperatorName << " ";
Richard Smithc20d1442018-08-20 20:14:49 +00002190 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002191 OB << "...";
2192 if (IsLeftFold || Init != nullptr) {
2193 // ' op (init|pack)'
2194 OB << " " << OperatorName << " ";
2195 if (IsLeftFold)
2196 PrintPack();
2197 else
2198 Init->printAsOperand(OB, Prec::Cast, true);
2199 }
2200 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002201 }
2202};
2203
2204class ThrowExpr : public Node {
2205 const Node *Op;
2206
2207public:
2208 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2209
2210 template<typename Fn> void match(Fn F) const { F(Op); }
2211
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002212 void printLeft(OutputBuffer &OB) const override {
2213 OB += "throw ";
2214 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002215 }
2216};
2217
2218class BoolExpr : public Node {
2219 bool Value;
2220
2221public:
2222 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2223
2224 template<typename Fn> void match(Fn F) const { F(Value); }
2225
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002226 void printLeft(OutputBuffer &OB) const override {
2227 OB += Value ? StringView("true") : StringView("false");
Richard Smithc20d1442018-08-20 20:14:49 +00002228 }
2229};
2230
Richard Smithdf1c14c2019-09-06 23:53:21 +00002231class StringLiteral : public Node {
2232 const Node *Type;
2233
2234public:
2235 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2236
2237 template<typename Fn> void match(Fn F) const { F(Type); }
2238
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002239 void printLeft(OutputBuffer &OB) const override {
2240 OB += "\"<";
2241 Type->print(OB);
2242 OB += ">\"";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002243 }
2244};
2245
2246class LambdaExpr : public Node {
2247 const Node *Type;
2248
Richard Smithdf1c14c2019-09-06 23:53:21 +00002249public:
2250 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2251
2252 template<typename Fn> void match(Fn F) const { F(Type); }
2253
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002254 void printLeft(OutputBuffer &OB) const override {
2255 OB += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002256 if (Type->getKind() == KClosureTypeName)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002257 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2258 OB += "{...}";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002259 }
2260};
2261
Erik Pilkington0a170f12020-05-13 14:13:37 -04002262class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002263 // ty(integer)
2264 const Node *Ty;
2265 StringView Integer;
2266
2267public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002268 EnumLiteral(const Node *Ty_, StringView Integer_)
2269 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002270
2271 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2272
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002273 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002274 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002275 Ty->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002276 OB.printClose();
Erik Pilkington0a170f12020-05-13 14:13:37 -04002277
2278 if (Integer[0] == 'n')
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002279 OB << "-" << Integer.dropFront(1);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002280 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002281 OB << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002282 }
2283};
2284
2285class IntegerLiteral : public Node {
2286 StringView Type;
2287 StringView Value;
2288
2289public:
2290 IntegerLiteral(StringView Type_, StringView Value_)
2291 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2292
2293 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2294
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002295 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002296 if (Type.size() > 3) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002297 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002298 OB += Type;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002299 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002300 }
2301
2302 if (Value[0] == 'n') {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002303 OB += '-';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002304 OB += Value.dropFront(1);
Richard Smithc20d1442018-08-20 20:14:49 +00002305 } else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002306 OB += Value;
Richard Smithc20d1442018-08-20 20:14:49 +00002307
2308 if (Type.size() <= 3)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002309 OB += Type;
Richard Smithc20d1442018-08-20 20:14:49 +00002310 }
2311};
2312
2313template <class Float> struct FloatData;
2314
2315namespace float_literal_impl {
2316constexpr Node::Kind getFloatLiteralKind(float *) {
2317 return Node::KFloatLiteral;
2318}
2319constexpr Node::Kind getFloatLiteralKind(double *) {
2320 return Node::KDoubleLiteral;
2321}
2322constexpr Node::Kind getFloatLiteralKind(long double *) {
2323 return Node::KLongDoubleLiteral;
2324}
2325}
2326
2327template <class Float> class FloatLiteralImpl : public Node {
2328 const StringView Contents;
2329
2330 static constexpr Kind KindForClass =
2331 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2332
2333public:
2334 FloatLiteralImpl(StringView Contents_)
2335 : Node(KindForClass), Contents(Contents_) {}
2336
2337 template<typename Fn> void match(Fn F) const { F(Contents); }
2338
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002339 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002340 const char *first = Contents.begin();
2341 const char *last = Contents.end() + 1;
2342
2343 const size_t N = FloatData<Float>::mangled_size;
2344 if (static_cast<std::size_t>(last - first) > N) {
2345 last = first + N;
2346 union {
2347 Float value;
2348 char buf[sizeof(Float)];
2349 };
2350 const char *t = first;
2351 char *e = buf;
2352 for (; t != last; ++t, ++e) {
2353 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2354 : static_cast<unsigned>(*t - 'a' + 10);
2355 ++t;
2356 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2357 : static_cast<unsigned>(*t - 'a' + 10);
2358 *e = static_cast<char>((d1 << 4) + d0);
2359 }
2360#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2361 std::reverse(buf, e);
2362#endif
2363 char num[FloatData<Float>::max_demangled_size] = {0};
2364 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002365 OB += StringView(num, num + n);
Richard Smithc20d1442018-08-20 20:14:49 +00002366 }
2367 }
2368};
2369
2370using FloatLiteral = FloatLiteralImpl<float>;
2371using DoubleLiteral = FloatLiteralImpl<double>;
2372using LongDoubleLiteral = FloatLiteralImpl<long double>;
2373
2374/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2375/// appropriate derived class.
2376template<typename Fn>
2377void Node::visit(Fn F) const {
2378 switch (K) {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002379#define NODE(X) \
2380 case K##X: \
2381 return F(static_cast<const X *>(this));
2382#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002383 }
2384 assert(0 && "unknown mangling node kind");
2385}
2386
2387/// Determine the kind of a node from its type.
2388template<typename NodeT> struct NodeKind;
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002389#define NODE(X) \
2390 template <> struct NodeKind<X> { \
2391 static constexpr Node::Kind Kind = Node::K##X; \
2392 static constexpr const char *name() { return #X; } \
Richard Smithc20d1442018-08-20 20:14:49 +00002393 };
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002394#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002395
Pavel Labathba825192018-10-16 14:29:14 +00002396template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002397 const char *First;
2398 const char *Last;
2399
2400 // Name stack, this is used by the parser to hold temporary names that were
2401 // parsed. The parser collapses multiple names into new nodes to construct
2402 // the AST. Once the parser is finished, names.size() == 1.
2403 PODSmallVector<Node *, 32> Names;
2404
2405 // Substitution table. Itanium supports name substitutions as a means of
2406 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2407 // table.
2408 PODSmallVector<Node *, 32> Subs;
2409
Richard Smithdf1c14c2019-09-06 23:53:21 +00002410 using TemplateParamList = PODSmallVector<Node *, 8>;
2411
2412 class ScopedTemplateParamList {
2413 AbstractManglingParser *Parser;
2414 size_t OldNumTemplateParamLists;
2415 TemplateParamList Params;
2416
2417 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002418 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2419 : Parser(TheParser),
2420 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002421 Parser->TemplateParams.push_back(&Params);
2422 }
2423 ~ScopedTemplateParamList() {
2424 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2425 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2426 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002427 };
2428
Richard Smithc20d1442018-08-20 20:14:49 +00002429 // Template parameter table. Like the above, but referenced like "T42_".
2430 // This has a smaller size compared to Subs and Names because it can be
2431 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002432 TemplateParamList OuterTemplateParams;
2433
2434 // Lists of template parameters indexed by template parameter depth,
2435 // referenced like "TL2_4_". If nonempty, element 0 is always
2436 // OuterTemplateParams; inner elements are always template parameter lists of
2437 // lambda expressions. For a generic lambda with no explicit template
2438 // parameter list, the corresponding parameter list pointer will be null.
2439 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002440
2441 // Set of unresolved forward <template-param> references. These can occur in a
2442 // conversion operator's type, and are resolved in the enclosing <encoding>.
2443 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2444
Richard Smithc20d1442018-08-20 20:14:49 +00002445 bool TryToParseTemplateArgs = true;
2446 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002447 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2448
2449 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002450
2451 Alloc ASTAllocator;
2452
Pavel Labathba825192018-10-16 14:29:14 +00002453 AbstractManglingParser(const char *First_, const char *Last_)
2454 : First(First_), Last(Last_) {}
2455
2456 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002457
2458 void reset(const char *First_, const char *Last_) {
2459 First = First_;
2460 Last = Last_;
2461 Names.clear();
2462 Subs.clear();
2463 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002464 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002465 TryToParseTemplateArgs = true;
2466 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002467 for (int I = 0; I != 3; ++I)
2468 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002469 ASTAllocator.reset();
2470 }
2471
Richard Smithb485b352018-08-24 23:30:26 +00002472 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002473 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2474 }
2475
2476 template <class It> NodeArray makeNodeArray(It begin, It end) {
2477 size_t sz = static_cast<size_t>(end - begin);
2478 void *mem = ASTAllocator.allocateNodeArray(sz);
2479 Node **data = new (mem) Node *[sz];
2480 std::copy(begin, end, data);
2481 return NodeArray(data, sz);
2482 }
2483
2484 NodeArray popTrailingNodeArray(size_t FromPosition) {
2485 assert(FromPosition <= Names.size());
2486 NodeArray res =
2487 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2488 Names.dropBack(FromPosition);
2489 return res;
2490 }
2491
2492 bool consumeIf(StringView S) {
2493 if (StringView(First, Last).startsWith(S)) {
2494 First += S.size();
2495 return true;
2496 }
2497 return false;
2498 }
2499
2500 bool consumeIf(char C) {
2501 if (First != Last && *First == C) {
2502 ++First;
2503 return true;
2504 }
2505 return false;
2506 }
2507
2508 char consume() { return First != Last ? *First++ : '\0'; }
2509
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08002510 char look(unsigned Lookahead = 0) const {
Richard Smithc20d1442018-08-20 20:14:49 +00002511 if (static_cast<size_t>(Last - First) <= Lookahead)
2512 return '\0';
2513 return First[Lookahead];
2514 }
2515
2516 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2517
2518 StringView parseNumber(bool AllowNegative = false);
2519 Qualifiers parseCVQualifiers();
2520 bool parsePositiveInteger(size_t *Out);
2521 StringView parseBareSourceName();
2522
2523 bool parseSeqId(size_t *Out);
2524 Node *parseSubstitution();
2525 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002526 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002527 Node *parseTemplateArgs(bool TagTemplates = false);
2528 Node *parseTemplateArg();
2529
2530 /// Parse the <expr> production.
2531 Node *parseExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002532 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2533 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00002534 Node *parseIntegerLiteral(StringView Lit);
2535 Node *parseExprPrimary();
2536 template <class Float> Node *parseFloatingLiteral();
2537 Node *parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00002538 Node *parseConversionExpr();
2539 Node *parseBracedExpr();
2540 Node *parseFoldExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002541 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07002542 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002543
2544 /// Parse the <type> production.
2545 Node *parseType();
2546 Node *parseFunctionType();
2547 Node *parseVectorType();
2548 Node *parseDecltype();
2549 Node *parseArrayType();
2550 Node *parsePointerToMemberType();
2551 Node *parseClassEnumType();
2552 Node *parseQualifiedType();
2553
2554 Node *parseEncoding();
2555 bool parseCallOffset();
2556 Node *parseSpecialName();
2557
2558 /// Holds some extra information about a <name> that is being parsed. This
2559 /// information is only pertinent if the <name> refers to an <encoding>.
2560 struct NameState {
2561 bool CtorDtorConversion = false;
2562 bool EndsWithTemplateArgs = false;
2563 Qualifiers CVQualifiers = QualNone;
2564 FunctionRefQual ReferenceQualifier = FrefQualNone;
2565 size_t ForwardTemplateRefsBegin;
2566
Pavel Labathba825192018-10-16 14:29:14 +00002567 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002568 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2569 };
2570
2571 bool resolveForwardTemplateRefs(NameState &State) {
2572 size_t I = State.ForwardTemplateRefsBegin;
2573 size_t E = ForwardTemplateRefs.size();
2574 for (; I < E; ++I) {
2575 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002576 if (TemplateParams.empty() || !TemplateParams[0] ||
2577 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002578 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002579 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002580 }
2581 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2582 return false;
2583 }
2584
2585 /// Parse the <name> production>
2586 Node *parseName(NameState *State = nullptr);
2587 Node *parseLocalName(NameState *State);
2588 Node *parseOperatorName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002589 bool parseModuleNameOpt(ModuleName *&Module);
2590 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
Richard Smithc20d1442018-08-20 20:14:49 +00002591 Node *parseUnnamedTypeName(NameState *State);
2592 Node *parseSourceName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002593 Node *parseUnscopedName(NameState *State, bool *isSubstName);
Richard Smithc20d1442018-08-20 20:14:49 +00002594 Node *parseNestedName(NameState *State);
2595 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2596
2597 Node *parseAbiTags(Node *N);
2598
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002599 struct OperatorInfo {
2600 enum OIKind : unsigned char {
2601 Prefix, // Prefix unary: @ expr
2602 Postfix, // Postfix unary: expr @
2603 Binary, // Binary: lhs @ rhs
2604 Array, // Array index: lhs [ rhs ]
2605 Member, // Member access: lhs @ rhs
2606 New, // New
2607 Del, // Delete
2608 Call, // Function call: expr (expr*)
2609 CCast, // C cast: (type)expr
2610 Conditional, // Conditional: expr ? expr : expr
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08002611 NameOnly, // Overload only, not allowed in expression.
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002612 // Below do not have operator names
2613 NamedCast, // Named cast, @<type>(expr)
2614 OfIdOp, // alignof, sizeof, typeid
2615
2616 Unnameable = NamedCast,
2617 };
2618 char Enc[2]; // Encoding
2619 OIKind Kind; // Kind of operator
2620 bool Flag : 1; // Entry-specific flag
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002621 Node::Prec Prec : 7; // Precedence
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002622 const char *Name; // Spelling
2623
2624 public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002625 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2626 const char *N)
2627 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002628
2629 public:
2630 bool operator<(const OperatorInfo &Other) const {
2631 return *this < Other.Enc;
2632 }
2633 bool operator<(const char *Peek) const {
2634 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2635 }
2636 bool operator==(const char *Peek) const {
2637 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2638 }
2639 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2640
2641 public:
2642 StringView getSymbol() const {
2643 StringView Res = Name;
2644 if (Kind < Unnameable) {
2645 assert(Res.startsWith("operator") &&
2646 "operator name does not start with 'operator'");
2647 Res = Res.dropFront(sizeof("operator") - 1);
2648 Res.consumeFront(' ');
2649 }
2650 return Res;
2651 }
2652 StringView getName() const { return Name; }
2653 OIKind getKind() const { return Kind; }
2654 bool getFlag() const { return Flag; }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002655 Node::Prec getPrecedence() const { return Prec; }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002656 };
Nathan Sidwell7d9bbeb2022-04-08 06:55:31 -07002657 static const OperatorInfo Ops[];
2658 static const size_t NumOps;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002659 const OperatorInfo *parseOperatorEncoding();
2660
Richard Smithc20d1442018-08-20 20:14:49 +00002661 /// Parse the <unresolved-name> production.
Nathan Sidwell77c52e22022-01-28 11:59:03 -08002662 Node *parseUnresolvedName(bool Global);
Richard Smithc20d1442018-08-20 20:14:49 +00002663 Node *parseSimpleId();
2664 Node *parseBaseUnresolvedName();
2665 Node *parseUnresolvedType();
2666 Node *parseDestructorName();
2667
2668 /// Top-level entry point into the parser.
2669 Node *parse();
2670};
2671
2672const char* parse_discriminator(const char* first, const char* last);
2673
2674// <name> ::= <nested-name> // N
2675// ::= <local-name> # See Scope Encoding below // Z
2676// ::= <unscoped-template-name> <template-args>
2677// ::= <unscoped-name>
2678//
2679// <unscoped-template-name> ::= <unscoped-name>
2680// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002681template <typename Derived, typename Alloc>
2682Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002683 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002684 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002685 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002686 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002687
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002688 Node *Result = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002689 bool IsSubst = false;
2690
2691 Result = getDerived().parseUnscopedName(State, &IsSubst);
2692 if (!Result)
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002693 return nullptr;
2694
2695 if (look() == 'I') {
2696 // ::= <unscoped-template-name> <template-args>
2697 if (!IsSubst)
2698 // An unscoped-template-name is substitutable.
2699 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00002700 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002701 if (TA == nullptr)
2702 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002703 if (State)
2704 State->EndsWithTemplateArgs = true;
2705 Result = make<NameWithTemplateArgs>(Result, TA);
2706 } else if (IsSubst) {
2707 // The substitution case must be followed by <template-args>.
2708 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002709 }
2710
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002711 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00002712}
2713
2714// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2715// := Z <function encoding> E s [<discriminator>]
2716// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002717template <typename Derived, typename Alloc>
2718Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002719 if (!consumeIf('Z'))
2720 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002721 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002722 if (Encoding == nullptr || !consumeIf('E'))
2723 return nullptr;
2724
2725 if (consumeIf('s')) {
2726 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002727 auto *StringLitName = make<NameType>("string literal");
2728 if (!StringLitName)
2729 return nullptr;
2730 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002731 }
2732
2733 if (consumeIf('d')) {
2734 parseNumber(true);
2735 if (!consumeIf('_'))
2736 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002737 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002738 if (N == nullptr)
2739 return nullptr;
2740 return make<LocalName>(Encoding, N);
2741 }
2742
Pavel Labathba825192018-10-16 14:29:14 +00002743 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002744 if (Entity == nullptr)
2745 return nullptr;
2746 First = parse_discriminator(First, Last);
2747 return make<LocalName>(Encoding, Entity);
2748}
2749
Nathan Sidwellac492da2022-04-05 09:25:47 -07002750// <unscoped-name> ::= <unqualified-name>
2751// ::= St <unqualified-name> # ::std::
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08002752// [*] extension
Pavel Labathba825192018-10-16 14:29:14 +00002753template <typename Derived, typename Alloc>
2754Node *
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002755AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2756 bool *IsSubst) {
2757
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002758 Node *Std = nullptr;
2759 if (consumeIf("St")) {
2760 Std = make<NameType>("std");
2761 if (Std == nullptr)
Nathan Sidwell200e97c2022-01-21 11:37:01 -08002762 return nullptr;
2763 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002764
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002765 Node *Res = nullptr;
2766 ModuleName *Module = nullptr;
2767 if (look() == 'S') {
2768 Node *S = getDerived().parseSubstitution();
2769 if (!S)
2770 return nullptr;
2771 if (S->getKind() == Node::KModuleName)
2772 Module = static_cast<ModuleName *>(S);
2773 else if (IsSubst && Std == nullptr) {
2774 Res = S;
2775 *IsSubst = true;
2776 } else {
2777 return nullptr;
2778 }
2779 }
2780
Nathan Sidwellac492da2022-04-05 09:25:47 -07002781 if (Res == nullptr || Std != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002782 Res = getDerived().parseUnqualifiedName(State, Std, Module);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002783 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002784
2785 return Res;
Richard Smithc20d1442018-08-20 20:14:49 +00002786}
2787
Nathan Sidwellac492da2022-04-05 09:25:47 -07002788// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002789// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
Nathan Sidwellac492da2022-04-05 09:25:47 -07002790// ::= [<module-name>] L? <source-name> [<abi-tags>]
2791// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002792// # structured binding declaration
Nathan Sidwellac492da2022-04-05 09:25:47 -07002793// ::= [<module-name>] L? DC <source-name>+ E
Pavel Labathba825192018-10-16 14:29:14 +00002794template <typename Derived, typename Alloc>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002795Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2796 NameState *State, Node *Scope, ModuleName *Module) {
2797 if (getDerived().parseModuleNameOpt(Module))
2798 return nullptr;
2799
Nathan Sidwellac492da2022-04-05 09:25:47 -07002800 consumeIf('L');
2801
Richard Smithc20d1442018-08-20 20:14:49 +00002802 Node *Result;
Nathan Sidwellac492da2022-04-05 09:25:47 -07002803 if (look() >= '1' && look() <= '9') {
Pavel Labathba825192018-10-16 14:29:14 +00002804 Result = getDerived().parseSourceName(State);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002805 } else if (look() == 'U') {
2806 Result = getDerived().parseUnnamedTypeName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002807 } else if (consumeIf("DC")) {
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002808 // Structured binding
Richard Smithc20d1442018-08-20 20:14:49 +00002809 size_t BindingsBegin = Names.size();
2810 do {
Pavel Labathba825192018-10-16 14:29:14 +00002811 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002812 if (Binding == nullptr)
2813 return nullptr;
2814 Names.push_back(Binding);
2815 } while (!consumeIf('E'));
2816 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002817 } else if (look() == 'C' || look() == 'D') {
2818 // A <ctor-dtor-name>.
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002819 if (Scope == nullptr || Module != nullptr)
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002820 return nullptr;
2821 Result = getDerived().parseCtorDtorName(Scope, State);
2822 } else {
Pavel Labathba825192018-10-16 14:29:14 +00002823 Result = getDerived().parseOperatorName(State);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002824 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002825
David Blaikie019fb1b2022-03-30 20:18:40 +00002826 if (Result != nullptr && Module != nullptr)
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002827 Result = make<ModuleEntity>(Module, Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002828 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002829 Result = getDerived().parseAbiTags(Result);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002830 if (Result != nullptr && Scope != nullptr)
2831 Result = make<NestedName>(Scope, Result);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002832
Richard Smithc20d1442018-08-20 20:14:49 +00002833 return Result;
2834}
2835
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002836// <module-name> ::= <module-subname>
2837// ::= <module-name> <module-subname>
2838// ::= <substitution> # passed in by caller
2839// <module-subname> ::= W <source-name>
2840// ::= W P <source-name>
2841template <typename Derived, typename Alloc>
2842bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2843 ModuleName *&Module) {
2844 while (consumeIf('W')) {
2845 bool IsPartition = consumeIf('P');
2846 Node *Sub = getDerived().parseSourceName(nullptr);
2847 if (!Sub)
2848 return true;
2849 Module =
2850 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2851 Subs.push_back(Module);
2852 }
2853
2854 return false;
2855}
2856
Richard Smithc20d1442018-08-20 20:14:49 +00002857// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2858// ::= <closure-type-name>
2859//
2860// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2861//
2862// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002863template <typename Derived, typename Alloc>
2864Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002865AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2866 // <template-params> refer to the innermost <template-args>. Clear out any
2867 // outer args that we may have inserted into TemplateParams.
2868 if (State != nullptr)
2869 TemplateParams.clear();
2870
Richard Smithc20d1442018-08-20 20:14:49 +00002871 if (consumeIf("Ut")) {
2872 StringView Count = parseNumber();
2873 if (!consumeIf('_'))
2874 return nullptr;
2875 return make<UnnamedTypeName>(Count);
2876 }
2877 if (consumeIf("Ul")) {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08002878 ScopedOverride<size_t> SwapParams(ParsingLambdaParamsAtLevel,
Richard Smithdf1c14c2019-09-06 23:53:21 +00002879 TemplateParams.size());
2880 ScopedTemplateParamList LambdaTemplateParams(this);
2881
2882 size_t ParamsBegin = Names.size();
2883 while (look() == 'T' &&
2884 StringView("yptn").find(look(1)) != StringView::npos) {
2885 Node *T = parseTemplateParamDecl();
2886 if (!T)
2887 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002888 Names.push_back(T);
2889 }
2890 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2891
2892 // FIXME: If TempParams is empty and none of the function parameters
2893 // includes 'auto', we should remove LambdaTemplateParams from the
2894 // TemplateParams list. Unfortunately, we don't find out whether there are
2895 // any 'auto' parameters until too late in an example such as:
2896 //
2897 // template<typename T> void f(
2898 // decltype([](decltype([]<typename T>(T v) {}),
2899 // auto) {})) {}
2900 // template<typename T> void f(
2901 // decltype([](decltype([]<typename T>(T w) {}),
2902 // int) {})) {}
2903 //
2904 // Here, the type of v is at level 2 but the type of w is at level 1. We
2905 // don't find this out until we encounter the type of the next parameter.
2906 //
2907 // However, compilers can't actually cope with the former example in
2908 // practice, and it's likely to be made ill-formed in future, so we don't
2909 // need to support it here.
2910 //
2911 // If we encounter an 'auto' in the function parameter types, we will
2912 // recreate a template parameter scope for it, but any intervening lambdas
2913 // will be parsed in the 'wrong' template parameter depth.
2914 if (TempParams.empty())
2915 TemplateParams.pop_back();
2916
Richard Smithc20d1442018-08-20 20:14:49 +00002917 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002918 do {
Pavel Labathba825192018-10-16 14:29:14 +00002919 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002920 if (P == nullptr)
2921 return nullptr;
2922 Names.push_back(P);
2923 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002924 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002925 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2926
Richard Smithc20d1442018-08-20 20:14:49 +00002927 StringView Count = parseNumber();
2928 if (!consumeIf('_'))
2929 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002930 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002931 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002932 if (consumeIf("Ub")) {
2933 (void)parseNumber();
2934 if (!consumeIf('_'))
2935 return nullptr;
2936 return make<NameType>("'block-literal'");
2937 }
Richard Smithc20d1442018-08-20 20:14:49 +00002938 return nullptr;
2939}
2940
2941// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002942template <typename Derived, typename Alloc>
2943Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002944 size_t Length = 0;
2945 if (parsePositiveInteger(&Length))
2946 return nullptr;
2947 if (numLeft() < Length || Length == 0)
2948 return nullptr;
2949 StringView Name(First, First + Length);
2950 First += Length;
2951 if (Name.startsWith("_GLOBAL__N"))
2952 return make<NameType>("(anonymous namespace)");
2953 return make<NameType>(Name);
2954}
2955
Nathan Sidwell7d9bbeb2022-04-08 06:55:31 -07002956// Operator encodings
2957template <typename Derived, typename Alloc>
2958const typename AbstractManglingParser<
2959 Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,
2960 Alloc>::Ops[] = {
2961 // Keep ordered by encoding
2962 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
2963 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
2964 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
2965 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
2966 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
2967 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},
2968 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
2969 "operator co_await"},
2970 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},
2971 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
2972 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
2973 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
2974 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
2975 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast
2976 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
2977 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
2978 "operator delete[]"},
2979 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},
2980 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
2981 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
2982 "operator delete"},
2983 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2984 "operator.*"},
2985 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
2986 "operator."},
2987 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
2988 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
2989 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
2990 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
2991 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
2992 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
2993 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
2994 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
2995 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
2996 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
2997 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
2998 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
2999 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
3000 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
3001 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3002 "operator*"},
3003 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
3004 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
3005 "operator new[]"},
3006 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
3007 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
3008 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
3009 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},
3010 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
3011 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
3012 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
3013 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
3014 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
3015 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3016 "operator->*"},
3017 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
3018 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
3019 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
3020 "operator->"},
3021 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
3022 "operator?"},
3023 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
3024 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
3025 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3026 "reinterpret_cast"},
3027 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3028 "operator%"},
3029 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3030 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},
3031 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3032 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3033 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},
3034 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3035 "typeid "},
3036 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
3037};
3038template <typename Derived, typename Alloc>
3039const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /
3040 sizeof(Ops[0]);
3041
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003042// If the next 2 chars are an operator encoding, consume them and return their
3043// OperatorInfo. Otherwise return nullptr.
3044template <typename Derived, typename Alloc>
3045const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
3046AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003047 if (numLeft() < 2)
3048 return nullptr;
3049
3050 auto Op = std::lower_bound(
3051 &Ops[0], &Ops[NumOps], First,
3052 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3053 if (Op == &Ops[NumOps] || *Op != First)
3054 return nullptr;
3055
3056 First += 2;
3057 return Op;
3058}
3059
3060// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003061// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003062// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003063template <typename Derived, typename Alloc>
3064Node *
3065AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003066 if (const auto *Op = parseOperatorEncoding()) {
3067 if (Op->getKind() == OperatorInfo::CCast) {
3068 // ::= cv <type> # (cast)
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003069 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);
Richard Smithc20d1442018-08-20 20:14:49 +00003070 // If we're parsing an encoding, State != nullptr and the conversion
3071 // operators' <type> could have a <template-param> that refers to some
3072 // <template-arg>s further ahead in the mangled name.
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003073 ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,
Richard Smithc20d1442018-08-20 20:14:49 +00003074 PermitForwardTemplateReferences ||
3075 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003076 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003077 if (Ty == nullptr)
3078 return nullptr;
3079 if (State) State->CtorDtorConversion = true;
3080 return make<ConversionOperatorType>(Ty);
3081 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003082
3083 if (Op->getKind() >= OperatorInfo::Unnameable)
3084 /* Not a nameable operator. */
3085 return nullptr;
3086 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3087 /* Not a nameable MemberExpr */
3088 return nullptr;
3089
3090 return make<NameType>(Op->getName());
3091 }
3092
3093 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003094 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003095 Node *SN = getDerived().parseSourceName(State);
3096 if (SN == nullptr)
3097 return nullptr;
3098 return make<LiteralOperator>(SN);
3099 }
3100
3101 if (consumeIf('v')) {
3102 // ::= v <digit> <source-name> # vendor extended operator
3103 if (look() >= '0' && look() <= '9') {
3104 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003105 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003106 if (SN == nullptr)
3107 return nullptr;
3108 return make<ConversionOperatorType>(SN);
3109 }
3110 return nullptr;
3111 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003112
Richard Smithc20d1442018-08-20 20:14:49 +00003113 return nullptr;
3114}
3115
3116// <ctor-dtor-name> ::= C1 # complete object constructor
3117// ::= C2 # base object constructor
3118// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003119// extension ::= C4 # gcc old-style "[unified]" constructor
3120// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003121// ::= D0 # deleting destructor
3122// ::= D1 # complete object destructor
3123// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003124// extension ::= D4 # gcc old-style "[unified]" destructor
3125// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003126template <typename Derived, typename Alloc>
3127Node *
3128AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3129 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003130 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3131 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3132 switch (SSK) {
3133 case SpecialSubKind::string:
3134 case SpecialSubKind::istream:
3135 case SpecialSubKind::ostream:
3136 case SpecialSubKind::iostream:
3137 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00003138 if (!SoFar)
3139 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00003140 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003141 default:
3142 break;
3143 }
3144 }
3145
3146 if (consumeIf('C')) {
3147 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003148 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3149 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003150 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003151 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003152 ++First;
3153 if (State) State->CtorDtorConversion = true;
3154 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003155 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003156 return nullptr;
3157 }
Nico Weber29294792019-04-03 23:14:33 +00003158 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003159 }
3160
Nico Weber29294792019-04-03 23:14:33 +00003161 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3162 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003163 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003164 First += 2;
3165 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003166 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003167 }
3168
3169 return nullptr;
3170}
3171
Nathan Sidwellac492da2022-04-05 09:25:47 -07003172// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3173// <unqualified-name> E
3174// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3175// <template-args> E
Richard Smithc20d1442018-08-20 20:14:49 +00003176//
Nathan Sidwellac492da2022-04-05 09:25:47 -07003177// <prefix> ::= <prefix> <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003178// ::= <template-prefix> <template-args>
3179// ::= <template-param>
3180// ::= <decltype>
3181// ::= # empty
3182// ::= <substitution>
3183// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003184// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003185//
3186// <data-member-prefix> := <member source-name> [<template-args>] M
3187//
3188// <template-prefix> ::= <prefix> <template unqualified-name>
3189// ::= <template-param>
3190// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003191template <typename Derived, typename Alloc>
3192Node *
3193AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003194 if (!consumeIf('N'))
3195 return nullptr;
3196
3197 Qualifiers CVTmp = parseCVQualifiers();
3198 if (State) State->CVQualifiers = CVTmp;
3199
3200 if (consumeIf('O')) {
3201 if (State) State->ReferenceQualifier = FrefQualRValue;
3202 } else if (consumeIf('R')) {
3203 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003204 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003205 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003206 }
Richard Smithc20d1442018-08-20 20:14:49 +00003207
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003208 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003209 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003210 if (State)
3211 // Only set end-with-template on the case that does that.
3212 State->EndsWithTemplateArgs = false;
3213
Richard Smithc20d1442018-08-20 20:14:49 +00003214 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003215 // ::= <template-param>
3216 if (SoFar != nullptr)
3217 return nullptr; // Cannot have a prefix.
3218 SoFar = getDerived().parseTemplateParam();
3219 } else if (look() == 'I') {
3220 // ::= <template-prefix> <template-args>
3221 if (SoFar == nullptr)
3222 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003223 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003224 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003225 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003226 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3227 // Semantically <template-args> <template-args> cannot be generated by a
3228 // C++ entity. There will always be [something like] a name between
3229 // them.
3230 return nullptr;
3231 if (State)
3232 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003233 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003234 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3235 // ::= <decltype>
3236 if (SoFar != nullptr)
3237 return nullptr; // Cannot have a prefix.
3238 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003239 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003240 ModuleName *Module = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003241
3242 if (look() == 'S') {
3243 // ::= <substitution>
3244 Node *S = nullptr;
3245 if (look(1) == 't') {
3246 First += 2;
3247 S = make<NameType>("std");
3248 } else {
3249 S = getDerived().parseSubstitution();
3250 }
3251 if (!S)
3252 return nullptr;
3253 if (S->getKind() == Node::KModuleName) {
3254 Module = static_cast<ModuleName *>(S);
Nathan Sidwellac492da2022-04-05 09:25:47 -07003255 } else if (SoFar != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003256 return nullptr; // Cannot have a prefix.
3257 } else {
3258 SoFar = S;
3259 continue; // Do not push a new substitution.
3260 }
3261 }
3262
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003263 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003264 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003265 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003266
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003267 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003268 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003269 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003270
3271 // No longer used.
3272 // <data-member-prefix> := <member source-name> [<template-args>] M
3273 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003274 }
3275
3276 if (SoFar == nullptr || Subs.empty())
3277 return nullptr;
3278
3279 Subs.pop_back();
3280 return SoFar;
3281}
3282
3283// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003284template <typename Derived, typename Alloc>
3285Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3286 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003287 if (SN == nullptr)
3288 return nullptr;
3289 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003290 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003291 if (TA == nullptr)
3292 return nullptr;
3293 return make<NameWithTemplateArgs>(SN, TA);
3294 }
3295 return SN;
3296}
3297
3298// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3299// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003300template <typename Derived, typename Alloc>
3301Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003302 Node *Result;
3303 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003304 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003305 else
Pavel Labathba825192018-10-16 14:29:14 +00003306 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003307 if (Result == nullptr)
3308 return nullptr;
3309 return make<DtorName>(Result);
3310}
3311
3312// <unresolved-type> ::= <template-param>
3313// ::= <decltype>
3314// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003315template <typename Derived, typename Alloc>
3316Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003317 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003318 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003319 if (TP == nullptr)
3320 return nullptr;
3321 Subs.push_back(TP);
3322 return TP;
3323 }
3324 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003325 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003326 if (DT == nullptr)
3327 return nullptr;
3328 Subs.push_back(DT);
3329 return DT;
3330 }
Pavel Labathba825192018-10-16 14:29:14 +00003331 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003332}
3333
3334// <base-unresolved-name> ::= <simple-id> # unresolved name
3335// extension ::= <operator-name> # unresolved operator-function-id
3336// extension ::= <operator-name> <template-args> # unresolved operator template-id
3337// ::= on <operator-name> # unresolved operator-function-id
3338// ::= on <operator-name> <template-args> # unresolved operator template-id
3339// ::= dn <destructor-name> # destructor or pseudo-destructor;
3340// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003341template <typename Derived, typename Alloc>
3342Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003343 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003344 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003345
3346 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003347 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003348
3349 consumeIf("on");
3350
Pavel Labathba825192018-10-16 14:29:14 +00003351 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003352 if (Oper == nullptr)
3353 return nullptr;
3354 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003355 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003356 if (TA == nullptr)
3357 return nullptr;
3358 return make<NameWithTemplateArgs>(Oper, TA);
3359 }
3360 return Oper;
3361}
3362
3363// <unresolved-name>
3364// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3365// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3366// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3367// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003368// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003369// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3370// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3371// # T::N::x /decltype(p)::N::x
3372// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3373//
3374// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003375template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003376Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003377 Node *SoFar = nullptr;
3378
3379 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3380 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3381 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003382 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003383 if (SoFar == nullptr)
3384 return nullptr;
3385
3386 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003387 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003388 if (TA == nullptr)
3389 return nullptr;
3390 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003391 if (!SoFar)
3392 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003393 }
3394
3395 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003396 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003397 if (Qual == nullptr)
3398 return nullptr;
3399 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003400 if (!SoFar)
3401 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003402 }
3403
Pavel Labathba825192018-10-16 14:29:14 +00003404 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003405 if (Base == nullptr)
3406 return nullptr;
3407 return make<QualifiedName>(SoFar, Base);
3408 }
3409
Richard Smithc20d1442018-08-20 20:14:49 +00003410 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3411 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003412 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003413 if (SoFar == nullptr)
3414 return nullptr;
3415 if (Global)
3416 SoFar = make<GlobalQualifiedName>(SoFar);
3417 return SoFar;
3418 }
3419
3420 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3421 if (std::isdigit(look())) {
3422 do {
Pavel Labathba825192018-10-16 14:29:14 +00003423 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003424 if (Qual == nullptr)
3425 return nullptr;
3426 if (SoFar)
3427 SoFar = make<QualifiedName>(SoFar, Qual);
3428 else if (Global)
3429 SoFar = make<GlobalQualifiedName>(Qual);
3430 else
3431 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003432 if (!SoFar)
3433 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003434 } while (!consumeIf('E'));
3435 }
3436 // sr <unresolved-type> <base-unresolved-name>
3437 // sr <unresolved-type> <template-args> <base-unresolved-name>
3438 else {
Pavel Labathba825192018-10-16 14:29:14 +00003439 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003440 if (SoFar == nullptr)
3441 return nullptr;
3442
3443 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003444 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003445 if (TA == nullptr)
3446 return nullptr;
3447 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003448 if (!SoFar)
3449 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003450 }
3451 }
3452
3453 assert(SoFar != nullptr);
3454
Pavel Labathba825192018-10-16 14:29:14 +00003455 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003456 if (Base == nullptr)
3457 return nullptr;
3458 return make<QualifiedName>(SoFar, Base);
3459}
3460
3461// <abi-tags> ::= <abi-tag> [<abi-tags>]
3462// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003463template <typename Derived, typename Alloc>
3464Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003465 while (consumeIf('B')) {
3466 StringView SN = parseBareSourceName();
3467 if (SN.empty())
3468 return nullptr;
3469 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003470 if (!N)
3471 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003472 }
3473 return N;
3474}
3475
3476// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003477template <typename Alloc, typename Derived>
3478StringView
3479AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003480 const char *Tmp = First;
3481 if (AllowNegative)
3482 consumeIf('n');
3483 if (numLeft() == 0 || !std::isdigit(*First))
3484 return StringView();
3485 while (numLeft() != 0 && std::isdigit(*First))
3486 ++First;
3487 return StringView(Tmp, First);
3488}
3489
3490// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003491template <typename Alloc, typename Derived>
3492bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003493 *Out = 0;
3494 if (look() < '0' || look() > '9')
3495 return true;
3496 while (look() >= '0' && look() <= '9') {
3497 *Out *= 10;
3498 *Out += static_cast<size_t>(consume() - '0');
3499 }
3500 return false;
3501}
3502
Pavel Labathba825192018-10-16 14:29:14 +00003503template <typename Alloc, typename Derived>
3504StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003505 size_t Int = 0;
3506 if (parsePositiveInteger(&Int) || numLeft() < Int)
3507 return StringView();
3508 StringView R(First, First + Int);
3509 First += Int;
3510 return R;
3511}
3512
3513// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3514//
3515// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3516// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3517// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3518//
3519// <ref-qualifier> ::= R # & ref-qualifier
3520// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003521template <typename Derived, typename Alloc>
3522Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003523 Qualifiers CVQuals = parseCVQualifiers();
3524
3525 Node *ExceptionSpec = nullptr;
3526 if (consumeIf("Do")) {
3527 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003528 if (!ExceptionSpec)
3529 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003530 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003531 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003532 if (E == nullptr || !consumeIf('E'))
3533 return nullptr;
3534 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003535 if (!ExceptionSpec)
3536 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003537 } else if (consumeIf("Dw")) {
3538 size_t SpecsBegin = Names.size();
3539 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003540 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003541 if (T == nullptr)
3542 return nullptr;
3543 Names.push_back(T);
3544 }
3545 ExceptionSpec =
3546 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003547 if (!ExceptionSpec)
3548 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003549 }
3550
3551 consumeIf("Dx"); // transaction safe
3552
3553 if (!consumeIf('F'))
3554 return nullptr;
3555 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003556 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003557 if (ReturnType == nullptr)
3558 return nullptr;
3559
3560 FunctionRefQual ReferenceQualifier = FrefQualNone;
3561 size_t ParamsBegin = Names.size();
3562 while (true) {
3563 if (consumeIf('E'))
3564 break;
3565 if (consumeIf('v'))
3566 continue;
3567 if (consumeIf("RE")) {
3568 ReferenceQualifier = FrefQualLValue;
3569 break;
3570 }
3571 if (consumeIf("OE")) {
3572 ReferenceQualifier = FrefQualRValue;
3573 break;
3574 }
Pavel Labathba825192018-10-16 14:29:14 +00003575 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003576 if (T == nullptr)
3577 return nullptr;
3578 Names.push_back(T);
3579 }
3580
3581 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3582 return make<FunctionType>(ReturnType, Params, CVQuals,
3583 ReferenceQualifier, ExceptionSpec);
3584}
3585
3586// extension:
3587// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3588// ::= Dv [<dimension expression>] _ <element type>
3589// <extended element type> ::= <element type>
3590// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003591template <typename Derived, typename Alloc>
3592Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003593 if (!consumeIf("Dv"))
3594 return nullptr;
3595 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003596 Node *DimensionNumber = make<NameType>(parseNumber());
3597 if (!DimensionNumber)
3598 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003599 if (!consumeIf('_'))
3600 return nullptr;
3601 if (consumeIf('p'))
3602 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003603 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003604 if (ElemType == nullptr)
3605 return nullptr;
3606 return make<VectorType>(ElemType, DimensionNumber);
3607 }
3608
3609 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003610 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003611 if (!DimExpr)
3612 return nullptr;
3613 if (!consumeIf('_'))
3614 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003615 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003616 if (!ElemType)
3617 return nullptr;
3618 return make<VectorType>(ElemType, DimExpr);
3619 }
Pavel Labathba825192018-10-16 14:29:14 +00003620 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003621 if (!ElemType)
3622 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003623 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003624}
3625
3626// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3627// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003628template <typename Derived, typename Alloc>
3629Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003630 if (!consumeIf('D'))
3631 return nullptr;
3632 if (!consumeIf('t') && !consumeIf('T'))
3633 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003634 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003635 if (E == nullptr)
3636 return nullptr;
3637 if (!consumeIf('E'))
3638 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003639 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003640}
3641
3642// <array-type> ::= A <positive dimension number> _ <element type>
3643// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003644template <typename Derived, typename Alloc>
3645Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003646 if (!consumeIf('A'))
3647 return nullptr;
3648
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003649 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003650
Richard Smithc20d1442018-08-20 20:14:49 +00003651 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003652 Dimension = make<NameType>(parseNumber());
3653 if (!Dimension)
3654 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003655 if (!consumeIf('_'))
3656 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003657 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003658 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003659 if (DimExpr == nullptr)
3660 return nullptr;
3661 if (!consumeIf('_'))
3662 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003663 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003664 }
3665
Pavel Labathba825192018-10-16 14:29:14 +00003666 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003667 if (Ty == nullptr)
3668 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003669 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003670}
3671
3672// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003673template <typename Derived, typename Alloc>
3674Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003675 if (!consumeIf('M'))
3676 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003677 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003678 if (ClassType == nullptr)
3679 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003680 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003681 if (MemberType == nullptr)
3682 return nullptr;
3683 return make<PointerToMemberType>(ClassType, MemberType);
3684}
3685
3686// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3687// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3688// ::= Tu <name> # dependent elaborated type specifier using 'union'
3689// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003690template <typename Derived, typename Alloc>
3691Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003692 StringView ElabSpef;
3693 if (consumeIf("Ts"))
3694 ElabSpef = "struct";
3695 else if (consumeIf("Tu"))
3696 ElabSpef = "union";
3697 else if (consumeIf("Te"))
3698 ElabSpef = "enum";
3699
Pavel Labathba825192018-10-16 14:29:14 +00003700 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003701 if (Name == nullptr)
3702 return nullptr;
3703
3704 if (!ElabSpef.empty())
3705 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3706
3707 return Name;
3708}
3709
3710// <qualified-type> ::= <qualifiers> <type>
3711// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3712// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003713template <typename Derived, typename Alloc>
3714Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003715 if (consumeIf('U')) {
3716 StringView Qual = parseBareSourceName();
3717 if (Qual.empty())
3718 return nullptr;
3719
Richard Smithc20d1442018-08-20 20:14:49 +00003720 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3721 if (Qual.startsWith("objcproto")) {
3722 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3723 StringView Proto;
3724 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003725 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()),
3726 SaveLast(Last, ProtoSourceName.end());
Richard Smithc20d1442018-08-20 20:14:49 +00003727 Proto = parseBareSourceName();
3728 }
3729 if (Proto.empty())
3730 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003731 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003732 if (Child == nullptr)
3733 return nullptr;
3734 return make<ObjCProtoName>(Child, Proto);
3735 }
3736
Alex Orlovf50df922021-03-24 10:21:32 +04003737 Node *TA = nullptr;
3738 if (look() == 'I') {
3739 TA = getDerived().parseTemplateArgs();
3740 if (TA == nullptr)
3741 return nullptr;
3742 }
3743
Pavel Labathba825192018-10-16 14:29:14 +00003744 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003745 if (Child == nullptr)
3746 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003747 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003748 }
3749
3750 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003751 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003752 if (Ty == nullptr)
3753 return nullptr;
3754 if (Quals != QualNone)
3755 Ty = make<QualType>(Ty, Quals);
3756 return Ty;
3757}
3758
3759// <type> ::= <builtin-type>
3760// ::= <qualified-type>
3761// ::= <function-type>
3762// ::= <class-enum-type>
3763// ::= <array-type>
3764// ::= <pointer-to-member-type>
3765// ::= <template-param>
3766// ::= <template-template-param> <template-args>
3767// ::= <decltype>
3768// ::= P <type> # pointer
3769// ::= R <type> # l-value reference
3770// ::= O <type> # r-value reference (C++11)
3771// ::= C <type> # complex pair (C99)
3772// ::= G <type> # imaginary (C99)
3773// ::= <substitution> # See Compression below
3774// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3775// extension ::= <vector-type> # <vector-type> starts with Dv
3776//
3777// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3778// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003779template <typename Derived, typename Alloc>
3780Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003781 Node *Result = nullptr;
3782
Richard Smithc20d1442018-08-20 20:14:49 +00003783 switch (look()) {
3784 // ::= <qualified-type>
3785 case 'r':
3786 case 'V':
3787 case 'K': {
3788 unsigned AfterQuals = 0;
3789 if (look(AfterQuals) == 'r') ++AfterQuals;
3790 if (look(AfterQuals) == 'V') ++AfterQuals;
3791 if (look(AfterQuals) == 'K') ++AfterQuals;
3792
3793 if (look(AfterQuals) == 'F' ||
3794 (look(AfterQuals) == 'D' &&
3795 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3796 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003797 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003798 break;
3799 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003800 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003801 }
3802 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003803 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003804 break;
3805 }
3806 // <builtin-type> ::= v # void
3807 case 'v':
3808 ++First;
3809 return make<NameType>("void");
3810 // ::= w # wchar_t
3811 case 'w':
3812 ++First;
3813 return make<NameType>("wchar_t");
3814 // ::= b # bool
3815 case 'b':
3816 ++First;
3817 return make<NameType>("bool");
3818 // ::= c # char
3819 case 'c':
3820 ++First;
3821 return make<NameType>("char");
3822 // ::= a # signed char
3823 case 'a':
3824 ++First;
3825 return make<NameType>("signed char");
3826 // ::= h # unsigned char
3827 case 'h':
3828 ++First;
3829 return make<NameType>("unsigned char");
3830 // ::= s # short
3831 case 's':
3832 ++First;
3833 return make<NameType>("short");
3834 // ::= t # unsigned short
3835 case 't':
3836 ++First;
3837 return make<NameType>("unsigned short");
3838 // ::= i # int
3839 case 'i':
3840 ++First;
3841 return make<NameType>("int");
3842 // ::= j # unsigned int
3843 case 'j':
3844 ++First;
3845 return make<NameType>("unsigned int");
3846 // ::= l # long
3847 case 'l':
3848 ++First;
3849 return make<NameType>("long");
3850 // ::= m # unsigned long
3851 case 'm':
3852 ++First;
3853 return make<NameType>("unsigned long");
3854 // ::= x # long long, __int64
3855 case 'x':
3856 ++First;
3857 return make<NameType>("long long");
3858 // ::= y # unsigned long long, __int64
3859 case 'y':
3860 ++First;
3861 return make<NameType>("unsigned long long");
3862 // ::= n # __int128
3863 case 'n':
3864 ++First;
3865 return make<NameType>("__int128");
3866 // ::= o # unsigned __int128
3867 case 'o':
3868 ++First;
3869 return make<NameType>("unsigned __int128");
3870 // ::= f # float
3871 case 'f':
3872 ++First;
3873 return make<NameType>("float");
3874 // ::= d # double
3875 case 'd':
3876 ++First;
3877 return make<NameType>("double");
3878 // ::= e # long double, __float80
3879 case 'e':
3880 ++First;
3881 return make<NameType>("long double");
3882 // ::= g # __float128
3883 case 'g':
3884 ++First;
3885 return make<NameType>("__float128");
3886 // ::= z # ellipsis
3887 case 'z':
3888 ++First;
3889 return make<NameType>("...");
3890
3891 // <builtin-type> ::= u <source-name> # vendor extended type
3892 case 'u': {
3893 ++First;
3894 StringView Res = parseBareSourceName();
3895 if (Res.empty())
3896 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003897 // Typically, <builtin-type>s are not considered substitution candidates,
3898 // but the exception to that exception is vendor extended types (Itanium C++
3899 // ABI 5.9.1).
3900 Result = make<NameType>(Res);
3901 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003902 }
3903 case 'D':
3904 switch (look(1)) {
3905 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3906 case 'd':
3907 First += 2;
3908 return make<NameType>("decimal64");
3909 // ::= De # IEEE 754r decimal floating point (128 bits)
3910 case 'e':
3911 First += 2;
3912 return make<NameType>("decimal128");
3913 // ::= Df # IEEE 754r decimal floating point (32 bits)
3914 case 'f':
3915 First += 2;
3916 return make<NameType>("decimal32");
3917 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3918 case 'h':
3919 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003920 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003921 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3922 case 'F': {
3923 First += 2;
3924 Node *DimensionNumber = make<NameType>(parseNumber());
3925 if (!DimensionNumber)
3926 return nullptr;
3927 if (!consumeIf('_'))
3928 return nullptr;
3929 return make<BinaryFPType>(DimensionNumber);
3930 }
Senran Zhange025ba52022-03-27 00:04:23 +08003931 // ::= DB <number> _ # C23 signed _BitInt(N)
3932 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
3933 // ::= DU <number> _ # C23 unsigned _BitInt(N)
3934 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
3935 case 'B':
3936 case 'U': {
3937 bool Signed = look(1) == 'B';
3938 First += 2;
3939 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())
3940 : getDerived().parseExpr();
3941 if (!Size)
3942 return nullptr;
3943 if (!consumeIf('_'))
3944 return nullptr;
3945 return make<BitIntType>(Size, Signed);
3946 }
Richard Smithc20d1442018-08-20 20:14:49 +00003947 // ::= Di # char32_t
3948 case 'i':
3949 First += 2;
3950 return make<NameType>("char32_t");
3951 // ::= Ds # char16_t
3952 case 's':
3953 First += 2;
3954 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003955 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3956 case 'u':
3957 First += 2;
3958 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003959 // ::= Da # auto (in dependent new-expressions)
3960 case 'a':
3961 First += 2;
3962 return make<NameType>("auto");
3963 // ::= Dc # decltype(auto)
3964 case 'c':
3965 First += 2;
3966 return make<NameType>("decltype(auto)");
3967 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3968 case 'n':
3969 First += 2;
3970 return make<NameType>("std::nullptr_t");
3971
3972 // ::= <decltype>
3973 case 't':
3974 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003975 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003976 break;
3977 }
3978 // extension ::= <vector-type> # <vector-type> starts with Dv
3979 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003980 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003981 break;
3982 }
3983 // ::= Dp <type> # pack expansion (C++0x)
3984 case 'p': {
3985 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003986 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003987 if (!Child)
3988 return nullptr;
3989 Result = make<ParameterPackExpansion>(Child);
3990 break;
3991 }
3992 // Exception specifier on a function type.
3993 case 'o':
3994 case 'O':
3995 case 'w':
3996 // Transaction safe function type.
3997 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003998 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003999 break;
4000 }
4001 break;
4002 // ::= <function-type>
4003 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00004004 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00004005 break;
4006 }
4007 // ::= <array-type>
4008 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00004009 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00004010 break;
4011 }
4012 // ::= <pointer-to-member-type>
4013 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00004014 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00004015 break;
4016 }
4017 // ::= <template-param>
4018 case 'T': {
4019 // This could be an elaborate type specifier on a <class-enum-type>.
4020 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00004021 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004022 break;
4023 }
4024
Pavel Labathba825192018-10-16 14:29:14 +00004025 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004026 if (Result == nullptr)
4027 return nullptr;
4028
4029 // Result could be either of:
4030 // <type> ::= <template-param>
4031 // <type> ::= <template-template-param> <template-args>
4032 //
4033 // <template-template-param> ::= <template-param>
4034 // ::= <substitution>
4035 //
4036 // If this is followed by some <template-args>, and we're permitted to
4037 // parse them, take the second production.
4038
4039 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004040 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004041 if (TA == nullptr)
4042 return nullptr;
4043 Result = make<NameWithTemplateArgs>(Result, TA);
4044 }
4045 break;
4046 }
4047 // ::= P <type> # pointer
4048 case 'P': {
4049 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004050 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004051 if (Ptr == nullptr)
4052 return nullptr;
4053 Result = make<PointerType>(Ptr);
4054 break;
4055 }
4056 // ::= R <type> # l-value reference
4057 case 'R': {
4058 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004059 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004060 if (Ref == nullptr)
4061 return nullptr;
4062 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4063 break;
4064 }
4065 // ::= O <type> # r-value reference (C++11)
4066 case 'O': {
4067 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004068 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004069 if (Ref == nullptr)
4070 return nullptr;
4071 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4072 break;
4073 }
4074 // ::= C <type> # complex pair (C99)
4075 case 'C': {
4076 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004077 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004078 if (P == nullptr)
4079 return nullptr;
4080 Result = make<PostfixQualifiedType>(P, " complex");
4081 break;
4082 }
4083 // ::= G <type> # imaginary (C99)
4084 case 'G': {
4085 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004086 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004087 if (P == nullptr)
4088 return P;
4089 Result = make<PostfixQualifiedType>(P, " imaginary");
4090 break;
4091 }
4092 // ::= <substitution> # See Compression below
4093 case 'S': {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004094 if (look(1) != 't') {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004095 bool IsSubst = false;
4096 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4097 if (!Result)
Richard Smithc20d1442018-08-20 20:14:49 +00004098 return nullptr;
4099
4100 // Sub could be either of:
4101 // <type> ::= <substitution>
4102 // <type> ::= <template-template-param> <template-args>
4103 //
4104 // <template-template-param> ::= <template-param>
4105 // ::= <substitution>
4106 //
4107 // If this is followed by some <template-args>, and we're permitted to
4108 // parse them, take the second production.
4109
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004110 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4111 if (!IsSubst)
4112 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00004113 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004114 if (TA == nullptr)
4115 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004116 Result = make<NameWithTemplateArgs>(Result, TA);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004117 } else if (IsSubst) {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004118 // If all we parsed was a substitution, don't re-insert into the
4119 // substitution table.
4120 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00004121 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004122 break;
Richard Smithc20d1442018-08-20 20:14:49 +00004123 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004124 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004125 }
4126 // ::= <class-enum-type>
4127 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004128 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004129 break;
4130 }
4131 }
4132
4133 // If we parsed a type, insert it into the substitution table. Note that all
4134 // <builtin-type>s and <substitution>s have already bailed out, because they
4135 // don't get substitutions.
4136 if (Result != nullptr)
4137 Subs.push_back(Result);
4138 return Result;
4139}
4140
Pavel Labathba825192018-10-16 14:29:14 +00004141template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004142Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4143 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004144 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004145 if (E == nullptr)
4146 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004147 return make<PrefixExpr>(Kind, E, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004148}
4149
Pavel Labathba825192018-10-16 14:29:14 +00004150template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004151Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4152 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004153 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004154 if (LHS == nullptr)
4155 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004156 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004157 if (RHS == nullptr)
4158 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004159 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004160}
4161
Pavel Labathba825192018-10-16 14:29:14 +00004162template <typename Derived, typename Alloc>
4163Node *
4164AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004165 StringView Tmp = parseNumber(true);
4166 if (!Tmp.empty() && consumeIf('E'))
4167 return make<IntegerLiteral>(Lit, Tmp);
4168 return nullptr;
4169}
4170
4171// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004172template <typename Alloc, typename Derived>
4173Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004174 Qualifiers CVR = QualNone;
4175 if (consumeIf('r'))
4176 CVR |= QualRestrict;
4177 if (consumeIf('V'))
4178 CVR |= QualVolatile;
4179 if (consumeIf('K'))
4180 CVR |= QualConst;
4181 return CVR;
4182}
4183
4184// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4185// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4186// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4187// ::= 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 -04004188// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004189template <typename Derived, typename Alloc>
4190Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004191 if (consumeIf("fpT"))
4192 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004193 if (consumeIf("fp")) {
4194 parseCVQualifiers();
4195 StringView Num = parseNumber();
4196 if (!consumeIf('_'))
4197 return nullptr;
4198 return make<FunctionParam>(Num);
4199 }
4200 if (consumeIf("fL")) {
4201 if (parseNumber().empty())
4202 return nullptr;
4203 if (!consumeIf('p'))
4204 return nullptr;
4205 parseCVQualifiers();
4206 StringView Num = parseNumber();
4207 if (!consumeIf('_'))
4208 return nullptr;
4209 return make<FunctionParam>(Num);
4210 }
4211 return nullptr;
4212}
4213
Richard Smithc20d1442018-08-20 20:14:49 +00004214// cv <type> <expression> # conversion with one argument
4215// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004216template <typename Derived, typename Alloc>
4217Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004218 if (!consumeIf("cv"))
4219 return nullptr;
4220 Node *Ty;
4221 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004222 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004223 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004224 }
4225
4226 if (Ty == nullptr)
4227 return nullptr;
4228
4229 if (consumeIf('_')) {
4230 size_t ExprsBegin = Names.size();
4231 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004232 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004233 if (E == nullptr)
4234 return E;
4235 Names.push_back(E);
4236 }
4237 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4238 return make<ConversionExpr>(Ty, Exprs);
4239 }
4240
Pavel Labathba825192018-10-16 14:29:14 +00004241 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004242 if (E[0] == nullptr)
4243 return nullptr;
4244 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4245}
4246
4247// <expr-primary> ::= L <type> <value number> E # integer literal
4248// ::= L <type> <value float> E # floating literal
4249// ::= L <string type> E # string literal
4250// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004251// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004252// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4253// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004254template <typename Derived, typename Alloc>
4255Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004256 if (!consumeIf('L'))
4257 return nullptr;
4258 switch (look()) {
4259 case 'w':
4260 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004261 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004262 case 'b':
4263 if (consumeIf("b0E"))
4264 return make<BoolExpr>(0);
4265 if (consumeIf("b1E"))
4266 return make<BoolExpr>(1);
4267 return nullptr;
4268 case 'c':
4269 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004270 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004271 case 'a':
4272 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004273 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004274 case 'h':
4275 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004276 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004277 case 's':
4278 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004279 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004280 case 't':
4281 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004282 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004283 case 'i':
4284 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004285 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004286 case 'j':
4287 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004288 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004289 case 'l':
4290 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004291 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004292 case 'm':
4293 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004294 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004295 case 'x':
4296 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004297 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004298 case 'y':
4299 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004300 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004301 case 'n':
4302 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004303 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004304 case 'o':
4305 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004306 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004307 case 'f':
4308 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004309 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004310 case 'd':
4311 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004312 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004313 case 'e':
4314 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004315#if defined(__powerpc__) || defined(__s390__)
4316 // Handle cases where long doubles encoded with e have the same size
4317 // and representation as doubles.
4318 return getDerived().template parseFloatingLiteral<double>();
4319#else
Pavel Labathba825192018-10-16 14:29:14 +00004320 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004321#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004322 case '_':
4323 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004324 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004325 if (R != nullptr && consumeIf('E'))
4326 return R;
4327 }
4328 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004329 case 'A': {
4330 Node *T = getDerived().parseType();
4331 if (T == nullptr)
4332 return nullptr;
4333 // FIXME: We need to include the string contents in the mangling.
4334 if (consumeIf('E'))
4335 return make<StringLiteral>(T);
4336 return nullptr;
4337 }
4338 case 'D':
gbreynooc0559322022-04-28 15:55:26 +01004339 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
Richard Smithdf1c14c2019-09-06 23:53:21 +00004340 return make<NameType>("nullptr");
4341 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004342 case 'T':
4343 // Invalid mangled name per
4344 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4345 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004346 case 'U': {
4347 // FIXME: Should we support LUb... for block literals?
4348 if (look(1) != 'l')
4349 return nullptr;
4350 Node *T = parseUnnamedTypeName(nullptr);
4351 if (!T || !consumeIf('E'))
4352 return nullptr;
4353 return make<LambdaExpr>(T);
4354 }
Richard Smithc20d1442018-08-20 20:14:49 +00004355 default: {
4356 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004357 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004358 if (T == nullptr)
4359 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004360 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004361 if (N.empty())
4362 return nullptr;
4363 if (!consumeIf('E'))
4364 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004365 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004366 }
4367 }
4368}
4369
4370// <braced-expression> ::= <expression>
4371// ::= di <field source-name> <braced-expression> # .name = expr
4372// ::= dx <index expression> <braced-expression> # [expr] = expr
4373// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004374template <typename Derived, typename Alloc>
4375Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004376 if (look() == 'd') {
4377 switch (look(1)) {
4378 case 'i': {
4379 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004380 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004381 if (Field == nullptr)
4382 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004383 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004384 if (Init == nullptr)
4385 return nullptr;
4386 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4387 }
4388 case 'x': {
4389 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004390 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004391 if (Index == nullptr)
4392 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004393 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004394 if (Init == nullptr)
4395 return nullptr;
4396 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4397 }
4398 case 'X': {
4399 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004400 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004401 if (RangeBegin == nullptr)
4402 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004403 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004404 if (RangeEnd == nullptr)
4405 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004406 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004407 if (Init == nullptr)
4408 return nullptr;
4409 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4410 }
4411 }
4412 }
Pavel Labathba825192018-10-16 14:29:14 +00004413 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004414}
4415
4416// (not yet in the spec)
4417// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4418// ::= fR <binary-operator-name> <expression> <expression>
4419// ::= fl <binary-operator-name> <expression>
4420// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004421template <typename Derived, typename Alloc>
4422Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004423 if (!consumeIf('f'))
4424 return nullptr;
4425
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004426 bool IsLeftFold = false, HasInitializer = false;
4427 switch (look()) {
4428 default:
Richard Smithc20d1442018-08-20 20:14:49 +00004429 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004430 case 'L':
4431 IsLeftFold = true;
4432 HasInitializer = true;
4433 break;
4434 case 'R':
4435 HasInitializer = true;
4436 break;
4437 case 'l':
4438 IsLeftFold = true;
4439 break;
4440 case 'r':
4441 break;
4442 }
Richard Smithc20d1442018-08-20 20:14:49 +00004443 ++First;
4444
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004445 const auto *Op = parseOperatorEncoding();
Nathan Sidwellce967252022-02-18 11:06:58 -08004446 if (!Op)
4447 return nullptr;
4448 if (!(Op->getKind() == OperatorInfo::Binary
4449 || (Op->getKind() == OperatorInfo::Member
4450 && Op->getName().back() == '*')))
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004451 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004452
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004453 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004454 if (Pack == nullptr)
4455 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004456
4457 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004458 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004459 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004460 if (Init == nullptr)
4461 return nullptr;
4462 }
4463
4464 if (IsLeftFold && Init)
4465 std::swap(Pack, Init);
4466
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004467 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004468}
4469
Richard Smith1865d2f2020-10-22 19:29:36 -07004470// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4471//
4472// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4473template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004474Node *
4475AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4476 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004477 Node *Ty = getDerived().parseType();
4478 if (!Ty)
4479 return nullptr;
4480 Node *Expr = getDerived().parseExpr();
4481 if (!Expr)
4482 return nullptr;
4483 StringView Offset = getDerived().parseNumber(true);
4484 if (!consumeIf('E'))
4485 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004486 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004487}
4488
4489// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4490// <union-selector> ::= _ [<number>]
4491//
4492// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4493template <typename Derived, typename Alloc>
4494Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4495 Node *Ty = getDerived().parseType();
4496 if (!Ty)
4497 return nullptr;
4498 Node *Expr = getDerived().parseExpr();
4499 if (!Expr)
4500 return nullptr;
4501 StringView Offset = getDerived().parseNumber(true);
4502 size_t SelectorsBegin = Names.size();
4503 while (consumeIf('_')) {
4504 Node *Selector = make<NameType>(parseNumber());
4505 if (!Selector)
4506 return nullptr;
4507 Names.push_back(Selector);
4508 }
4509 bool OnePastTheEnd = consumeIf('p');
4510 if (!consumeIf('E'))
4511 return nullptr;
4512 return make<SubobjectExpr>(
4513 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4514}
4515
Richard Smithc20d1442018-08-20 20:14:49 +00004516// <expression> ::= <unary operator-name> <expression>
4517// ::= <binary operator-name> <expression> <expression>
4518// ::= <ternary operator-name> <expression> <expression> <expression>
4519// ::= cl <expression>+ E # call
4520// ::= cv <type> <expression> # conversion with one argument
4521// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4522// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4523// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4524// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4525// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4526// ::= [gs] dl <expression> # delete expression
4527// ::= [gs] da <expression> # delete[] expression
4528// ::= pp_ <expression> # prefix ++
4529// ::= mm_ <expression> # prefix --
4530// ::= ti <type> # typeid (type)
4531// ::= te <expression> # typeid (expression)
4532// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4533// ::= sc <type> <expression> # static_cast<type> (expression)
4534// ::= cc <type> <expression> # const_cast<type> (expression)
4535// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4536// ::= st <type> # sizeof (a type)
4537// ::= sz <expression> # sizeof (an expression)
4538// ::= at <type> # alignof (a type)
4539// ::= az <expression> # alignof (an expression)
4540// ::= nx <expression> # noexcept (expression)
4541// ::= <template-param>
4542// ::= <function-param>
4543// ::= dt <expression> <unresolved-name> # expr.name
4544// ::= pt <expression> <unresolved-name> # expr->name
4545// ::= ds <expression> <expression> # expr.*expr
4546// ::= sZ <template-param> # size of a parameter pack
4547// ::= sZ <function-param> # size of a function parameter pack
4548// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4549// ::= sp <expression> # pack expansion
4550// ::= tw <expression> # throw expression
4551// ::= tr # throw with no operand (rethrow)
4552// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4553// # freestanding dependent name (e.g., T::x),
4554// # objectless nonstatic member reference
4555// ::= fL <binary-operator-name> <expression> <expression>
4556// ::= fR <binary-operator-name> <expression> <expression>
4557// ::= fl <binary-operator-name> <expression>
4558// ::= fr <binary-operator-name> <expression>
4559// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004560template <typename Derived, typename Alloc>
4561Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004562 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004563
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004564 const auto *Op = parseOperatorEncoding();
4565 if (Op) {
4566 auto Sym = Op->getSymbol();
4567 switch (Op->getKind()) {
4568 case OperatorInfo::Binary:
4569 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004570 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004571 case OperatorInfo::Prefix:
4572 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004573 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004574 case OperatorInfo::Postfix: {
4575 // Postfix unary operator: expr @
4576 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004577 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004578 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004579 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004580 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004581 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004582 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004583 case OperatorInfo::Array: {
4584 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004585 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004586 if (Base == nullptr)
4587 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004588 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004589 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004590 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004591 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004592 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004593 case OperatorInfo::Member: {
4594 // Member access lhs @ rhs
4595 Node *LHS = getDerived().parseExpr();
4596 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004597 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004598 Node *RHS = getDerived().parseExpr();
4599 if (RHS == nullptr)
4600 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004601 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004602 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004603 case OperatorInfo::New: {
4604 // New
4605 // # new (expr-list) type [(init)]
4606 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4607 // # new[] (expr-list) type [(init)]
4608 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004609 size_t Exprs = Names.size();
4610 while (!consumeIf('_')) {
4611 Node *Ex = getDerived().parseExpr();
4612 if (Ex == nullptr)
4613 return nullptr;
4614 Names.push_back(Ex);
4615 }
4616 NodeArray ExprList = popTrailingNodeArray(Exprs);
4617 Node *Ty = getDerived().parseType();
4618 if (Ty == nullptr)
4619 return nullptr;
4620 bool HaveInits = consumeIf("pi");
4621 size_t InitsBegin = Names.size();
4622 while (!consumeIf('E')) {
4623 if (!HaveInits)
4624 return nullptr;
4625 Node *Init = getDerived().parseExpr();
4626 if (Init == nullptr)
4627 return Init;
4628 Names.push_back(Init);
4629 }
4630 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004631 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004632 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004633 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004634 case OperatorInfo::Del: {
4635 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004636 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004637 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004638 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004639 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4640 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004641 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004642 case OperatorInfo::Call: {
4643 // Function Call
4644 Node *Callee = getDerived().parseExpr();
4645 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004646 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004647 size_t ExprsBegin = Names.size();
4648 while (!consumeIf('E')) {
4649 Node *E = getDerived().parseExpr();
4650 if (E == nullptr)
4651 return nullptr;
4652 Names.push_back(E);
4653 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004654 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4655 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004656 }
4657 case OperatorInfo::CCast: {
4658 // C Cast: (type)expr
4659 Node *Ty;
4660 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004661 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004662 Ty = getDerived().parseType();
4663 }
4664 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004665 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004666
4667 size_t ExprsBegin = Names.size();
4668 bool IsMany = consumeIf('_');
4669 while (!consumeIf('E')) {
4670 Node *E = getDerived().parseExpr();
4671 if (E == nullptr)
4672 return E;
4673 Names.push_back(E);
4674 if (!IsMany)
4675 break;
4676 }
4677 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4678 if (!IsMany && Exprs.size() != 1)
4679 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004680 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004681 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004682 case OperatorInfo::Conditional: {
4683 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004684 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004685 if (Cond == nullptr)
4686 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004687 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004688 if (LHS == nullptr)
4689 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004690 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004691 if (RHS == nullptr)
4692 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004693 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004694 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004695 case OperatorInfo::NamedCast: {
4696 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004697 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004698 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004699 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004700 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004701 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004702 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004703 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004704 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004705 case OperatorInfo::OfIdOp: {
4706 // [sizeof/alignof/typeid] ( <type>|<expr> )
4707 Node *Arg =
4708 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4709 if (!Arg)
4710 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004711 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004712 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004713 case OperatorInfo::NameOnly: {
4714 // Not valid as an expression operand.
4715 return nullptr;
4716 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004717 }
4718 DEMANGLE_UNREACHABLE;
4719 }
4720
4721 if (numLeft() < 2)
4722 return nullptr;
4723
4724 if (look() == 'L')
4725 return getDerived().parseExprPrimary();
4726 if (look() == 'T')
4727 return getDerived().parseTemplateParam();
4728 if (look() == 'f') {
4729 // Disambiguate a fold expression from a <function-param>.
4730 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4731 return getDerived().parseFunctionParam();
4732 return getDerived().parseFoldExpr();
4733 }
4734 if (consumeIf("il")) {
4735 size_t InitsBegin = Names.size();
4736 while (!consumeIf('E')) {
4737 Node *E = getDerived().parseBracedExpr();
4738 if (E == nullptr)
4739 return nullptr;
4740 Names.push_back(E);
4741 }
4742 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4743 }
4744 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004745 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004746 if (consumeIf("nx")) {
4747 Node *Ex = getDerived().parseExpr();
4748 if (Ex == nullptr)
4749 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004750 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004751 }
4752 if (consumeIf("so"))
4753 return parseSubobjectExpr();
4754 if (consumeIf("sp")) {
4755 Node *Child = getDerived().parseExpr();
4756 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004757 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004758 return make<ParameterPackExpansion>(Child);
4759 }
4760 if (consumeIf("sZ")) {
4761 if (look() == 'T') {
4762 Node *R = getDerived().parseTemplateParam();
4763 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004764 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004765 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004766 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004767 Node *FP = getDerived().parseFunctionParam();
4768 if (FP == nullptr)
4769 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004770 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004771 }
4772 if (consumeIf("sP")) {
4773 size_t ArgsBegin = Names.size();
4774 while (!consumeIf('E')) {
4775 Node *Arg = getDerived().parseTemplateArg();
4776 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004777 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004778 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004779 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004780 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4781 if (!Pack)
4782 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004783 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004784 }
4785 if (consumeIf("tl")) {
4786 Node *Ty = getDerived().parseType();
4787 if (Ty == nullptr)
4788 return nullptr;
4789 size_t InitsBegin = Names.size();
4790 while (!consumeIf('E')) {
4791 Node *E = getDerived().parseBracedExpr();
4792 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004793 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004794 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004795 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004796 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4797 }
4798 if (consumeIf("tr"))
4799 return make<NameType>("throw");
4800 if (consumeIf("tw")) {
4801 Node *Ex = getDerived().parseExpr();
4802 if (Ex == nullptr)
4803 return nullptr;
4804 return make<ThrowExpr>(Ex);
4805 }
4806 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004807 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4808 if (!Name)
4809 return nullptr;
4810 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4811 // standard encoding expects a <template-arg>, and would be otherwise be
4812 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4813 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4814 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004815 bool IsUUID = false;
4816 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004817 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004818 if (consumeIf('t')) {
4819 UUID = getDerived().parseType();
4820 IsUUID = true;
4821 } else if (consumeIf('z')) {
4822 UUID = getDerived().parseExpr();
4823 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004824 }
4825 }
4826 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004827 if (IsUUID) {
4828 if (UUID == nullptr)
4829 return nullptr;
4830 Names.push_back(UUID);
4831 } else {
4832 while (!consumeIf('E')) {
4833 Node *E = getDerived().parseTemplateArg();
4834 if (E == nullptr)
4835 return E;
4836 Names.push_back(E);
4837 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004838 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004839 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4840 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004841 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004842
4843 // Only unresolved names remain.
4844 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004845}
4846
4847// <call-offset> ::= h <nv-offset> _
4848// ::= v <v-offset> _
4849//
4850// <nv-offset> ::= <offset number>
4851// # non-virtual base override
4852//
4853// <v-offset> ::= <offset number> _ <virtual offset number>
4854// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004855template <typename Alloc, typename Derived>
4856bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004857 // Just scan through the call offset, we never add this information into the
4858 // output.
4859 if (consumeIf('h'))
4860 return parseNumber(true).empty() || !consumeIf('_');
4861 if (consumeIf('v'))
4862 return parseNumber(true).empty() || !consumeIf('_') ||
4863 parseNumber(true).empty() || !consumeIf('_');
4864 return true;
4865}
4866
4867// <special-name> ::= TV <type> # virtual table
4868// ::= TT <type> # VTT structure (construction vtable index)
4869// ::= TI <type> # typeinfo structure
4870// ::= TS <type> # typeinfo name (null-terminated byte string)
4871// ::= Tc <call-offset> <call-offset> <base encoding>
4872// # base is the nominal target function of thunk
4873// # first call-offset is 'this' adjustment
4874// # second call-offset is result adjustment
4875// ::= T <call-offset> <base encoding>
4876// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004877// # Guard variable for one-time initialization
4878// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004879// # No <type>
4880// ::= TW <object name> # Thread-local wrapper
4881// ::= TH <object name> # Thread-local initialization
4882// ::= GR <object name> _ # First temporary
4883// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004884// # construction vtable for second-in-first
4885// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004886// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004887// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004888template <typename Derived, typename Alloc>
4889Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004890 switch (look()) {
4891 case 'T':
4892 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004893 // TA <template-arg> # template parameter object
4894 //
4895 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4896 case 'A': {
4897 First += 2;
4898 Node *Arg = getDerived().parseTemplateArg();
4899 if (Arg == nullptr)
4900 return nullptr;
4901 return make<SpecialName>("template parameter object for ", Arg);
4902 }
Richard Smithc20d1442018-08-20 20:14:49 +00004903 // TV <type> # virtual table
4904 case 'V': {
4905 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004906 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004907 if (Ty == nullptr)
4908 return nullptr;
4909 return make<SpecialName>("vtable for ", Ty);
4910 }
4911 // TT <type> # VTT structure (construction vtable index)
4912 case 'T': {
4913 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004914 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004915 if (Ty == nullptr)
4916 return nullptr;
4917 return make<SpecialName>("VTT for ", Ty);
4918 }
4919 // TI <type> # typeinfo structure
4920 case 'I': {
4921 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004922 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004923 if (Ty == nullptr)
4924 return nullptr;
4925 return make<SpecialName>("typeinfo for ", Ty);
4926 }
4927 // TS <type> # typeinfo name (null-terminated byte string)
4928 case 'S': {
4929 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004930 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004931 if (Ty == nullptr)
4932 return nullptr;
4933 return make<SpecialName>("typeinfo name for ", Ty);
4934 }
4935 // Tc <call-offset> <call-offset> <base encoding>
4936 case 'c': {
4937 First += 2;
4938 if (parseCallOffset() || parseCallOffset())
4939 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004940 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004941 if (Encoding == nullptr)
4942 return nullptr;
4943 return make<SpecialName>("covariant return thunk to ", Encoding);
4944 }
4945 // extension ::= TC <first type> <number> _ <second type>
4946 // # construction vtable for second-in-first
4947 case 'C': {
4948 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004949 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004950 if (FirstType == nullptr)
4951 return nullptr;
4952 if (parseNumber(true).empty() || !consumeIf('_'))
4953 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004954 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004955 if (SecondType == nullptr)
4956 return nullptr;
4957 return make<CtorVtableSpecialName>(SecondType, FirstType);
4958 }
4959 // TW <object name> # Thread-local wrapper
4960 case 'W': {
4961 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004962 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004963 if (Name == nullptr)
4964 return nullptr;
4965 return make<SpecialName>("thread-local wrapper routine for ", Name);
4966 }
4967 // TH <object name> # Thread-local initialization
4968 case 'H': {
4969 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004970 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004971 if (Name == nullptr)
4972 return nullptr;
4973 return make<SpecialName>("thread-local initialization routine for ", Name);
4974 }
4975 // T <call-offset> <base encoding>
4976 default: {
4977 ++First;
4978 bool IsVirt = look() == 'v';
4979 if (parseCallOffset())
4980 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004981 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004982 if (BaseEncoding == nullptr)
4983 return nullptr;
4984 if (IsVirt)
4985 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4986 else
4987 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4988 }
4989 }
4990 case 'G':
4991 switch (look(1)) {
4992 // GV <object name> # Guard variable for one-time initialization
4993 case 'V': {
4994 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004995 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004996 if (Name == nullptr)
4997 return nullptr;
4998 return make<SpecialName>("guard variable for ", Name);
4999 }
5000 // GR <object name> # reference temporary for object
5001 // GR <object name> _ # First temporary
5002 // GR <object name> <seq-id> _ # Subsequent temporaries
5003 case 'R': {
5004 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005005 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005006 if (Name == nullptr)
5007 return nullptr;
5008 size_t Count;
5009 bool ParsedSeqId = !parseSeqId(&Count);
5010 if (!consumeIf('_') && ParsedSeqId)
5011 return nullptr;
5012 return make<SpecialName>("reference temporary for ", Name);
5013 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08005014 // GI <module-name> v
5015 case 'I': {
5016 First += 2;
5017 ModuleName *Module = nullptr;
5018 if (getDerived().parseModuleNameOpt(Module))
5019 return nullptr;
5020 if (Module == nullptr)
5021 return nullptr;
5022 return make<SpecialName>("initializer for module ", Module);
5023 }
Richard Smithc20d1442018-08-20 20:14:49 +00005024 }
5025 }
5026 return nullptr;
5027}
5028
5029// <encoding> ::= <function name> <bare-function-type>
5030// ::= <data name>
5031// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005032template <typename Derived, typename Alloc>
5033Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005034 // The template parameters of an encoding are unrelated to those of the
5035 // enclosing context.
5036 class SaveTemplateParams {
5037 AbstractManglingParser *Parser;
5038 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005039 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005040
5041 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005042 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005043 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005044 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005045 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005046 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005047 }
5048 ~SaveTemplateParams() {
5049 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005050 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005051 }
5052 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005053
Richard Smithc20d1442018-08-20 20:14:49 +00005054 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005055 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005056
5057 auto IsEndOfEncoding = [&] {
5058 // The set of chars that can potentially follow an <encoding> (none of which
5059 // can start a <type>). Enumerating these allows us to avoid speculative
5060 // parsing.
5061 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5062 };
5063
5064 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005065 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005066 if (Name == nullptr)
5067 return nullptr;
5068
5069 if (resolveForwardTemplateRefs(NameInfo))
5070 return nullptr;
5071
5072 if (IsEndOfEncoding())
5073 return Name;
5074
5075 Node *Attrs = nullptr;
5076 if (consumeIf("Ua9enable_ifI")) {
5077 size_t BeforeArgs = Names.size();
5078 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005079 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005080 if (Arg == nullptr)
5081 return nullptr;
5082 Names.push_back(Arg);
5083 }
5084 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005085 if (!Attrs)
5086 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005087 }
5088
5089 Node *ReturnType = nullptr;
5090 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005091 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005092 if (ReturnType == nullptr)
5093 return nullptr;
5094 }
5095
5096 if (consumeIf('v'))
5097 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5098 Attrs, NameInfo.CVQualifiers,
5099 NameInfo.ReferenceQualifier);
5100
5101 size_t ParamsBegin = Names.size();
5102 do {
Pavel Labathba825192018-10-16 14:29:14 +00005103 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005104 if (Ty == nullptr)
5105 return nullptr;
5106 Names.push_back(Ty);
5107 } while (!IsEndOfEncoding());
5108
5109 return make<FunctionEncoding>(ReturnType, Name,
5110 popTrailingNodeArray(ParamsBegin),
5111 Attrs, NameInfo.CVQualifiers,
5112 NameInfo.ReferenceQualifier);
5113}
5114
5115template <class Float>
5116struct FloatData;
5117
5118template <>
5119struct FloatData<float>
5120{
5121 static const size_t mangled_size = 8;
5122 static const size_t max_demangled_size = 24;
5123 static constexpr const char* spec = "%af";
5124};
5125
5126template <>
5127struct FloatData<double>
5128{
5129 static const size_t mangled_size = 16;
5130 static const size_t max_demangled_size = 32;
5131 static constexpr const char* spec = "%a";
5132};
5133
5134template <>
5135struct FloatData<long double>
5136{
5137#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5138 defined(__wasm__)
5139 static const size_t mangled_size = 32;
5140#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5141 static const size_t mangled_size = 16;
5142#else
5143 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5144#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005145 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5146 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5147 // Negatives are one character longer than positives.
5148 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5149 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5150 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005151 static constexpr const char *spec = "%LaL";
5152};
5153
Pavel Labathba825192018-10-16 14:29:14 +00005154template <typename Alloc, typename Derived>
5155template <class Float>
5156Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005157 const size_t N = FloatData<Float>::mangled_size;
5158 if (numLeft() <= N)
5159 return nullptr;
5160 StringView Data(First, First + N);
5161 for (char C : Data)
5162 if (!std::isxdigit(C))
5163 return nullptr;
5164 First += N;
5165 if (!consumeIf('E'))
5166 return nullptr;
5167 return make<FloatLiteralImpl<Float>>(Data);
5168}
5169
5170// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005171template <typename Alloc, typename Derived>
5172bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005173 if (!(look() >= '0' && look() <= '9') &&
5174 !(look() >= 'A' && look() <= 'Z'))
5175 return true;
5176
5177 size_t Id = 0;
5178 while (true) {
5179 if (look() >= '0' && look() <= '9') {
5180 Id *= 36;
5181 Id += static_cast<size_t>(look() - '0');
5182 } else if (look() >= 'A' && look() <= 'Z') {
5183 Id *= 36;
5184 Id += static_cast<size_t>(look() - 'A') + 10;
5185 } else {
5186 *Out = Id;
5187 return false;
5188 }
5189 ++First;
5190 }
5191}
5192
5193// <substitution> ::= S <seq-id> _
5194// ::= S_
5195// <substitution> ::= Sa # ::std::allocator
5196// <substitution> ::= Sb # ::std::basic_string
5197// <substitution> ::= Ss # ::std::basic_string < char,
5198// ::std::char_traits<char>,
5199// ::std::allocator<char> >
5200// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5201// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5202// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005203// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005204template <typename Derived, typename Alloc>
5205Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005206 if (!consumeIf('S'))
5207 return nullptr;
5208
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005209 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005210 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005211 switch (look()) {
5212 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005213 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005214 break;
5215 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005216 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005217 break;
5218 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005219 Kind = SpecialSubKind::iostream;
5220 break;
5221 case 'i':
5222 Kind = SpecialSubKind::istream;
5223 break;
5224 case 'o':
5225 Kind = SpecialSubKind::ostream;
5226 break;
5227 case 's':
5228 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005229 break;
5230 default:
5231 return nullptr;
5232 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005233 ++First;
5234 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005235 if (!SpecialSub)
5236 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005237
Richard Smithc20d1442018-08-20 20:14:49 +00005238 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5239 // has ABI tags, the tags are appended to the substitution; the result is a
5240 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005241 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005242 if (WithTags != SpecialSub) {
5243 Subs.push_back(WithTags);
5244 SpecialSub = WithTags;
5245 }
5246 return SpecialSub;
5247 }
5248
5249 // ::= S_
5250 if (consumeIf('_')) {
5251 if (Subs.empty())
5252 return nullptr;
5253 return Subs[0];
5254 }
5255
5256 // ::= S <seq-id> _
5257 size_t Index = 0;
5258 if (parseSeqId(&Index))
5259 return nullptr;
5260 ++Index;
5261 if (!consumeIf('_') || Index >= Subs.size())
5262 return nullptr;
5263 return Subs[Index];
5264}
5265
5266// <template-param> ::= T_ # first template parameter
5267// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005268// ::= TL <level-1> __
5269// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005270template <typename Derived, typename Alloc>
5271Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005272 if (!consumeIf('T'))
5273 return nullptr;
5274
Richard Smithdf1c14c2019-09-06 23:53:21 +00005275 size_t Level = 0;
5276 if (consumeIf('L')) {
5277 if (parsePositiveInteger(&Level))
5278 return nullptr;
5279 ++Level;
5280 if (!consumeIf('_'))
5281 return nullptr;
5282 }
5283
Richard Smithc20d1442018-08-20 20:14:49 +00005284 size_t Index = 0;
5285 if (!consumeIf('_')) {
5286 if (parsePositiveInteger(&Index))
5287 return nullptr;
5288 ++Index;
5289 if (!consumeIf('_'))
5290 return nullptr;
5291 }
5292
Richard Smithc20d1442018-08-20 20:14:49 +00005293 // If we're in a context where this <template-param> refers to a
5294 // <template-arg> further ahead in the mangled name (currently just conversion
5295 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005296 // This can only happen at the outermost level.
5297 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005298 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5299 if (!ForwardRef)
5300 return nullptr;
5301 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5302 ForwardTemplateRefs.push_back(
5303 static_cast<ForwardTemplateReference *>(ForwardRef));
5304 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005305 }
5306
Richard Smithdf1c14c2019-09-06 23:53:21 +00005307 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5308 Index >= TemplateParams[Level]->size()) {
5309 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5310 // list are mangled as the corresponding artificial template type parameter.
5311 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5312 // This will be popped by the ScopedTemplateParamList in
5313 // parseUnnamedTypeName.
5314 if (Level == TemplateParams.size())
5315 TemplateParams.push_back(nullptr);
5316 return make<NameType>("auto");
5317 }
5318
Richard Smithc20d1442018-08-20 20:14:49 +00005319 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005320 }
5321
5322 return (*TemplateParams[Level])[Index];
5323}
5324
5325// <template-param-decl> ::= Ty # type parameter
5326// ::= Tn <type> # non-type parameter
5327// ::= Tt <template-param-decl>* E # template parameter
5328// ::= Tp <template-param-decl> # parameter pack
5329template <typename Derived, typename Alloc>
5330Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5331 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5332 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5333 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5334 if (N) TemplateParams.back()->push_back(N);
5335 return N;
5336 };
5337
5338 if (consumeIf("Ty")) {
5339 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5340 if (!Name)
5341 return nullptr;
5342 return make<TypeTemplateParamDecl>(Name);
5343 }
5344
5345 if (consumeIf("Tn")) {
5346 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5347 if (!Name)
5348 return nullptr;
5349 Node *Type = parseType();
5350 if (!Type)
5351 return nullptr;
5352 return make<NonTypeTemplateParamDecl>(Name, Type);
5353 }
5354
5355 if (consumeIf("Tt")) {
5356 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5357 if (!Name)
5358 return nullptr;
5359 size_t ParamsBegin = Names.size();
5360 ScopedTemplateParamList TemplateTemplateParamParams(this);
5361 while (!consumeIf("E")) {
5362 Node *P = parseTemplateParamDecl();
5363 if (!P)
5364 return nullptr;
5365 Names.push_back(P);
5366 }
5367 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5368 return make<TemplateTemplateParamDecl>(Name, Params);
5369 }
5370
5371 if (consumeIf("Tp")) {
5372 Node *P = parseTemplateParamDecl();
5373 if (!P)
5374 return nullptr;
5375 return make<TemplateParamPackDecl>(P);
5376 }
5377
5378 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005379}
5380
5381// <template-arg> ::= <type> # type or template
5382// ::= X <expression> E # expression
5383// ::= <expr-primary> # simple expressions
5384// ::= J <template-arg>* E # argument pack
5385// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005386template <typename Derived, typename Alloc>
5387Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005388 switch (look()) {
5389 case 'X': {
5390 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005391 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005392 if (Arg == nullptr || !consumeIf('E'))
5393 return nullptr;
5394 return Arg;
5395 }
5396 case 'J': {
5397 ++First;
5398 size_t ArgsBegin = Names.size();
5399 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005400 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005401 if (Arg == nullptr)
5402 return nullptr;
5403 Names.push_back(Arg);
5404 }
5405 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5406 return make<TemplateArgumentPack>(Args);
5407 }
5408 case 'L': {
5409 // ::= LZ <encoding> E # extension
5410 if (look(1) == 'Z') {
5411 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005412 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005413 if (Arg == nullptr || !consumeIf('E'))
5414 return nullptr;
5415 return Arg;
5416 }
5417 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005418 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005419 }
5420 default:
Pavel Labathba825192018-10-16 14:29:14 +00005421 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005422 }
5423}
5424
5425// <template-args> ::= I <template-arg>* E
5426// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005427template <typename Derived, typename Alloc>
5428Node *
5429AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005430 if (!consumeIf('I'))
5431 return nullptr;
5432
5433 // <template-params> refer to the innermost <template-args>. Clear out any
5434 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005435 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005436 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005437 TemplateParams.push_back(&OuterTemplateParams);
5438 OuterTemplateParams.clear();
5439 }
Richard Smithc20d1442018-08-20 20:14:49 +00005440
5441 size_t ArgsBegin = Names.size();
5442 while (!consumeIf('E')) {
5443 if (TagTemplates) {
5444 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005445 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005446 TemplateParams = std::move(OldParams);
5447 if (Arg == nullptr)
5448 return nullptr;
5449 Names.push_back(Arg);
5450 Node *TableEntry = Arg;
5451 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5452 TableEntry = make<ParameterPack>(
5453 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005454 if (!TableEntry)
5455 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005456 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005457 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005458 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005459 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005460 if (Arg == nullptr)
5461 return nullptr;
5462 Names.push_back(Arg);
5463 }
5464 }
5465 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5466}
5467
5468// <mangled-name> ::= _Z <encoding>
5469// ::= <type>
5470// extension ::= ___Z <encoding> _block_invoke
5471// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5472// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005473template <typename Derived, typename Alloc>
5474Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005475 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005476 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005477 if (Encoding == nullptr)
5478 return nullptr;
5479 if (look() == '.') {
5480 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5481 First = Last;
5482 }
5483 if (numLeft() != 0)
5484 return nullptr;
5485 return Encoding;
5486 }
5487
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005488 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005489 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005490 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5491 return nullptr;
5492 bool RequireNumber = consumeIf('_');
5493 if (parseNumber().empty() && RequireNumber)
5494 return nullptr;
5495 if (look() == '.')
5496 First = Last;
5497 if (numLeft() != 0)
5498 return nullptr;
5499 return make<SpecialName>("invocation function for block in ", Encoding);
5500 }
5501
Pavel Labathba825192018-10-16 14:29:14 +00005502 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005503 if (numLeft() != 0)
5504 return nullptr;
5505 return Ty;
5506}
5507
Pavel Labathba825192018-10-16 14:29:14 +00005508template <typename Alloc>
5509struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5510 using AbstractManglingParser<ManglingParser<Alloc>,
5511 Alloc>::AbstractManglingParser;
5512};
5513
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005514DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005515
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005516#endif // DEMANGLE_ITANIUMDEMANGLE_H