blob: beece93b21d41b6dbf137c81b55dc8c967132136 [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
Nathan Sidwell28201492022-03-28 12:55:45 -07001509class SpecialSubstitution;
1510class ExpandedSpecialSubstitution : public Node {
1511protected:
Richard Smithc20d1442018-08-20 20:14:49 +00001512 SpecialSubKind SSK;
1513
Nathan Sidwell28201492022-03-28 12:55:45 -07001514 ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)
1515 : Node(K_), SSK(SSK_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001516public:
1517 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
Nathan Sidwell28201492022-03-28 12:55:45 -07001518 : ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}
1519 inline ExpandedSpecialSubstitution(SpecialSubstitution const *);
Richard Smithc20d1442018-08-20 20:14:49 +00001520
1521 template<typename Fn> void match(Fn F) const { F(SSK); }
1522
Nathan Sidwell28201492022-03-28 12:55:45 -07001523protected:
1524 bool isInstantiation() const {
1525 return unsigned(SSK) >= unsigned(SpecialSubKind::string);
1526 }
1527
Richard Smithc20d1442018-08-20 20:14:49 +00001528 StringView getBaseName() const override {
1529 switch (SSK) {
1530 case SpecialSubKind::allocator:
1531 return StringView("allocator");
1532 case SpecialSubKind::basic_string:
1533 return StringView("basic_string");
1534 case SpecialSubKind::string:
1535 return StringView("basic_string");
1536 case SpecialSubKind::istream:
1537 return StringView("basic_istream");
1538 case SpecialSubKind::ostream:
1539 return StringView("basic_ostream");
1540 case SpecialSubKind::iostream:
1541 return StringView("basic_iostream");
1542 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001543 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001544 }
1545
Nathan Sidwell28201492022-03-28 12:55:45 -07001546private:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001547 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell28201492022-03-28 12:55:45 -07001548 OB << "std::" << getBaseName();
1549 if (isInstantiation()) {
1550 OB << "<char, std::char_traits<char>";
1551 if (SSK == SpecialSubKind::string)
1552 OB << ", std::allocator<char>";
1553 OB << ">";
Richard Smithc20d1442018-08-20 20:14:49 +00001554 }
1555 }
1556};
1557
Nathan Sidwell28201492022-03-28 12:55:45 -07001558class SpecialSubstitution final : public ExpandedSpecialSubstitution {
Richard Smithc20d1442018-08-20 20:14:49 +00001559public:
Richard Smithc20d1442018-08-20 20:14:49 +00001560 SpecialSubstitution(SpecialSubKind SSK_)
Nathan Sidwell28201492022-03-28 12:55:45 -07001561 : ExpandedSpecialSubstitution(SSK_, KSpecialSubstitution) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001562
1563 template<typename Fn> void match(Fn F) const { F(SSK); }
1564
1565 StringView getBaseName() const override {
Nathan Sidwell28201492022-03-28 12:55:45 -07001566 auto SV = ExpandedSpecialSubstitution::getBaseName ();
1567 if (isInstantiation()) {
1568 // The instantiations are typedefs that drop the "basic_" prefix.
1569 assert(SV.startsWith("basic_"));
1570 SV = SV.dropFront(sizeof("basic_") - 1);
Richard Smithc20d1442018-08-20 20:14:49 +00001571 }
Nathan Sidwell28201492022-03-28 12:55:45 -07001572 return SV;
Richard Smithc20d1442018-08-20 20:14:49 +00001573 }
1574
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001575 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell28201492022-03-28 12:55:45 -07001576 OB << "std::" << getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001577 }
1578};
1579
Nathan Sidwell28201492022-03-28 12:55:45 -07001580inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(
1581 SpecialSubstitution const *SS)
1582 : ExpandedSpecialSubstitution(SS->SSK) {}
1583
Richard Smithc20d1442018-08-20 20:14:49 +00001584class CtorDtorName final : public Node {
1585 const Node *Basename;
1586 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001587 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001588
1589public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001590 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1591 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1592 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001593
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001594 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001595
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001596 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001597 if (IsDtor)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001598 OB += "~";
1599 OB += Basename->getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001600 }
1601};
1602
1603class DtorName : public Node {
1604 const Node *Base;
1605
1606public:
1607 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1608
1609 template<typename Fn> void match(Fn F) const { F(Base); }
1610
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001611 void printLeft(OutputBuffer &OB) const override {
1612 OB += "~";
1613 Base->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001614 }
1615};
1616
1617class UnnamedTypeName : public Node {
1618 const StringView Count;
1619
1620public:
1621 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1622
1623 template<typename Fn> void match(Fn F) const { F(Count); }
1624
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001625 void printLeft(OutputBuffer &OB) const override {
1626 OB += "'unnamed";
1627 OB += Count;
1628 OB += "\'";
Richard Smithc20d1442018-08-20 20:14:49 +00001629 }
1630};
1631
1632class ClosureTypeName : public Node {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001633 NodeArray TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00001634 NodeArray Params;
1635 StringView Count;
1636
1637public:
Richard Smithdf1c14c2019-09-06 23:53:21 +00001638 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1639 StringView Count_)
1640 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1641 Params(Params_), Count(Count_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001642
Richard Smithdf1c14c2019-09-06 23:53:21 +00001643 template<typename Fn> void match(Fn F) const {
1644 F(TemplateParams, Params, Count);
1645 }
1646
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001647 void printDeclarator(OutputBuffer &OB) const {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001648 if (!TemplateParams.empty()) {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001649 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001650 OB += "<";
1651 TemplateParams.printWithComma(OB);
1652 OB += ">";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001653 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001654 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001655 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001656 OB.printClose();
Richard Smithdf1c14c2019-09-06 23:53:21 +00001657 }
Richard Smithc20d1442018-08-20 20:14:49 +00001658
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001659 void printLeft(OutputBuffer &OB) const override {
1660 OB += "\'lambda";
1661 OB += Count;
1662 OB += "\'";
1663 printDeclarator(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001664 }
1665};
1666
1667class StructuredBindingName : public Node {
1668 NodeArray Bindings;
1669public:
1670 StructuredBindingName(NodeArray Bindings_)
1671 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1672
1673 template<typename Fn> void match(Fn F) const { F(Bindings); }
1674
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001675 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001676 OB.printOpen('[');
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001677 Bindings.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001678 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001679 }
1680};
1681
1682// -- Expression Nodes --
1683
1684class BinaryExpr : public Node {
1685 const Node *LHS;
1686 const StringView InfixOperator;
1687 const Node *RHS;
1688
1689public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001690 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
1691 Prec Prec_)
1692 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
1693 RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001694
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001695 template <typename Fn> void match(Fn F) const {
1696 F(LHS, InfixOperator, RHS, getPrecedence());
1697 }
Richard Smithc20d1442018-08-20 20:14:49 +00001698
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001699 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell18505102022-03-25 04:34:19 -07001700 bool ParenAll = OB.isGtInsideTemplateArgs() &&
1701 (InfixOperator == ">" || InfixOperator == ">>");
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001702 if (ParenAll)
1703 OB.printOpen();
1704 // Assignment is right associative, with special LHS precedence.
1705 bool IsAssign = getPrecedence() == Prec::Assign;
1706 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1707 // No space before comma operator
1708 if (!(InfixOperator == ","))
1709 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001710 OB += InfixOperator;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001711 OB += " ";
1712 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1713 if (ParenAll)
1714 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001715 }
1716};
1717
1718class ArraySubscriptExpr : public Node {
1719 const Node *Op1;
1720 const Node *Op2;
1721
1722public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001723 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1724 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001725
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001726 template <typename Fn> void match(Fn F) const {
1727 F(Op1, Op2, getPrecedence());
1728 }
Richard Smithc20d1442018-08-20 20:14:49 +00001729
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001730 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001731 Op1->printAsOperand(OB, getPrecedence());
1732 OB.printOpen('[');
1733 Op2->printAsOperand(OB);
1734 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001735 }
1736};
1737
1738class PostfixExpr : public Node {
1739 const Node *Child;
1740 const StringView Operator;
1741
1742public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001743 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
1744 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001745
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001746 template <typename Fn> void match(Fn F) const {
1747 F(Child, Operator, getPrecedence());
1748 }
Richard Smithc20d1442018-08-20 20:14:49 +00001749
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001750 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001751 Child->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001752 OB += Operator;
Richard Smithc20d1442018-08-20 20:14:49 +00001753 }
1754};
1755
1756class ConditionalExpr : public Node {
1757 const Node *Cond;
1758 const Node *Then;
1759 const Node *Else;
1760
1761public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001762 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1763 Prec Prec_)
1764 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001765
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001766 template <typename Fn> void match(Fn F) const {
1767 F(Cond, Then, Else, getPrecedence());
1768 }
Richard Smithc20d1442018-08-20 20:14:49 +00001769
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001770 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001771 Cond->printAsOperand(OB, getPrecedence());
1772 OB += " ? ";
1773 Then->printAsOperand(OB);
1774 OB += " : ";
1775 Else->printAsOperand(OB, Prec::Assign, true);
Richard Smithc20d1442018-08-20 20:14:49 +00001776 }
1777};
1778
1779class MemberExpr : public Node {
1780 const Node *LHS;
1781 const StringView Kind;
1782 const Node *RHS;
1783
1784public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001785 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
1786 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001787
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001788 template <typename Fn> void match(Fn F) const {
1789 F(LHS, Kind, RHS, getPrecedence());
1790 }
Richard Smithc20d1442018-08-20 20:14:49 +00001791
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001792 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001793 LHS->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001794 OB += Kind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001795 RHS->printAsOperand(OB, getPrecedence(), false);
Richard Smithc20d1442018-08-20 20:14:49 +00001796 }
1797};
1798
Richard Smith1865d2f2020-10-22 19:29:36 -07001799class SubobjectExpr : public Node {
1800 const Node *Type;
1801 const Node *SubExpr;
1802 StringView Offset;
1803 NodeArray UnionSelectors;
1804 bool OnePastTheEnd;
1805
1806public:
1807 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1808 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1809 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1810 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1811
1812 template<typename Fn> void match(Fn F) const {
1813 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1814 }
1815
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001816 void printLeft(OutputBuffer &OB) const override {
1817 SubExpr->print(OB);
1818 OB += ".<";
1819 Type->print(OB);
1820 OB += " at offset ";
Richard Smith1865d2f2020-10-22 19:29:36 -07001821 if (Offset.empty()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001822 OB += "0";
Richard Smith1865d2f2020-10-22 19:29:36 -07001823 } else if (Offset[0] == 'n') {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001824 OB += "-";
1825 OB += Offset.dropFront();
Richard Smith1865d2f2020-10-22 19:29:36 -07001826 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001827 OB += Offset;
Richard Smith1865d2f2020-10-22 19:29:36 -07001828 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001829 OB += ">";
Richard Smith1865d2f2020-10-22 19:29:36 -07001830 }
1831};
1832
Richard Smithc20d1442018-08-20 20:14:49 +00001833class EnclosingExpr : public Node {
1834 const StringView Prefix;
1835 const Node *Infix;
1836 const StringView Postfix;
1837
1838public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001839 EnclosingExpr(StringView Prefix_, const Node *Infix_,
1840 Prec Prec_ = Prec::Primary)
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001841 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001842
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001843 template <typename Fn> void match(Fn F) const {
1844 F(Prefix, Infix, getPrecedence());
1845 }
Richard Smithc20d1442018-08-20 20:14:49 +00001846
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001847 void printLeft(OutputBuffer &OB) const override {
1848 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001849 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001850 Infix->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001851 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001852 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +00001853 }
1854};
1855
1856class CastExpr : public Node {
1857 // cast_kind<to>(from)
1858 const StringView CastKind;
1859 const Node *To;
1860 const Node *From;
1861
1862public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001863 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
1864 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001865
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001866 template <typename Fn> void match(Fn F) const {
1867 F(CastKind, To, From, getPrecedence());
1868 }
Richard Smithc20d1442018-08-20 20:14:49 +00001869
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001870 void printLeft(OutputBuffer &OB) const override {
1871 OB += CastKind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001872 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001873 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001874 OB += "<";
1875 To->printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001876 OB += ">";
1877 }
1878 OB.printOpen();
1879 From->printAsOperand(OB);
1880 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001881 }
1882};
1883
1884class SizeofParamPackExpr : public Node {
1885 const Node *Pack;
1886
1887public:
1888 SizeofParamPackExpr(const Node *Pack_)
1889 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1890
1891 template<typename Fn> void match(Fn F) const { F(Pack); }
1892
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001893 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001894 OB += "sizeof...";
1895 OB.printOpen();
Richard Smithc20d1442018-08-20 20:14:49 +00001896 ParameterPackExpansion PPE(Pack);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001897 PPE.printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001898 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001899 }
1900};
1901
1902class CallExpr : public Node {
1903 const Node *Callee;
1904 NodeArray Args;
1905
1906public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001907 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
1908 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001909
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001910 template <typename Fn> void match(Fn F) const {
1911 F(Callee, Args, getPrecedence());
1912 }
Richard Smithc20d1442018-08-20 20:14:49 +00001913
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001914 void printLeft(OutputBuffer &OB) const override {
1915 Callee->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001916 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001917 Args.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001918 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001919 }
1920};
1921
1922class NewExpr : public Node {
1923 // new (expr_list) type(init_list)
1924 NodeArray ExprList;
1925 Node *Type;
1926 NodeArray InitList;
1927 bool IsGlobal; // ::operator new ?
1928 bool IsArray; // new[] ?
1929public:
1930 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001931 bool IsArray_, Prec Prec_)
1932 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
1933 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001934
1935 template<typename Fn> void match(Fn F) const {
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001936 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00001937 }
1938
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001939 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001940 if (IsGlobal)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001941 OB += "::";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001942 OB += "new";
Richard Smithc20d1442018-08-20 20:14:49 +00001943 if (IsArray)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001944 OB += "[]";
Richard Smithc20d1442018-08-20 20:14:49 +00001945 if (!ExprList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001946 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001947 ExprList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001948 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001949 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001950 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001951 Type->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001952 if (!InitList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001953 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001954 InitList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001955 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001956 }
Richard Smithc20d1442018-08-20 20:14:49 +00001957 }
1958};
1959
1960class DeleteExpr : public Node {
1961 Node *Op;
1962 bool IsGlobal;
1963 bool IsArray;
1964
1965public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001966 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
1967 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
1968 IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001969
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001970 template <typename Fn> void match(Fn F) const {
1971 F(Op, IsGlobal, IsArray, getPrecedence());
1972 }
Richard Smithc20d1442018-08-20 20:14:49 +00001973
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001974 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001975 if (IsGlobal)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001976 OB += "::";
1977 OB += "delete";
Richard Smithc20d1442018-08-20 20:14:49 +00001978 if (IsArray)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001979 OB += "[]";
1980 OB += ' ';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001981 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001982 }
1983};
1984
1985class PrefixExpr : public Node {
1986 StringView Prefix;
1987 Node *Child;
1988
1989public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001990 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
1991 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001992
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001993 template <typename Fn> void match(Fn F) const {
1994 F(Prefix, Child, getPrecedence());
1995 }
Richard Smithc20d1442018-08-20 20:14:49 +00001996
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001997 void printLeft(OutputBuffer &OB) const override {
1998 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001999 Child->printAsOperand(OB, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00002000 }
2001};
2002
2003class FunctionParam : public Node {
2004 StringView Number;
2005
2006public:
2007 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
2008
2009 template<typename Fn> void match(Fn F) const { F(Number); }
2010
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002011 void printLeft(OutputBuffer &OB) const override {
2012 OB += "fp";
2013 OB += Number;
Richard Smithc20d1442018-08-20 20:14:49 +00002014 }
2015};
2016
2017class ConversionExpr : public Node {
2018 const Node *Type;
2019 NodeArray Expressions;
2020
2021public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002022 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2023 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002024
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002025 template <typename Fn> void match(Fn F) const {
2026 F(Type, Expressions, getPrecedence());
2027 }
Richard Smithc20d1442018-08-20 20:14:49 +00002028
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002029 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002030 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002031 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002032 OB.printClose();
2033 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002034 Expressions.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002035 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002036 }
2037};
2038
Richard Smith1865d2f2020-10-22 19:29:36 -07002039class PointerToMemberConversionExpr : public Node {
2040 const Node *Type;
2041 const Node *SubExpr;
2042 StringView Offset;
2043
2044public:
2045 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002046 StringView Offset_, Prec Prec_)
2047 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2048 SubExpr(SubExpr_), Offset(Offset_) {}
Richard Smith1865d2f2020-10-22 19:29:36 -07002049
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002050 template <typename Fn> void match(Fn F) const {
2051 F(Type, SubExpr, Offset, getPrecedence());
2052 }
Richard Smith1865d2f2020-10-22 19:29:36 -07002053
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002054 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002055 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002056 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002057 OB.printClose();
2058 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002059 SubExpr->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002060 OB.printClose();
Richard Smith1865d2f2020-10-22 19:29:36 -07002061 }
2062};
2063
Richard Smithc20d1442018-08-20 20:14:49 +00002064class InitListExpr : public Node {
2065 const Node *Ty;
2066 NodeArray Inits;
2067public:
2068 InitListExpr(const Node *Ty_, NodeArray Inits_)
2069 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2070
2071 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2072
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002073 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002074 if (Ty)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002075 Ty->print(OB);
2076 OB += '{';
2077 Inits.printWithComma(OB);
2078 OB += '}';
Richard Smithc20d1442018-08-20 20:14:49 +00002079 }
2080};
2081
2082class BracedExpr : public Node {
2083 const Node *Elem;
2084 const Node *Init;
2085 bool IsArray;
2086public:
2087 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2088 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2089
2090 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
2091
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002092 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002093 if (IsArray) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002094 OB += '[';
2095 Elem->print(OB);
2096 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002097 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002098 OB += '.';
2099 Elem->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002100 }
2101 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002102 OB += " = ";
2103 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002104 }
2105};
2106
2107class BracedRangeExpr : public Node {
2108 const Node *First;
2109 const Node *Last;
2110 const Node *Init;
2111public:
2112 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2113 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2114
2115 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2116
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002117 void printLeft(OutputBuffer &OB) const override {
2118 OB += '[';
2119 First->print(OB);
2120 OB += " ... ";
2121 Last->print(OB);
2122 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002123 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002124 OB += " = ";
2125 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002126 }
2127};
2128
2129class FoldExpr : public Node {
2130 const Node *Pack, *Init;
2131 StringView OperatorName;
2132 bool IsLeftFold;
2133
2134public:
2135 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
2136 const Node *Init_)
2137 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2138 IsLeftFold(IsLeftFold_) {}
2139
2140 template<typename Fn> void match(Fn F) const {
2141 F(IsLeftFold, OperatorName, Pack, Init);
2142 }
2143
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002144 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002145 auto PrintPack = [&] {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002146 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002147 ParameterPackExpansion(Pack).print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002148 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002149 };
2150
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002151 OB.printOpen();
2152 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2153 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2154 // Fold expr operands are cast-expressions
2155 if (!IsLeftFold || Init != nullptr) {
2156 // '(init|pack) op '
2157 if (IsLeftFold)
2158 Init->printAsOperand(OB, Prec::Cast, true);
2159 else
2160 PrintPack();
2161 OB << " " << OperatorName << " ";
Richard Smithc20d1442018-08-20 20:14:49 +00002162 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002163 OB << "...";
2164 if (IsLeftFold || Init != nullptr) {
2165 // ' op (init|pack)'
2166 OB << " " << OperatorName << " ";
2167 if (IsLeftFold)
2168 PrintPack();
2169 else
2170 Init->printAsOperand(OB, Prec::Cast, true);
2171 }
2172 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002173 }
2174};
2175
2176class ThrowExpr : public Node {
2177 const Node *Op;
2178
2179public:
2180 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2181
2182 template<typename Fn> void match(Fn F) const { F(Op); }
2183
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002184 void printLeft(OutputBuffer &OB) const override {
2185 OB += "throw ";
2186 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002187 }
2188};
2189
2190class BoolExpr : public Node {
2191 bool Value;
2192
2193public:
2194 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2195
2196 template<typename Fn> void match(Fn F) const { F(Value); }
2197
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002198 void printLeft(OutputBuffer &OB) const override {
2199 OB += Value ? StringView("true") : StringView("false");
Richard Smithc20d1442018-08-20 20:14:49 +00002200 }
2201};
2202
Richard Smithdf1c14c2019-09-06 23:53:21 +00002203class StringLiteral : public Node {
2204 const Node *Type;
2205
2206public:
2207 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2208
2209 template<typename Fn> void match(Fn F) const { F(Type); }
2210
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002211 void printLeft(OutputBuffer &OB) const override {
2212 OB += "\"<";
2213 Type->print(OB);
2214 OB += ">\"";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002215 }
2216};
2217
2218class LambdaExpr : public Node {
2219 const Node *Type;
2220
Richard Smithdf1c14c2019-09-06 23:53:21 +00002221public:
2222 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2223
2224 template<typename Fn> void match(Fn F) const { F(Type); }
2225
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002226 void printLeft(OutputBuffer &OB) const override {
2227 OB += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002228 if (Type->getKind() == KClosureTypeName)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002229 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2230 OB += "{...}";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002231 }
2232};
2233
Erik Pilkington0a170f12020-05-13 14:13:37 -04002234class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002235 // ty(integer)
2236 const Node *Ty;
2237 StringView Integer;
2238
2239public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002240 EnumLiteral(const Node *Ty_, StringView Integer_)
2241 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002242
2243 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2244
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002245 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002246 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002247 Ty->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002248 OB.printClose();
Erik Pilkington0a170f12020-05-13 14:13:37 -04002249
2250 if (Integer[0] == 'n')
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002251 OB << "-" << Integer.dropFront(1);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002252 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002253 OB << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002254 }
2255};
2256
2257class IntegerLiteral : public Node {
2258 StringView Type;
2259 StringView Value;
2260
2261public:
2262 IntegerLiteral(StringView Type_, StringView Value_)
2263 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2264
2265 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2266
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002267 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002268 if (Type.size() > 3) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002269 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002270 OB += Type;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002271 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002272 }
2273
2274 if (Value[0] == 'n') {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002275 OB += '-';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002276 OB += Value.dropFront(1);
Richard Smithc20d1442018-08-20 20:14:49 +00002277 } else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002278 OB += Value;
Richard Smithc20d1442018-08-20 20:14:49 +00002279
2280 if (Type.size() <= 3)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002281 OB += Type;
Richard Smithc20d1442018-08-20 20:14:49 +00002282 }
2283};
2284
2285template <class Float> struct FloatData;
2286
2287namespace float_literal_impl {
2288constexpr Node::Kind getFloatLiteralKind(float *) {
2289 return Node::KFloatLiteral;
2290}
2291constexpr Node::Kind getFloatLiteralKind(double *) {
2292 return Node::KDoubleLiteral;
2293}
2294constexpr Node::Kind getFloatLiteralKind(long double *) {
2295 return Node::KLongDoubleLiteral;
2296}
2297}
2298
2299template <class Float> class FloatLiteralImpl : public Node {
2300 const StringView Contents;
2301
2302 static constexpr Kind KindForClass =
2303 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2304
2305public:
2306 FloatLiteralImpl(StringView Contents_)
2307 : Node(KindForClass), Contents(Contents_) {}
2308
2309 template<typename Fn> void match(Fn F) const { F(Contents); }
2310
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002311 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002312 const char *first = Contents.begin();
2313 const char *last = Contents.end() + 1;
2314
2315 const size_t N = FloatData<Float>::mangled_size;
2316 if (static_cast<std::size_t>(last - first) > N) {
2317 last = first + N;
2318 union {
2319 Float value;
2320 char buf[sizeof(Float)];
2321 };
2322 const char *t = first;
2323 char *e = buf;
2324 for (; t != last; ++t, ++e) {
2325 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2326 : static_cast<unsigned>(*t - 'a' + 10);
2327 ++t;
2328 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2329 : static_cast<unsigned>(*t - 'a' + 10);
2330 *e = static_cast<char>((d1 << 4) + d0);
2331 }
2332#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2333 std::reverse(buf, e);
2334#endif
2335 char num[FloatData<Float>::max_demangled_size] = {0};
2336 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002337 OB += StringView(num, num + n);
Richard Smithc20d1442018-08-20 20:14:49 +00002338 }
2339 }
2340};
2341
2342using FloatLiteral = FloatLiteralImpl<float>;
2343using DoubleLiteral = FloatLiteralImpl<double>;
2344using LongDoubleLiteral = FloatLiteralImpl<long double>;
2345
2346/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2347/// appropriate derived class.
2348template<typename Fn>
2349void Node::visit(Fn F) const {
2350 switch (K) {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002351#define NODE(X) \
2352 case K##X: \
2353 return F(static_cast<const X *>(this));
2354#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002355 }
2356 assert(0 && "unknown mangling node kind");
2357}
2358
2359/// Determine the kind of a node from its type.
2360template<typename NodeT> struct NodeKind;
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002361#define NODE(X) \
2362 template <> struct NodeKind<X> { \
2363 static constexpr Node::Kind Kind = Node::K##X; \
2364 static constexpr const char *name() { return #X; } \
Richard Smithc20d1442018-08-20 20:14:49 +00002365 };
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002366#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002367
Pavel Labathba825192018-10-16 14:29:14 +00002368template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002369 const char *First;
2370 const char *Last;
2371
2372 // Name stack, this is used by the parser to hold temporary names that were
2373 // parsed. The parser collapses multiple names into new nodes to construct
2374 // the AST. Once the parser is finished, names.size() == 1.
2375 PODSmallVector<Node *, 32> Names;
2376
2377 // Substitution table. Itanium supports name substitutions as a means of
2378 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2379 // table.
2380 PODSmallVector<Node *, 32> Subs;
2381
Richard Smithdf1c14c2019-09-06 23:53:21 +00002382 using TemplateParamList = PODSmallVector<Node *, 8>;
2383
2384 class ScopedTemplateParamList {
2385 AbstractManglingParser *Parser;
2386 size_t OldNumTemplateParamLists;
2387 TemplateParamList Params;
2388
2389 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002390 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2391 : Parser(TheParser),
2392 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002393 Parser->TemplateParams.push_back(&Params);
2394 }
2395 ~ScopedTemplateParamList() {
2396 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2397 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2398 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002399 };
2400
Richard Smithc20d1442018-08-20 20:14:49 +00002401 // Template parameter table. Like the above, but referenced like "T42_".
2402 // This has a smaller size compared to Subs and Names because it can be
2403 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002404 TemplateParamList OuterTemplateParams;
2405
2406 // Lists of template parameters indexed by template parameter depth,
2407 // referenced like "TL2_4_". If nonempty, element 0 is always
2408 // OuterTemplateParams; inner elements are always template parameter lists of
2409 // lambda expressions. For a generic lambda with no explicit template
2410 // parameter list, the corresponding parameter list pointer will be null.
2411 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002412
2413 // Set of unresolved forward <template-param> references. These can occur in a
2414 // conversion operator's type, and are resolved in the enclosing <encoding>.
2415 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2416
Richard Smithc20d1442018-08-20 20:14:49 +00002417 bool TryToParseTemplateArgs = true;
2418 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002419 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2420
2421 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002422
2423 Alloc ASTAllocator;
2424
Pavel Labathba825192018-10-16 14:29:14 +00002425 AbstractManglingParser(const char *First_, const char *Last_)
2426 : First(First_), Last(Last_) {}
2427
2428 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002429
2430 void reset(const char *First_, const char *Last_) {
2431 First = First_;
2432 Last = Last_;
2433 Names.clear();
2434 Subs.clear();
2435 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002436 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002437 TryToParseTemplateArgs = true;
2438 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002439 for (int I = 0; I != 3; ++I)
2440 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002441 ASTAllocator.reset();
2442 }
2443
Richard Smithb485b352018-08-24 23:30:26 +00002444 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002445 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2446 }
2447
2448 template <class It> NodeArray makeNodeArray(It begin, It end) {
2449 size_t sz = static_cast<size_t>(end - begin);
2450 void *mem = ASTAllocator.allocateNodeArray(sz);
2451 Node **data = new (mem) Node *[sz];
2452 std::copy(begin, end, data);
2453 return NodeArray(data, sz);
2454 }
2455
2456 NodeArray popTrailingNodeArray(size_t FromPosition) {
2457 assert(FromPosition <= Names.size());
2458 NodeArray res =
2459 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2460 Names.dropBack(FromPosition);
2461 return res;
2462 }
2463
2464 bool consumeIf(StringView S) {
2465 if (StringView(First, Last).startsWith(S)) {
2466 First += S.size();
2467 return true;
2468 }
2469 return false;
2470 }
2471
2472 bool consumeIf(char C) {
2473 if (First != Last && *First == C) {
2474 ++First;
2475 return true;
2476 }
2477 return false;
2478 }
2479
2480 char consume() { return First != Last ? *First++ : '\0'; }
2481
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08002482 char look(unsigned Lookahead = 0) const {
Richard Smithc20d1442018-08-20 20:14:49 +00002483 if (static_cast<size_t>(Last - First) <= Lookahead)
2484 return '\0';
2485 return First[Lookahead];
2486 }
2487
2488 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2489
2490 StringView parseNumber(bool AllowNegative = false);
2491 Qualifiers parseCVQualifiers();
2492 bool parsePositiveInteger(size_t *Out);
2493 StringView parseBareSourceName();
2494
2495 bool parseSeqId(size_t *Out);
2496 Node *parseSubstitution();
2497 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002498 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002499 Node *parseTemplateArgs(bool TagTemplates = false);
2500 Node *parseTemplateArg();
2501
2502 /// Parse the <expr> production.
2503 Node *parseExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002504 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2505 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00002506 Node *parseIntegerLiteral(StringView Lit);
2507 Node *parseExprPrimary();
2508 template <class Float> Node *parseFloatingLiteral();
2509 Node *parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00002510 Node *parseConversionExpr();
2511 Node *parseBracedExpr();
2512 Node *parseFoldExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002513 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07002514 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002515
2516 /// Parse the <type> production.
2517 Node *parseType();
2518 Node *parseFunctionType();
2519 Node *parseVectorType();
2520 Node *parseDecltype();
2521 Node *parseArrayType();
2522 Node *parsePointerToMemberType();
2523 Node *parseClassEnumType();
2524 Node *parseQualifiedType();
2525
2526 Node *parseEncoding();
2527 bool parseCallOffset();
2528 Node *parseSpecialName();
2529
2530 /// Holds some extra information about a <name> that is being parsed. This
2531 /// information is only pertinent if the <name> refers to an <encoding>.
2532 struct NameState {
2533 bool CtorDtorConversion = false;
2534 bool EndsWithTemplateArgs = false;
2535 Qualifiers CVQualifiers = QualNone;
2536 FunctionRefQual ReferenceQualifier = FrefQualNone;
2537 size_t ForwardTemplateRefsBegin;
2538
Pavel Labathba825192018-10-16 14:29:14 +00002539 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002540 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2541 };
2542
2543 bool resolveForwardTemplateRefs(NameState &State) {
2544 size_t I = State.ForwardTemplateRefsBegin;
2545 size_t E = ForwardTemplateRefs.size();
2546 for (; I < E; ++I) {
2547 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002548 if (TemplateParams.empty() || !TemplateParams[0] ||
2549 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002550 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002551 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002552 }
2553 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2554 return false;
2555 }
2556
2557 /// Parse the <name> production>
2558 Node *parseName(NameState *State = nullptr);
2559 Node *parseLocalName(NameState *State);
2560 Node *parseOperatorName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002561 bool parseModuleNameOpt(ModuleName *&Module);
2562 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
Richard Smithc20d1442018-08-20 20:14:49 +00002563 Node *parseUnnamedTypeName(NameState *State);
2564 Node *parseSourceName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002565 Node *parseUnscopedName(NameState *State, bool *isSubstName);
Richard Smithc20d1442018-08-20 20:14:49 +00002566 Node *parseNestedName(NameState *State);
2567 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2568
2569 Node *parseAbiTags(Node *N);
2570
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002571 struct OperatorInfo {
2572 enum OIKind : unsigned char {
2573 Prefix, // Prefix unary: @ expr
2574 Postfix, // Postfix unary: expr @
2575 Binary, // Binary: lhs @ rhs
2576 Array, // Array index: lhs [ rhs ]
2577 Member, // Member access: lhs @ rhs
2578 New, // New
2579 Del, // Delete
2580 Call, // Function call: expr (expr*)
2581 CCast, // C cast: (type)expr
2582 Conditional, // Conditional: expr ? expr : expr
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08002583 NameOnly, // Overload only, not allowed in expression.
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002584 // Below do not have operator names
2585 NamedCast, // Named cast, @<type>(expr)
2586 OfIdOp, // alignof, sizeof, typeid
2587
2588 Unnameable = NamedCast,
2589 };
2590 char Enc[2]; // Encoding
2591 OIKind Kind; // Kind of operator
2592 bool Flag : 1; // Entry-specific flag
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002593 Node::Prec Prec : 7; // Precedence
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002594 const char *Name; // Spelling
2595
2596 public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002597 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2598 const char *N)
2599 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002600
2601 public:
2602 bool operator<(const OperatorInfo &Other) const {
2603 return *this < Other.Enc;
2604 }
2605 bool operator<(const char *Peek) const {
2606 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2607 }
2608 bool operator==(const char *Peek) const {
2609 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2610 }
2611 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2612
2613 public:
2614 StringView getSymbol() const {
2615 StringView Res = Name;
2616 if (Kind < Unnameable) {
2617 assert(Res.startsWith("operator") &&
2618 "operator name does not start with 'operator'");
2619 Res = Res.dropFront(sizeof("operator") - 1);
2620 Res.consumeFront(' ');
2621 }
2622 return Res;
2623 }
2624 StringView getName() const { return Name; }
2625 OIKind getKind() const { return Kind; }
2626 bool getFlag() const { return Flag; }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002627 Node::Prec getPrecedence() const { return Prec; }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002628 };
Nathan Sidwell7d9bbeb2022-04-08 06:55:31 -07002629 static const OperatorInfo Ops[];
2630 static const size_t NumOps;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002631 const OperatorInfo *parseOperatorEncoding();
2632
Richard Smithc20d1442018-08-20 20:14:49 +00002633 /// Parse the <unresolved-name> production.
Nathan Sidwell77c52e22022-01-28 11:59:03 -08002634 Node *parseUnresolvedName(bool Global);
Richard Smithc20d1442018-08-20 20:14:49 +00002635 Node *parseSimpleId();
2636 Node *parseBaseUnresolvedName();
2637 Node *parseUnresolvedType();
2638 Node *parseDestructorName();
2639
2640 /// Top-level entry point into the parser.
2641 Node *parse();
2642};
2643
2644const char* parse_discriminator(const char* first, const char* last);
2645
2646// <name> ::= <nested-name> // N
2647// ::= <local-name> # See Scope Encoding below // Z
2648// ::= <unscoped-template-name> <template-args>
2649// ::= <unscoped-name>
2650//
2651// <unscoped-template-name> ::= <unscoped-name>
2652// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002653template <typename Derived, typename Alloc>
2654Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002655 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002656 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002657 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002658 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002659
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002660 Node *Result = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002661 bool IsSubst = false;
2662
2663 Result = getDerived().parseUnscopedName(State, &IsSubst);
2664 if (!Result)
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002665 return nullptr;
2666
2667 if (look() == 'I') {
2668 // ::= <unscoped-template-name> <template-args>
2669 if (!IsSubst)
2670 // An unscoped-template-name is substitutable.
2671 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00002672 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002673 if (TA == nullptr)
2674 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002675 if (State)
2676 State->EndsWithTemplateArgs = true;
2677 Result = make<NameWithTemplateArgs>(Result, TA);
2678 } else if (IsSubst) {
2679 // The substitution case must be followed by <template-args>.
2680 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002681 }
2682
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002683 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00002684}
2685
2686// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2687// := Z <function encoding> E s [<discriminator>]
2688// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002689template <typename Derived, typename Alloc>
2690Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002691 if (!consumeIf('Z'))
2692 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002693 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002694 if (Encoding == nullptr || !consumeIf('E'))
2695 return nullptr;
2696
2697 if (consumeIf('s')) {
2698 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002699 auto *StringLitName = make<NameType>("string literal");
2700 if (!StringLitName)
2701 return nullptr;
2702 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002703 }
2704
2705 if (consumeIf('d')) {
2706 parseNumber(true);
2707 if (!consumeIf('_'))
2708 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002709 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002710 if (N == nullptr)
2711 return nullptr;
2712 return make<LocalName>(Encoding, N);
2713 }
2714
Pavel Labathba825192018-10-16 14:29:14 +00002715 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002716 if (Entity == nullptr)
2717 return nullptr;
2718 First = parse_discriminator(First, Last);
2719 return make<LocalName>(Encoding, Entity);
2720}
2721
Nathan Sidwellac492da2022-04-05 09:25:47 -07002722// <unscoped-name> ::= <unqualified-name>
2723// ::= St <unqualified-name> # ::std::
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08002724// [*] extension
Pavel Labathba825192018-10-16 14:29:14 +00002725template <typename Derived, typename Alloc>
2726Node *
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002727AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2728 bool *IsSubst) {
2729
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002730 Node *Std = nullptr;
2731 if (consumeIf("St")) {
2732 Std = make<NameType>("std");
2733 if (Std == nullptr)
Nathan Sidwell200e97c2022-01-21 11:37:01 -08002734 return nullptr;
2735 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002736
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002737 Node *Res = nullptr;
2738 ModuleName *Module = nullptr;
2739 if (look() == 'S') {
2740 Node *S = getDerived().parseSubstitution();
2741 if (!S)
2742 return nullptr;
2743 if (S->getKind() == Node::KModuleName)
2744 Module = static_cast<ModuleName *>(S);
2745 else if (IsSubst && Std == nullptr) {
2746 Res = S;
2747 *IsSubst = true;
2748 } else {
2749 return nullptr;
2750 }
2751 }
2752
Nathan Sidwellac492da2022-04-05 09:25:47 -07002753 if (Res == nullptr || Std != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002754 Res = getDerived().parseUnqualifiedName(State, Std, Module);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002755 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002756
2757 return Res;
Richard Smithc20d1442018-08-20 20:14:49 +00002758}
2759
Nathan Sidwellac492da2022-04-05 09:25:47 -07002760// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002761// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
Nathan Sidwellac492da2022-04-05 09:25:47 -07002762// ::= [<module-name>] L? <source-name> [<abi-tags>]
2763// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002764// # structured binding declaration
Nathan Sidwellac492da2022-04-05 09:25:47 -07002765// ::= [<module-name>] L? DC <source-name>+ E
Pavel Labathba825192018-10-16 14:29:14 +00002766template <typename Derived, typename Alloc>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002767Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2768 NameState *State, Node *Scope, ModuleName *Module) {
2769 if (getDerived().parseModuleNameOpt(Module))
2770 return nullptr;
2771
Nathan Sidwellac492da2022-04-05 09:25:47 -07002772 consumeIf('L');
2773
Richard Smithc20d1442018-08-20 20:14:49 +00002774 Node *Result;
Nathan Sidwellac492da2022-04-05 09:25:47 -07002775 if (look() >= '1' && look() <= '9') {
Pavel Labathba825192018-10-16 14:29:14 +00002776 Result = getDerived().parseSourceName(State);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002777 } else if (look() == 'U') {
2778 Result = getDerived().parseUnnamedTypeName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002779 } else if (consumeIf("DC")) {
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002780 // Structured binding
Richard Smithc20d1442018-08-20 20:14:49 +00002781 size_t BindingsBegin = Names.size();
2782 do {
Pavel Labathba825192018-10-16 14:29:14 +00002783 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002784 if (Binding == nullptr)
2785 return nullptr;
2786 Names.push_back(Binding);
2787 } while (!consumeIf('E'));
2788 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002789 } else if (look() == 'C' || look() == 'D') {
2790 // A <ctor-dtor-name>.
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002791 if (Scope == nullptr || Module != nullptr)
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002792 return nullptr;
2793 Result = getDerived().parseCtorDtorName(Scope, State);
2794 } else {
Pavel Labathba825192018-10-16 14:29:14 +00002795 Result = getDerived().parseOperatorName(State);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002796 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002797
David Blaikie019fb1b2022-03-30 20:18:40 +00002798 if (Result != nullptr && Module != nullptr)
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002799 Result = make<ModuleEntity>(Module, Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002800 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002801 Result = getDerived().parseAbiTags(Result);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002802 if (Result != nullptr && Scope != nullptr)
2803 Result = make<NestedName>(Scope, Result);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002804
Richard Smithc20d1442018-08-20 20:14:49 +00002805 return Result;
2806}
2807
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002808// <module-name> ::= <module-subname>
2809// ::= <module-name> <module-subname>
2810// ::= <substitution> # passed in by caller
2811// <module-subname> ::= W <source-name>
2812// ::= W P <source-name>
2813template <typename Derived, typename Alloc>
2814bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2815 ModuleName *&Module) {
2816 while (consumeIf('W')) {
2817 bool IsPartition = consumeIf('P');
2818 Node *Sub = getDerived().parseSourceName(nullptr);
2819 if (!Sub)
2820 return true;
2821 Module =
2822 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2823 Subs.push_back(Module);
2824 }
2825
2826 return false;
2827}
2828
Richard Smithc20d1442018-08-20 20:14:49 +00002829// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2830// ::= <closure-type-name>
2831//
2832// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2833//
2834// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002835template <typename Derived, typename Alloc>
2836Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002837AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2838 // <template-params> refer to the innermost <template-args>. Clear out any
2839 // outer args that we may have inserted into TemplateParams.
2840 if (State != nullptr)
2841 TemplateParams.clear();
2842
Richard Smithc20d1442018-08-20 20:14:49 +00002843 if (consumeIf("Ut")) {
2844 StringView Count = parseNumber();
2845 if (!consumeIf('_'))
2846 return nullptr;
2847 return make<UnnamedTypeName>(Count);
2848 }
2849 if (consumeIf("Ul")) {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08002850 ScopedOverride<size_t> SwapParams(ParsingLambdaParamsAtLevel,
Richard Smithdf1c14c2019-09-06 23:53:21 +00002851 TemplateParams.size());
2852 ScopedTemplateParamList LambdaTemplateParams(this);
2853
2854 size_t ParamsBegin = Names.size();
2855 while (look() == 'T' &&
2856 StringView("yptn").find(look(1)) != StringView::npos) {
2857 Node *T = parseTemplateParamDecl();
2858 if (!T)
2859 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002860 Names.push_back(T);
2861 }
2862 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2863
2864 // FIXME: If TempParams is empty and none of the function parameters
2865 // includes 'auto', we should remove LambdaTemplateParams from the
2866 // TemplateParams list. Unfortunately, we don't find out whether there are
2867 // any 'auto' parameters until too late in an example such as:
2868 //
2869 // template<typename T> void f(
2870 // decltype([](decltype([]<typename T>(T v) {}),
2871 // auto) {})) {}
2872 // template<typename T> void f(
2873 // decltype([](decltype([]<typename T>(T w) {}),
2874 // int) {})) {}
2875 //
2876 // Here, the type of v is at level 2 but the type of w is at level 1. We
2877 // don't find this out until we encounter the type of the next parameter.
2878 //
2879 // However, compilers can't actually cope with the former example in
2880 // practice, and it's likely to be made ill-formed in future, so we don't
2881 // need to support it here.
2882 //
2883 // If we encounter an 'auto' in the function parameter types, we will
2884 // recreate a template parameter scope for it, but any intervening lambdas
2885 // will be parsed in the 'wrong' template parameter depth.
2886 if (TempParams.empty())
2887 TemplateParams.pop_back();
2888
Richard Smithc20d1442018-08-20 20:14:49 +00002889 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002890 do {
Pavel Labathba825192018-10-16 14:29:14 +00002891 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002892 if (P == nullptr)
2893 return nullptr;
2894 Names.push_back(P);
2895 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002896 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002897 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2898
Richard Smithc20d1442018-08-20 20:14:49 +00002899 StringView Count = parseNumber();
2900 if (!consumeIf('_'))
2901 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002902 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002903 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002904 if (consumeIf("Ub")) {
2905 (void)parseNumber();
2906 if (!consumeIf('_'))
2907 return nullptr;
2908 return make<NameType>("'block-literal'");
2909 }
Richard Smithc20d1442018-08-20 20:14:49 +00002910 return nullptr;
2911}
2912
2913// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002914template <typename Derived, typename Alloc>
2915Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002916 size_t Length = 0;
2917 if (parsePositiveInteger(&Length))
2918 return nullptr;
2919 if (numLeft() < Length || Length == 0)
2920 return nullptr;
2921 StringView Name(First, First + Length);
2922 First += Length;
2923 if (Name.startsWith("_GLOBAL__N"))
2924 return make<NameType>("(anonymous namespace)");
2925 return make<NameType>(Name);
2926}
2927
Nathan Sidwell7d9bbeb2022-04-08 06:55:31 -07002928// Operator encodings
2929template <typename Derived, typename Alloc>
2930const typename AbstractManglingParser<
2931 Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,
2932 Alloc>::Ops[] = {
2933 // Keep ordered by encoding
2934 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
2935 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
2936 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
2937 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
2938 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
2939 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},
2940 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
2941 "operator co_await"},
2942 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},
2943 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
2944 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
2945 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
2946 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
2947 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast
2948 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
2949 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
2950 "operator delete[]"},
2951 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},
2952 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
2953 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
2954 "operator delete"},
2955 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2956 "operator.*"},
2957 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
2958 "operator."},
2959 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
2960 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
2961 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
2962 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
2963 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
2964 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
2965 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
2966 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
2967 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
2968 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
2969 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
2970 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
2971 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
2972 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
2973 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
2974 "operator*"},
2975 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
2976 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
2977 "operator new[]"},
2978 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
2979 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
2980 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
2981 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},
2982 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
2983 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
2984 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
2985 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
2986 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
2987 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2988 "operator->*"},
2989 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
2990 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
2991 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
2992 "operator->"},
2993 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
2994 "operator?"},
2995 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
2996 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
2997 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
2998 "reinterpret_cast"},
2999 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3000 "operator%"},
3001 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3002 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},
3003 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3004 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3005 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},
3006 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3007 "typeid "},
3008 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
3009};
3010template <typename Derived, typename Alloc>
3011const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /
3012 sizeof(Ops[0]);
3013
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003014// If the next 2 chars are an operator encoding, consume them and return their
3015// OperatorInfo. Otherwise return nullptr.
3016template <typename Derived, typename Alloc>
3017const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
3018AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003019 if (numLeft() < 2)
3020 return nullptr;
3021
3022 auto Op = std::lower_bound(
3023 &Ops[0], &Ops[NumOps], First,
3024 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3025 if (Op == &Ops[NumOps] || *Op != First)
3026 return nullptr;
3027
3028 First += 2;
3029 return Op;
3030}
3031
3032// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003033// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003034// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003035template <typename Derived, typename Alloc>
3036Node *
3037AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003038 if (const auto *Op = parseOperatorEncoding()) {
3039 if (Op->getKind() == OperatorInfo::CCast) {
3040 // ::= cv <type> # (cast)
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003041 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);
Richard Smithc20d1442018-08-20 20:14:49 +00003042 // If we're parsing an encoding, State != nullptr and the conversion
3043 // operators' <type> could have a <template-param> that refers to some
3044 // <template-arg>s further ahead in the mangled name.
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003045 ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,
Richard Smithc20d1442018-08-20 20:14:49 +00003046 PermitForwardTemplateReferences ||
3047 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003048 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003049 if (Ty == nullptr)
3050 return nullptr;
3051 if (State) State->CtorDtorConversion = true;
3052 return make<ConversionOperatorType>(Ty);
3053 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003054
3055 if (Op->getKind() >= OperatorInfo::Unnameable)
3056 /* Not a nameable operator. */
3057 return nullptr;
3058 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3059 /* Not a nameable MemberExpr */
3060 return nullptr;
3061
3062 return make<NameType>(Op->getName());
3063 }
3064
3065 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003066 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003067 Node *SN = getDerived().parseSourceName(State);
3068 if (SN == nullptr)
3069 return nullptr;
3070 return make<LiteralOperator>(SN);
3071 }
3072
3073 if (consumeIf('v')) {
3074 // ::= v <digit> <source-name> # vendor extended operator
3075 if (look() >= '0' && look() <= '9') {
3076 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003077 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003078 if (SN == nullptr)
3079 return nullptr;
3080 return make<ConversionOperatorType>(SN);
3081 }
3082 return nullptr;
3083 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003084
Richard Smithc20d1442018-08-20 20:14:49 +00003085 return nullptr;
3086}
3087
3088// <ctor-dtor-name> ::= C1 # complete object constructor
3089// ::= C2 # base object constructor
3090// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003091// extension ::= C4 # gcc old-style "[unified]" constructor
3092// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003093// ::= D0 # deleting destructor
3094// ::= D1 # complete object destructor
3095// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003096// extension ::= D4 # gcc old-style "[unified]" destructor
3097// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003098template <typename Derived, typename Alloc>
3099Node *
3100AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3101 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003102 if (SoFar->getKind() == Node::KSpecialSubstitution) {
Nathan Sidwell28201492022-03-28 12:55:45 -07003103 // Expand the special substitution.
3104 SoFar = make<ExpandedSpecialSubstitution>(
3105 static_cast<SpecialSubstitution *>(SoFar));
3106 if (!SoFar)
3107 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003108 }
3109
3110 if (consumeIf('C')) {
3111 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003112 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3113 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003114 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003115 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003116 ++First;
3117 if (State) State->CtorDtorConversion = true;
3118 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003119 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003120 return nullptr;
3121 }
Nico Weber29294792019-04-03 23:14:33 +00003122 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003123 }
3124
Nico Weber29294792019-04-03 23:14:33 +00003125 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3126 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003127 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003128 First += 2;
3129 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003130 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003131 }
3132
3133 return nullptr;
3134}
3135
Nathan Sidwellac492da2022-04-05 09:25:47 -07003136// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3137// <unqualified-name> E
3138// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3139// <template-args> E
Richard Smithc20d1442018-08-20 20:14:49 +00003140//
Nathan Sidwellac492da2022-04-05 09:25:47 -07003141// <prefix> ::= <prefix> <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003142// ::= <template-prefix> <template-args>
3143// ::= <template-param>
3144// ::= <decltype>
3145// ::= # empty
3146// ::= <substitution>
3147// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003148// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003149//
3150// <data-member-prefix> := <member source-name> [<template-args>] M
3151//
3152// <template-prefix> ::= <prefix> <template unqualified-name>
3153// ::= <template-param>
3154// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003155template <typename Derived, typename Alloc>
3156Node *
3157AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003158 if (!consumeIf('N'))
3159 return nullptr;
3160
3161 Qualifiers CVTmp = parseCVQualifiers();
3162 if (State) State->CVQualifiers = CVTmp;
3163
3164 if (consumeIf('O')) {
3165 if (State) State->ReferenceQualifier = FrefQualRValue;
3166 } else if (consumeIf('R')) {
3167 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003168 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003169 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003170 }
Richard Smithc20d1442018-08-20 20:14:49 +00003171
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003172 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003173 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003174 if (State)
3175 // Only set end-with-template on the case that does that.
3176 State->EndsWithTemplateArgs = false;
3177
Richard Smithc20d1442018-08-20 20:14:49 +00003178 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003179 // ::= <template-param>
3180 if (SoFar != nullptr)
3181 return nullptr; // Cannot have a prefix.
3182 SoFar = getDerived().parseTemplateParam();
3183 } else if (look() == 'I') {
3184 // ::= <template-prefix> <template-args>
3185 if (SoFar == nullptr)
3186 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003187 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003188 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003189 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003190 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3191 // Semantically <template-args> <template-args> cannot be generated by a
3192 // C++ entity. There will always be [something like] a name between
3193 // them.
3194 return nullptr;
3195 if (State)
3196 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003197 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003198 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3199 // ::= <decltype>
3200 if (SoFar != nullptr)
3201 return nullptr; // Cannot have a prefix.
3202 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003203 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003204 ModuleName *Module = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003205
3206 if (look() == 'S') {
3207 // ::= <substitution>
3208 Node *S = nullptr;
3209 if (look(1) == 't') {
3210 First += 2;
3211 S = make<NameType>("std");
3212 } else {
3213 S = getDerived().parseSubstitution();
3214 }
3215 if (!S)
3216 return nullptr;
3217 if (S->getKind() == Node::KModuleName) {
3218 Module = static_cast<ModuleName *>(S);
Nathan Sidwellac492da2022-04-05 09:25:47 -07003219 } else if (SoFar != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003220 return nullptr; // Cannot have a prefix.
3221 } else {
3222 SoFar = S;
3223 continue; // Do not push a new substitution.
3224 }
3225 }
3226
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003227 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003228 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003229 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003230
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003231 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003232 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003233 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003234
3235 // No longer used.
3236 // <data-member-prefix> := <member source-name> [<template-args>] M
3237 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003238 }
3239
3240 if (SoFar == nullptr || Subs.empty())
3241 return nullptr;
3242
3243 Subs.pop_back();
3244 return SoFar;
3245}
3246
3247// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003248template <typename Derived, typename Alloc>
3249Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3250 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003251 if (SN == nullptr)
3252 return nullptr;
3253 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003254 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003255 if (TA == nullptr)
3256 return nullptr;
3257 return make<NameWithTemplateArgs>(SN, TA);
3258 }
3259 return SN;
3260}
3261
3262// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3263// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003264template <typename Derived, typename Alloc>
3265Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003266 Node *Result;
3267 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003268 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003269 else
Pavel Labathba825192018-10-16 14:29:14 +00003270 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003271 if (Result == nullptr)
3272 return nullptr;
3273 return make<DtorName>(Result);
3274}
3275
3276// <unresolved-type> ::= <template-param>
3277// ::= <decltype>
3278// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003279template <typename Derived, typename Alloc>
3280Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003281 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003282 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003283 if (TP == nullptr)
3284 return nullptr;
3285 Subs.push_back(TP);
3286 return TP;
3287 }
3288 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003289 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003290 if (DT == nullptr)
3291 return nullptr;
3292 Subs.push_back(DT);
3293 return DT;
3294 }
Pavel Labathba825192018-10-16 14:29:14 +00003295 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003296}
3297
3298// <base-unresolved-name> ::= <simple-id> # unresolved name
3299// extension ::= <operator-name> # unresolved operator-function-id
3300// extension ::= <operator-name> <template-args> # unresolved operator template-id
3301// ::= on <operator-name> # unresolved operator-function-id
3302// ::= on <operator-name> <template-args> # unresolved operator template-id
3303// ::= dn <destructor-name> # destructor or pseudo-destructor;
3304// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003305template <typename Derived, typename Alloc>
3306Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003307 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003308 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003309
3310 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003311 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003312
3313 consumeIf("on");
3314
Pavel Labathba825192018-10-16 14:29:14 +00003315 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003316 if (Oper == nullptr)
3317 return nullptr;
3318 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003319 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003320 if (TA == nullptr)
3321 return nullptr;
3322 return make<NameWithTemplateArgs>(Oper, TA);
3323 }
3324 return Oper;
3325}
3326
3327// <unresolved-name>
3328// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3329// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3330// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3331// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003332// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003333// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3334// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3335// # T::N::x /decltype(p)::N::x
3336// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3337//
3338// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003339template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003340Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003341 Node *SoFar = nullptr;
3342
3343 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3344 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3345 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003346 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003347 if (SoFar == nullptr)
3348 return nullptr;
3349
3350 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003351 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003352 if (TA == nullptr)
3353 return nullptr;
3354 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003355 if (!SoFar)
3356 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003357 }
3358
3359 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003360 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003361 if (Qual == nullptr)
3362 return nullptr;
3363 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003364 if (!SoFar)
3365 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003366 }
3367
Pavel Labathba825192018-10-16 14:29:14 +00003368 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003369 if (Base == nullptr)
3370 return nullptr;
3371 return make<QualifiedName>(SoFar, Base);
3372 }
3373
Richard Smithc20d1442018-08-20 20:14:49 +00003374 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3375 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003376 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003377 if (SoFar == nullptr)
3378 return nullptr;
3379 if (Global)
3380 SoFar = make<GlobalQualifiedName>(SoFar);
3381 return SoFar;
3382 }
3383
3384 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3385 if (std::isdigit(look())) {
3386 do {
Pavel Labathba825192018-10-16 14:29:14 +00003387 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003388 if (Qual == nullptr)
3389 return nullptr;
3390 if (SoFar)
3391 SoFar = make<QualifiedName>(SoFar, Qual);
3392 else if (Global)
3393 SoFar = make<GlobalQualifiedName>(Qual);
3394 else
3395 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003396 if (!SoFar)
3397 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003398 } while (!consumeIf('E'));
3399 }
3400 // sr <unresolved-type> <base-unresolved-name>
3401 // sr <unresolved-type> <template-args> <base-unresolved-name>
3402 else {
Pavel Labathba825192018-10-16 14:29:14 +00003403 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003404 if (SoFar == nullptr)
3405 return nullptr;
3406
3407 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003408 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003409 if (TA == nullptr)
3410 return nullptr;
3411 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003412 if (!SoFar)
3413 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003414 }
3415 }
3416
3417 assert(SoFar != nullptr);
3418
Pavel Labathba825192018-10-16 14:29:14 +00003419 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003420 if (Base == nullptr)
3421 return nullptr;
3422 return make<QualifiedName>(SoFar, Base);
3423}
3424
3425// <abi-tags> ::= <abi-tag> [<abi-tags>]
3426// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003427template <typename Derived, typename Alloc>
3428Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003429 while (consumeIf('B')) {
3430 StringView SN = parseBareSourceName();
3431 if (SN.empty())
3432 return nullptr;
3433 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003434 if (!N)
3435 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003436 }
3437 return N;
3438}
3439
3440// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003441template <typename Alloc, typename Derived>
3442StringView
3443AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003444 const char *Tmp = First;
3445 if (AllowNegative)
3446 consumeIf('n');
3447 if (numLeft() == 0 || !std::isdigit(*First))
3448 return StringView();
3449 while (numLeft() != 0 && std::isdigit(*First))
3450 ++First;
3451 return StringView(Tmp, First);
3452}
3453
3454// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003455template <typename Alloc, typename Derived>
3456bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003457 *Out = 0;
3458 if (look() < '0' || look() > '9')
3459 return true;
3460 while (look() >= '0' && look() <= '9') {
3461 *Out *= 10;
3462 *Out += static_cast<size_t>(consume() - '0');
3463 }
3464 return false;
3465}
3466
Pavel Labathba825192018-10-16 14:29:14 +00003467template <typename Alloc, typename Derived>
3468StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003469 size_t Int = 0;
3470 if (parsePositiveInteger(&Int) || numLeft() < Int)
3471 return StringView();
3472 StringView R(First, First + Int);
3473 First += Int;
3474 return R;
3475}
3476
3477// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3478//
3479// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3480// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3481// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3482//
3483// <ref-qualifier> ::= R # & ref-qualifier
3484// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003485template <typename Derived, typename Alloc>
3486Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003487 Qualifiers CVQuals = parseCVQualifiers();
3488
3489 Node *ExceptionSpec = nullptr;
3490 if (consumeIf("Do")) {
3491 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003492 if (!ExceptionSpec)
3493 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003494 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003495 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003496 if (E == nullptr || !consumeIf('E'))
3497 return nullptr;
3498 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003499 if (!ExceptionSpec)
3500 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003501 } else if (consumeIf("Dw")) {
3502 size_t SpecsBegin = Names.size();
3503 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003504 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003505 if (T == nullptr)
3506 return nullptr;
3507 Names.push_back(T);
3508 }
3509 ExceptionSpec =
3510 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003511 if (!ExceptionSpec)
3512 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003513 }
3514
3515 consumeIf("Dx"); // transaction safe
3516
3517 if (!consumeIf('F'))
3518 return nullptr;
3519 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003520 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003521 if (ReturnType == nullptr)
3522 return nullptr;
3523
3524 FunctionRefQual ReferenceQualifier = FrefQualNone;
3525 size_t ParamsBegin = Names.size();
3526 while (true) {
3527 if (consumeIf('E'))
3528 break;
3529 if (consumeIf('v'))
3530 continue;
3531 if (consumeIf("RE")) {
3532 ReferenceQualifier = FrefQualLValue;
3533 break;
3534 }
3535 if (consumeIf("OE")) {
3536 ReferenceQualifier = FrefQualRValue;
3537 break;
3538 }
Pavel Labathba825192018-10-16 14:29:14 +00003539 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003540 if (T == nullptr)
3541 return nullptr;
3542 Names.push_back(T);
3543 }
3544
3545 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3546 return make<FunctionType>(ReturnType, Params, CVQuals,
3547 ReferenceQualifier, ExceptionSpec);
3548}
3549
3550// extension:
3551// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3552// ::= Dv [<dimension expression>] _ <element type>
3553// <extended element type> ::= <element type>
3554// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003555template <typename Derived, typename Alloc>
3556Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003557 if (!consumeIf("Dv"))
3558 return nullptr;
3559 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003560 Node *DimensionNumber = make<NameType>(parseNumber());
3561 if (!DimensionNumber)
3562 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003563 if (!consumeIf('_'))
3564 return nullptr;
3565 if (consumeIf('p'))
3566 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003567 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003568 if (ElemType == nullptr)
3569 return nullptr;
3570 return make<VectorType>(ElemType, DimensionNumber);
3571 }
3572
3573 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003574 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003575 if (!DimExpr)
3576 return nullptr;
3577 if (!consumeIf('_'))
3578 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003579 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003580 if (!ElemType)
3581 return nullptr;
3582 return make<VectorType>(ElemType, DimExpr);
3583 }
Pavel Labathba825192018-10-16 14:29:14 +00003584 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003585 if (!ElemType)
3586 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003587 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003588}
3589
3590// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3591// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003592template <typename Derived, typename Alloc>
3593Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003594 if (!consumeIf('D'))
3595 return nullptr;
3596 if (!consumeIf('t') && !consumeIf('T'))
3597 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003598 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003599 if (E == nullptr)
3600 return nullptr;
3601 if (!consumeIf('E'))
3602 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003603 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003604}
3605
3606// <array-type> ::= A <positive dimension number> _ <element type>
3607// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003608template <typename Derived, typename Alloc>
3609Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003610 if (!consumeIf('A'))
3611 return nullptr;
3612
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003613 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003614
Richard Smithc20d1442018-08-20 20:14:49 +00003615 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003616 Dimension = make<NameType>(parseNumber());
3617 if (!Dimension)
3618 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003619 if (!consumeIf('_'))
3620 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003621 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003622 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003623 if (DimExpr == nullptr)
3624 return nullptr;
3625 if (!consumeIf('_'))
3626 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003627 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003628 }
3629
Pavel Labathba825192018-10-16 14:29:14 +00003630 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003631 if (Ty == nullptr)
3632 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003633 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003634}
3635
3636// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003637template <typename Derived, typename Alloc>
3638Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003639 if (!consumeIf('M'))
3640 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003641 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003642 if (ClassType == nullptr)
3643 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003644 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003645 if (MemberType == nullptr)
3646 return nullptr;
3647 return make<PointerToMemberType>(ClassType, MemberType);
3648}
3649
3650// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3651// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3652// ::= Tu <name> # dependent elaborated type specifier using 'union'
3653// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003654template <typename Derived, typename Alloc>
3655Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003656 StringView ElabSpef;
3657 if (consumeIf("Ts"))
3658 ElabSpef = "struct";
3659 else if (consumeIf("Tu"))
3660 ElabSpef = "union";
3661 else if (consumeIf("Te"))
3662 ElabSpef = "enum";
3663
Pavel Labathba825192018-10-16 14:29:14 +00003664 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003665 if (Name == nullptr)
3666 return nullptr;
3667
3668 if (!ElabSpef.empty())
3669 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3670
3671 return Name;
3672}
3673
3674// <qualified-type> ::= <qualifiers> <type>
3675// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3676// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003677template <typename Derived, typename Alloc>
3678Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003679 if (consumeIf('U')) {
3680 StringView Qual = parseBareSourceName();
3681 if (Qual.empty())
3682 return nullptr;
3683
Richard Smithc20d1442018-08-20 20:14:49 +00003684 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3685 if (Qual.startsWith("objcproto")) {
3686 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3687 StringView Proto;
3688 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003689 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()),
3690 SaveLast(Last, ProtoSourceName.end());
Richard Smithc20d1442018-08-20 20:14:49 +00003691 Proto = parseBareSourceName();
3692 }
3693 if (Proto.empty())
3694 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003695 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003696 if (Child == nullptr)
3697 return nullptr;
3698 return make<ObjCProtoName>(Child, Proto);
3699 }
3700
Alex Orlovf50df922021-03-24 10:21:32 +04003701 Node *TA = nullptr;
3702 if (look() == 'I') {
3703 TA = getDerived().parseTemplateArgs();
3704 if (TA == nullptr)
3705 return nullptr;
3706 }
3707
Pavel Labathba825192018-10-16 14:29:14 +00003708 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003709 if (Child == nullptr)
3710 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003711 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003712 }
3713
3714 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003715 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003716 if (Ty == nullptr)
3717 return nullptr;
3718 if (Quals != QualNone)
3719 Ty = make<QualType>(Ty, Quals);
3720 return Ty;
3721}
3722
3723// <type> ::= <builtin-type>
3724// ::= <qualified-type>
3725// ::= <function-type>
3726// ::= <class-enum-type>
3727// ::= <array-type>
3728// ::= <pointer-to-member-type>
3729// ::= <template-param>
3730// ::= <template-template-param> <template-args>
3731// ::= <decltype>
3732// ::= P <type> # pointer
3733// ::= R <type> # l-value reference
3734// ::= O <type> # r-value reference (C++11)
3735// ::= C <type> # complex pair (C99)
3736// ::= G <type> # imaginary (C99)
3737// ::= <substitution> # See Compression below
3738// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3739// extension ::= <vector-type> # <vector-type> starts with Dv
3740//
3741// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3742// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003743template <typename Derived, typename Alloc>
3744Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003745 Node *Result = nullptr;
3746
Richard Smithc20d1442018-08-20 20:14:49 +00003747 switch (look()) {
3748 // ::= <qualified-type>
3749 case 'r':
3750 case 'V':
3751 case 'K': {
3752 unsigned AfterQuals = 0;
3753 if (look(AfterQuals) == 'r') ++AfterQuals;
3754 if (look(AfterQuals) == 'V') ++AfterQuals;
3755 if (look(AfterQuals) == 'K') ++AfterQuals;
3756
3757 if (look(AfterQuals) == 'F' ||
3758 (look(AfterQuals) == 'D' &&
3759 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3760 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003761 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003762 break;
3763 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003764 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003765 }
3766 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003767 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003768 break;
3769 }
3770 // <builtin-type> ::= v # void
3771 case 'v':
3772 ++First;
3773 return make<NameType>("void");
3774 // ::= w # wchar_t
3775 case 'w':
3776 ++First;
3777 return make<NameType>("wchar_t");
3778 // ::= b # bool
3779 case 'b':
3780 ++First;
3781 return make<NameType>("bool");
3782 // ::= c # char
3783 case 'c':
3784 ++First;
3785 return make<NameType>("char");
3786 // ::= a # signed char
3787 case 'a':
3788 ++First;
3789 return make<NameType>("signed char");
3790 // ::= h # unsigned char
3791 case 'h':
3792 ++First;
3793 return make<NameType>("unsigned char");
3794 // ::= s # short
3795 case 's':
3796 ++First;
3797 return make<NameType>("short");
3798 // ::= t # unsigned short
3799 case 't':
3800 ++First;
3801 return make<NameType>("unsigned short");
3802 // ::= i # int
3803 case 'i':
3804 ++First;
3805 return make<NameType>("int");
3806 // ::= j # unsigned int
3807 case 'j':
3808 ++First;
3809 return make<NameType>("unsigned int");
3810 // ::= l # long
3811 case 'l':
3812 ++First;
3813 return make<NameType>("long");
3814 // ::= m # unsigned long
3815 case 'm':
3816 ++First;
3817 return make<NameType>("unsigned long");
3818 // ::= x # long long, __int64
3819 case 'x':
3820 ++First;
3821 return make<NameType>("long long");
3822 // ::= y # unsigned long long, __int64
3823 case 'y':
3824 ++First;
3825 return make<NameType>("unsigned long long");
3826 // ::= n # __int128
3827 case 'n':
3828 ++First;
3829 return make<NameType>("__int128");
3830 // ::= o # unsigned __int128
3831 case 'o':
3832 ++First;
3833 return make<NameType>("unsigned __int128");
3834 // ::= f # float
3835 case 'f':
3836 ++First;
3837 return make<NameType>("float");
3838 // ::= d # double
3839 case 'd':
3840 ++First;
3841 return make<NameType>("double");
3842 // ::= e # long double, __float80
3843 case 'e':
3844 ++First;
3845 return make<NameType>("long double");
3846 // ::= g # __float128
3847 case 'g':
3848 ++First;
3849 return make<NameType>("__float128");
3850 // ::= z # ellipsis
3851 case 'z':
3852 ++First;
3853 return make<NameType>("...");
3854
3855 // <builtin-type> ::= u <source-name> # vendor extended type
3856 case 'u': {
3857 ++First;
3858 StringView Res = parseBareSourceName();
3859 if (Res.empty())
3860 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003861 // Typically, <builtin-type>s are not considered substitution candidates,
3862 // but the exception to that exception is vendor extended types (Itanium C++
3863 // ABI 5.9.1).
3864 Result = make<NameType>(Res);
3865 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003866 }
3867 case 'D':
3868 switch (look(1)) {
3869 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3870 case 'd':
3871 First += 2;
3872 return make<NameType>("decimal64");
3873 // ::= De # IEEE 754r decimal floating point (128 bits)
3874 case 'e':
3875 First += 2;
3876 return make<NameType>("decimal128");
3877 // ::= Df # IEEE 754r decimal floating point (32 bits)
3878 case 'f':
3879 First += 2;
3880 return make<NameType>("decimal32");
3881 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3882 case 'h':
3883 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003884 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003885 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3886 case 'F': {
3887 First += 2;
3888 Node *DimensionNumber = make<NameType>(parseNumber());
3889 if (!DimensionNumber)
3890 return nullptr;
3891 if (!consumeIf('_'))
3892 return nullptr;
3893 return make<BinaryFPType>(DimensionNumber);
3894 }
Senran Zhange025ba52022-03-27 00:04:23 +08003895 // ::= DB <number> _ # C23 signed _BitInt(N)
3896 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
3897 // ::= DU <number> _ # C23 unsigned _BitInt(N)
3898 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
3899 case 'B':
3900 case 'U': {
3901 bool Signed = look(1) == 'B';
3902 First += 2;
3903 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())
3904 : getDerived().parseExpr();
3905 if (!Size)
3906 return nullptr;
3907 if (!consumeIf('_'))
3908 return nullptr;
3909 return make<BitIntType>(Size, Signed);
3910 }
Richard Smithc20d1442018-08-20 20:14:49 +00003911 // ::= Di # char32_t
3912 case 'i':
3913 First += 2;
3914 return make<NameType>("char32_t");
3915 // ::= Ds # char16_t
3916 case 's':
3917 First += 2;
3918 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003919 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3920 case 'u':
3921 First += 2;
3922 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003923 // ::= Da # auto (in dependent new-expressions)
3924 case 'a':
3925 First += 2;
3926 return make<NameType>("auto");
3927 // ::= Dc # decltype(auto)
3928 case 'c':
3929 First += 2;
3930 return make<NameType>("decltype(auto)");
3931 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3932 case 'n':
3933 First += 2;
3934 return make<NameType>("std::nullptr_t");
3935
3936 // ::= <decltype>
3937 case 't':
3938 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003939 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003940 break;
3941 }
3942 // extension ::= <vector-type> # <vector-type> starts with Dv
3943 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003944 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003945 break;
3946 }
3947 // ::= Dp <type> # pack expansion (C++0x)
3948 case 'p': {
3949 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003950 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003951 if (!Child)
3952 return nullptr;
3953 Result = make<ParameterPackExpansion>(Child);
3954 break;
3955 }
3956 // Exception specifier on a function type.
3957 case 'o':
3958 case 'O':
3959 case 'w':
3960 // Transaction safe function type.
3961 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003962 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003963 break;
3964 }
3965 break;
3966 // ::= <function-type>
3967 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003968 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003969 break;
3970 }
3971 // ::= <array-type>
3972 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003973 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003974 break;
3975 }
3976 // ::= <pointer-to-member-type>
3977 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003978 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003979 break;
3980 }
3981 // ::= <template-param>
3982 case 'T': {
3983 // This could be an elaborate type specifier on a <class-enum-type>.
3984 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00003985 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003986 break;
3987 }
3988
Pavel Labathba825192018-10-16 14:29:14 +00003989 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003990 if (Result == nullptr)
3991 return nullptr;
3992
3993 // Result could be either of:
3994 // <type> ::= <template-param>
3995 // <type> ::= <template-template-param> <template-args>
3996 //
3997 // <template-template-param> ::= <template-param>
3998 // ::= <substitution>
3999 //
4000 // If this is followed by some <template-args>, and we're permitted to
4001 // parse them, take the second production.
4002
4003 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004004 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004005 if (TA == nullptr)
4006 return nullptr;
4007 Result = make<NameWithTemplateArgs>(Result, TA);
4008 }
4009 break;
4010 }
4011 // ::= P <type> # pointer
4012 case 'P': {
4013 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004014 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004015 if (Ptr == nullptr)
4016 return nullptr;
4017 Result = make<PointerType>(Ptr);
4018 break;
4019 }
4020 // ::= R <type> # l-value reference
4021 case 'R': {
4022 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004023 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004024 if (Ref == nullptr)
4025 return nullptr;
4026 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4027 break;
4028 }
4029 // ::= O <type> # r-value reference (C++11)
4030 case 'O': {
4031 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004032 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004033 if (Ref == nullptr)
4034 return nullptr;
4035 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4036 break;
4037 }
4038 // ::= C <type> # complex pair (C99)
4039 case 'C': {
4040 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004041 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004042 if (P == nullptr)
4043 return nullptr;
4044 Result = make<PostfixQualifiedType>(P, " complex");
4045 break;
4046 }
4047 // ::= G <type> # imaginary (C99)
4048 case 'G': {
4049 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004050 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004051 if (P == nullptr)
4052 return P;
4053 Result = make<PostfixQualifiedType>(P, " imaginary");
4054 break;
4055 }
4056 // ::= <substitution> # See Compression below
4057 case 'S': {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004058 if (look(1) != 't') {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004059 bool IsSubst = false;
4060 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4061 if (!Result)
Richard Smithc20d1442018-08-20 20:14:49 +00004062 return nullptr;
4063
4064 // Sub could be either of:
4065 // <type> ::= <substitution>
4066 // <type> ::= <template-template-param> <template-args>
4067 //
4068 // <template-template-param> ::= <template-param>
4069 // ::= <substitution>
4070 //
4071 // If this is followed by some <template-args>, and we're permitted to
4072 // parse them, take the second production.
4073
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004074 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4075 if (!IsSubst)
4076 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00004077 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004078 if (TA == nullptr)
4079 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004080 Result = make<NameWithTemplateArgs>(Result, TA);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004081 } else if (IsSubst) {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004082 // If all we parsed was a substitution, don't re-insert into the
4083 // substitution table.
4084 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00004085 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004086 break;
Richard Smithc20d1442018-08-20 20:14:49 +00004087 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004088 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004089 }
4090 // ::= <class-enum-type>
4091 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004092 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004093 break;
4094 }
4095 }
4096
4097 // If we parsed a type, insert it into the substitution table. Note that all
4098 // <builtin-type>s and <substitution>s have already bailed out, because they
4099 // don't get substitutions.
4100 if (Result != nullptr)
4101 Subs.push_back(Result);
4102 return Result;
4103}
4104
Pavel Labathba825192018-10-16 14:29:14 +00004105template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004106Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4107 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004108 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004109 if (E == nullptr)
4110 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004111 return make<PrefixExpr>(Kind, E, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004112}
4113
Pavel Labathba825192018-10-16 14:29:14 +00004114template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004115Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4116 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004117 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004118 if (LHS == nullptr)
4119 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004120 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004121 if (RHS == nullptr)
4122 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004123 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004124}
4125
Pavel Labathba825192018-10-16 14:29:14 +00004126template <typename Derived, typename Alloc>
4127Node *
4128AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004129 StringView Tmp = parseNumber(true);
4130 if (!Tmp.empty() && consumeIf('E'))
4131 return make<IntegerLiteral>(Lit, Tmp);
4132 return nullptr;
4133}
4134
4135// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004136template <typename Alloc, typename Derived>
4137Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004138 Qualifiers CVR = QualNone;
4139 if (consumeIf('r'))
4140 CVR |= QualRestrict;
4141 if (consumeIf('V'))
4142 CVR |= QualVolatile;
4143 if (consumeIf('K'))
4144 CVR |= QualConst;
4145 return CVR;
4146}
4147
4148// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4149// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4150// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4151// ::= 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 -04004152// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004153template <typename Derived, typename Alloc>
4154Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004155 if (consumeIf("fpT"))
4156 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004157 if (consumeIf("fp")) {
4158 parseCVQualifiers();
4159 StringView Num = parseNumber();
4160 if (!consumeIf('_'))
4161 return nullptr;
4162 return make<FunctionParam>(Num);
4163 }
4164 if (consumeIf("fL")) {
4165 if (parseNumber().empty())
4166 return nullptr;
4167 if (!consumeIf('p'))
4168 return nullptr;
4169 parseCVQualifiers();
4170 StringView Num = parseNumber();
4171 if (!consumeIf('_'))
4172 return nullptr;
4173 return make<FunctionParam>(Num);
4174 }
4175 return nullptr;
4176}
4177
Richard Smithc20d1442018-08-20 20:14:49 +00004178// cv <type> <expression> # conversion with one argument
4179// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004180template <typename Derived, typename Alloc>
4181Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004182 if (!consumeIf("cv"))
4183 return nullptr;
4184 Node *Ty;
4185 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004186 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004187 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004188 }
4189
4190 if (Ty == nullptr)
4191 return nullptr;
4192
4193 if (consumeIf('_')) {
4194 size_t ExprsBegin = Names.size();
4195 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004196 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004197 if (E == nullptr)
4198 return E;
4199 Names.push_back(E);
4200 }
4201 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4202 return make<ConversionExpr>(Ty, Exprs);
4203 }
4204
Pavel Labathba825192018-10-16 14:29:14 +00004205 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004206 if (E[0] == nullptr)
4207 return nullptr;
4208 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4209}
4210
4211// <expr-primary> ::= L <type> <value number> E # integer literal
4212// ::= L <type> <value float> E # floating literal
4213// ::= L <string type> E # string literal
4214// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004215// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004216// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4217// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004218template <typename Derived, typename Alloc>
4219Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004220 if (!consumeIf('L'))
4221 return nullptr;
4222 switch (look()) {
4223 case 'w':
4224 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004225 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004226 case 'b':
4227 if (consumeIf("b0E"))
4228 return make<BoolExpr>(0);
4229 if (consumeIf("b1E"))
4230 return make<BoolExpr>(1);
4231 return nullptr;
4232 case 'c':
4233 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004234 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004235 case 'a':
4236 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004237 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004238 case 'h':
4239 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004240 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004241 case 's':
4242 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004243 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004244 case 't':
4245 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004246 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004247 case 'i':
4248 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004249 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004250 case 'j':
4251 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004252 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004253 case 'l':
4254 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004255 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004256 case 'm':
4257 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004258 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004259 case 'x':
4260 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004261 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004262 case 'y':
4263 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004264 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004265 case 'n':
4266 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004267 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004268 case 'o':
4269 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004270 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004271 case 'f':
4272 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004273 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004274 case 'd':
4275 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004276 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004277 case 'e':
4278 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004279#if defined(__powerpc__) || defined(__s390__)
4280 // Handle cases where long doubles encoded with e have the same size
4281 // and representation as doubles.
4282 return getDerived().template parseFloatingLiteral<double>();
4283#else
Pavel Labathba825192018-10-16 14:29:14 +00004284 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004285#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004286 case '_':
4287 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004288 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004289 if (R != nullptr && consumeIf('E'))
4290 return R;
4291 }
4292 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004293 case 'A': {
4294 Node *T = getDerived().parseType();
4295 if (T == nullptr)
4296 return nullptr;
4297 // FIXME: We need to include the string contents in the mangling.
4298 if (consumeIf('E'))
4299 return make<StringLiteral>(T);
4300 return nullptr;
4301 }
4302 case 'D':
gbreynooc0559322022-04-28 15:55:26 +01004303 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
Richard Smithdf1c14c2019-09-06 23:53:21 +00004304 return make<NameType>("nullptr");
4305 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004306 case 'T':
4307 // Invalid mangled name per
4308 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4309 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004310 case 'U': {
4311 // FIXME: Should we support LUb... for block literals?
4312 if (look(1) != 'l')
4313 return nullptr;
4314 Node *T = parseUnnamedTypeName(nullptr);
4315 if (!T || !consumeIf('E'))
4316 return nullptr;
4317 return make<LambdaExpr>(T);
4318 }
Richard Smithc20d1442018-08-20 20:14:49 +00004319 default: {
4320 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004321 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004322 if (T == nullptr)
4323 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004324 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004325 if (N.empty())
4326 return nullptr;
4327 if (!consumeIf('E'))
4328 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004329 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004330 }
4331 }
4332}
4333
4334// <braced-expression> ::= <expression>
4335// ::= di <field source-name> <braced-expression> # .name = expr
4336// ::= dx <index expression> <braced-expression> # [expr] = expr
4337// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004338template <typename Derived, typename Alloc>
4339Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004340 if (look() == 'd') {
4341 switch (look(1)) {
4342 case 'i': {
4343 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004344 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004345 if (Field == nullptr)
4346 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004347 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004348 if (Init == nullptr)
4349 return nullptr;
4350 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4351 }
4352 case 'x': {
4353 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004354 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004355 if (Index == nullptr)
4356 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004357 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004358 if (Init == nullptr)
4359 return nullptr;
4360 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4361 }
4362 case 'X': {
4363 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004364 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004365 if (RangeBegin == nullptr)
4366 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004367 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004368 if (RangeEnd == nullptr)
4369 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004370 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004371 if (Init == nullptr)
4372 return nullptr;
4373 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4374 }
4375 }
4376 }
Pavel Labathba825192018-10-16 14:29:14 +00004377 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004378}
4379
4380// (not yet in the spec)
4381// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4382// ::= fR <binary-operator-name> <expression> <expression>
4383// ::= fl <binary-operator-name> <expression>
4384// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004385template <typename Derived, typename Alloc>
4386Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004387 if (!consumeIf('f'))
4388 return nullptr;
4389
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004390 bool IsLeftFold = false, HasInitializer = false;
4391 switch (look()) {
4392 default:
Richard Smithc20d1442018-08-20 20:14:49 +00004393 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004394 case 'L':
4395 IsLeftFold = true;
4396 HasInitializer = true;
4397 break;
4398 case 'R':
4399 HasInitializer = true;
4400 break;
4401 case 'l':
4402 IsLeftFold = true;
4403 break;
4404 case 'r':
4405 break;
4406 }
Richard Smithc20d1442018-08-20 20:14:49 +00004407 ++First;
4408
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004409 const auto *Op = parseOperatorEncoding();
Nathan Sidwellce967252022-02-18 11:06:58 -08004410 if (!Op)
4411 return nullptr;
4412 if (!(Op->getKind() == OperatorInfo::Binary
4413 || (Op->getKind() == OperatorInfo::Member
4414 && Op->getName().back() == '*')))
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004415 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004416
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004417 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004418 if (Pack == nullptr)
4419 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004420
4421 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004422 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004423 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004424 if (Init == nullptr)
4425 return nullptr;
4426 }
4427
4428 if (IsLeftFold && Init)
4429 std::swap(Pack, Init);
4430
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004431 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004432}
4433
Richard Smith1865d2f2020-10-22 19:29:36 -07004434// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4435//
4436// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4437template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004438Node *
4439AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4440 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004441 Node *Ty = getDerived().parseType();
4442 if (!Ty)
4443 return nullptr;
4444 Node *Expr = getDerived().parseExpr();
4445 if (!Expr)
4446 return nullptr;
4447 StringView Offset = getDerived().parseNumber(true);
4448 if (!consumeIf('E'))
4449 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004450 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004451}
4452
4453// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4454// <union-selector> ::= _ [<number>]
4455//
4456// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4457template <typename Derived, typename Alloc>
4458Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4459 Node *Ty = getDerived().parseType();
4460 if (!Ty)
4461 return nullptr;
4462 Node *Expr = getDerived().parseExpr();
4463 if (!Expr)
4464 return nullptr;
4465 StringView Offset = getDerived().parseNumber(true);
4466 size_t SelectorsBegin = Names.size();
4467 while (consumeIf('_')) {
4468 Node *Selector = make<NameType>(parseNumber());
4469 if (!Selector)
4470 return nullptr;
4471 Names.push_back(Selector);
4472 }
4473 bool OnePastTheEnd = consumeIf('p');
4474 if (!consumeIf('E'))
4475 return nullptr;
4476 return make<SubobjectExpr>(
4477 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4478}
4479
Richard Smithc20d1442018-08-20 20:14:49 +00004480// <expression> ::= <unary operator-name> <expression>
4481// ::= <binary operator-name> <expression> <expression>
4482// ::= <ternary operator-name> <expression> <expression> <expression>
4483// ::= cl <expression>+ E # call
4484// ::= cv <type> <expression> # conversion with one argument
4485// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4486// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4487// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4488// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4489// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4490// ::= [gs] dl <expression> # delete expression
4491// ::= [gs] da <expression> # delete[] expression
4492// ::= pp_ <expression> # prefix ++
4493// ::= mm_ <expression> # prefix --
4494// ::= ti <type> # typeid (type)
4495// ::= te <expression> # typeid (expression)
4496// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4497// ::= sc <type> <expression> # static_cast<type> (expression)
4498// ::= cc <type> <expression> # const_cast<type> (expression)
4499// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4500// ::= st <type> # sizeof (a type)
4501// ::= sz <expression> # sizeof (an expression)
4502// ::= at <type> # alignof (a type)
4503// ::= az <expression> # alignof (an expression)
4504// ::= nx <expression> # noexcept (expression)
4505// ::= <template-param>
4506// ::= <function-param>
4507// ::= dt <expression> <unresolved-name> # expr.name
4508// ::= pt <expression> <unresolved-name> # expr->name
4509// ::= ds <expression> <expression> # expr.*expr
4510// ::= sZ <template-param> # size of a parameter pack
4511// ::= sZ <function-param> # size of a function parameter pack
4512// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4513// ::= sp <expression> # pack expansion
4514// ::= tw <expression> # throw expression
4515// ::= tr # throw with no operand (rethrow)
4516// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4517// # freestanding dependent name (e.g., T::x),
4518// # objectless nonstatic member reference
4519// ::= fL <binary-operator-name> <expression> <expression>
4520// ::= fR <binary-operator-name> <expression> <expression>
4521// ::= fl <binary-operator-name> <expression>
4522// ::= fr <binary-operator-name> <expression>
4523// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004524template <typename Derived, typename Alloc>
4525Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004526 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004527
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004528 const auto *Op = parseOperatorEncoding();
4529 if (Op) {
4530 auto Sym = Op->getSymbol();
4531 switch (Op->getKind()) {
4532 case OperatorInfo::Binary:
4533 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004534 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004535 case OperatorInfo::Prefix:
4536 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004537 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004538 case OperatorInfo::Postfix: {
4539 // Postfix unary operator: expr @
4540 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004541 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004542 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004543 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004544 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004545 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004546 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004547 case OperatorInfo::Array: {
4548 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004549 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004550 if (Base == nullptr)
4551 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004552 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004553 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004554 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004555 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004556 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004557 case OperatorInfo::Member: {
4558 // Member access lhs @ rhs
4559 Node *LHS = getDerived().parseExpr();
4560 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004561 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004562 Node *RHS = getDerived().parseExpr();
4563 if (RHS == nullptr)
4564 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004565 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004566 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004567 case OperatorInfo::New: {
4568 // New
4569 // # new (expr-list) type [(init)]
4570 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4571 // # new[] (expr-list) type [(init)]
4572 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004573 size_t Exprs = Names.size();
4574 while (!consumeIf('_')) {
4575 Node *Ex = getDerived().parseExpr();
4576 if (Ex == nullptr)
4577 return nullptr;
4578 Names.push_back(Ex);
4579 }
4580 NodeArray ExprList = popTrailingNodeArray(Exprs);
4581 Node *Ty = getDerived().parseType();
4582 if (Ty == nullptr)
4583 return nullptr;
4584 bool HaveInits = consumeIf("pi");
4585 size_t InitsBegin = Names.size();
4586 while (!consumeIf('E')) {
4587 if (!HaveInits)
4588 return nullptr;
4589 Node *Init = getDerived().parseExpr();
4590 if (Init == nullptr)
4591 return Init;
4592 Names.push_back(Init);
4593 }
4594 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004595 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004596 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004597 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004598 case OperatorInfo::Del: {
4599 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004600 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004601 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004602 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004603 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4604 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004605 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004606 case OperatorInfo::Call: {
4607 // Function Call
4608 Node *Callee = getDerived().parseExpr();
4609 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004610 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004611 size_t ExprsBegin = Names.size();
4612 while (!consumeIf('E')) {
4613 Node *E = getDerived().parseExpr();
4614 if (E == nullptr)
4615 return nullptr;
4616 Names.push_back(E);
4617 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004618 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4619 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004620 }
4621 case OperatorInfo::CCast: {
4622 // C Cast: (type)expr
4623 Node *Ty;
4624 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004625 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004626 Ty = getDerived().parseType();
4627 }
4628 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004629 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004630
4631 size_t ExprsBegin = Names.size();
4632 bool IsMany = consumeIf('_');
4633 while (!consumeIf('E')) {
4634 Node *E = getDerived().parseExpr();
4635 if (E == nullptr)
4636 return E;
4637 Names.push_back(E);
4638 if (!IsMany)
4639 break;
4640 }
4641 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4642 if (!IsMany && Exprs.size() != 1)
4643 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004644 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004645 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004646 case OperatorInfo::Conditional: {
4647 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004648 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004649 if (Cond == nullptr)
4650 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004651 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004652 if (LHS == nullptr)
4653 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004654 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004655 if (RHS == nullptr)
4656 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004657 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004658 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004659 case OperatorInfo::NamedCast: {
4660 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004661 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004662 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004663 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004664 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004665 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004666 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004667 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004668 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004669 case OperatorInfo::OfIdOp: {
4670 // [sizeof/alignof/typeid] ( <type>|<expr> )
4671 Node *Arg =
4672 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4673 if (!Arg)
4674 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004675 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004676 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004677 case OperatorInfo::NameOnly: {
4678 // Not valid as an expression operand.
4679 return nullptr;
4680 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004681 }
4682 DEMANGLE_UNREACHABLE;
4683 }
4684
4685 if (numLeft() < 2)
4686 return nullptr;
4687
4688 if (look() == 'L')
4689 return getDerived().parseExprPrimary();
4690 if (look() == 'T')
4691 return getDerived().parseTemplateParam();
4692 if (look() == 'f') {
4693 // Disambiguate a fold expression from a <function-param>.
4694 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4695 return getDerived().parseFunctionParam();
4696 return getDerived().parseFoldExpr();
4697 }
4698 if (consumeIf("il")) {
4699 size_t InitsBegin = Names.size();
4700 while (!consumeIf('E')) {
4701 Node *E = getDerived().parseBracedExpr();
4702 if (E == nullptr)
4703 return nullptr;
4704 Names.push_back(E);
4705 }
4706 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4707 }
4708 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004709 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004710 if (consumeIf("nx")) {
4711 Node *Ex = getDerived().parseExpr();
4712 if (Ex == nullptr)
4713 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004714 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004715 }
4716 if (consumeIf("so"))
4717 return parseSubobjectExpr();
4718 if (consumeIf("sp")) {
4719 Node *Child = getDerived().parseExpr();
4720 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004721 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004722 return make<ParameterPackExpansion>(Child);
4723 }
4724 if (consumeIf("sZ")) {
4725 if (look() == 'T') {
4726 Node *R = getDerived().parseTemplateParam();
4727 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004728 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004729 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004730 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004731 Node *FP = getDerived().parseFunctionParam();
4732 if (FP == nullptr)
4733 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004734 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004735 }
4736 if (consumeIf("sP")) {
4737 size_t ArgsBegin = Names.size();
4738 while (!consumeIf('E')) {
4739 Node *Arg = getDerived().parseTemplateArg();
4740 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004741 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004742 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004743 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004744 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4745 if (!Pack)
4746 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004747 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004748 }
4749 if (consumeIf("tl")) {
4750 Node *Ty = getDerived().parseType();
4751 if (Ty == nullptr)
4752 return nullptr;
4753 size_t InitsBegin = Names.size();
4754 while (!consumeIf('E')) {
4755 Node *E = getDerived().parseBracedExpr();
4756 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004757 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004758 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004759 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004760 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4761 }
4762 if (consumeIf("tr"))
4763 return make<NameType>("throw");
4764 if (consumeIf("tw")) {
4765 Node *Ex = getDerived().parseExpr();
4766 if (Ex == nullptr)
4767 return nullptr;
4768 return make<ThrowExpr>(Ex);
4769 }
4770 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004771 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4772 if (!Name)
4773 return nullptr;
4774 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4775 // standard encoding expects a <template-arg>, and would be otherwise be
4776 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4777 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4778 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004779 bool IsUUID = false;
4780 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004781 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004782 if (consumeIf('t')) {
4783 UUID = getDerived().parseType();
4784 IsUUID = true;
4785 } else if (consumeIf('z')) {
4786 UUID = getDerived().parseExpr();
4787 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004788 }
4789 }
4790 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004791 if (IsUUID) {
4792 if (UUID == nullptr)
4793 return nullptr;
4794 Names.push_back(UUID);
4795 } else {
4796 while (!consumeIf('E')) {
4797 Node *E = getDerived().parseTemplateArg();
4798 if (E == nullptr)
4799 return E;
4800 Names.push_back(E);
4801 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004802 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004803 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4804 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004805 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004806
4807 // Only unresolved names remain.
4808 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004809}
4810
4811// <call-offset> ::= h <nv-offset> _
4812// ::= v <v-offset> _
4813//
4814// <nv-offset> ::= <offset number>
4815// # non-virtual base override
4816//
4817// <v-offset> ::= <offset number> _ <virtual offset number>
4818// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004819template <typename Alloc, typename Derived>
4820bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004821 // Just scan through the call offset, we never add this information into the
4822 // output.
4823 if (consumeIf('h'))
4824 return parseNumber(true).empty() || !consumeIf('_');
4825 if (consumeIf('v'))
4826 return parseNumber(true).empty() || !consumeIf('_') ||
4827 parseNumber(true).empty() || !consumeIf('_');
4828 return true;
4829}
4830
4831// <special-name> ::= TV <type> # virtual table
4832// ::= TT <type> # VTT structure (construction vtable index)
4833// ::= TI <type> # typeinfo structure
4834// ::= TS <type> # typeinfo name (null-terminated byte string)
4835// ::= Tc <call-offset> <call-offset> <base encoding>
4836// # base is the nominal target function of thunk
4837// # first call-offset is 'this' adjustment
4838// # second call-offset is result adjustment
4839// ::= T <call-offset> <base encoding>
4840// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004841// # Guard variable for one-time initialization
4842// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004843// # No <type>
4844// ::= TW <object name> # Thread-local wrapper
4845// ::= TH <object name> # Thread-local initialization
4846// ::= GR <object name> _ # First temporary
4847// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004848// # construction vtable for second-in-first
4849// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004850// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004851// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004852template <typename Derived, typename Alloc>
4853Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004854 switch (look()) {
4855 case 'T':
4856 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004857 // TA <template-arg> # template parameter object
4858 //
4859 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4860 case 'A': {
4861 First += 2;
4862 Node *Arg = getDerived().parseTemplateArg();
4863 if (Arg == nullptr)
4864 return nullptr;
4865 return make<SpecialName>("template parameter object for ", Arg);
4866 }
Richard Smithc20d1442018-08-20 20:14:49 +00004867 // TV <type> # virtual table
4868 case 'V': {
4869 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004870 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004871 if (Ty == nullptr)
4872 return nullptr;
4873 return make<SpecialName>("vtable for ", Ty);
4874 }
4875 // TT <type> # VTT structure (construction vtable index)
4876 case 'T': {
4877 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004878 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004879 if (Ty == nullptr)
4880 return nullptr;
4881 return make<SpecialName>("VTT for ", Ty);
4882 }
4883 // TI <type> # typeinfo structure
4884 case 'I': {
4885 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004886 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004887 if (Ty == nullptr)
4888 return nullptr;
4889 return make<SpecialName>("typeinfo for ", Ty);
4890 }
4891 // TS <type> # typeinfo name (null-terminated byte string)
4892 case 'S': {
4893 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004894 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004895 if (Ty == nullptr)
4896 return nullptr;
4897 return make<SpecialName>("typeinfo name for ", Ty);
4898 }
4899 // Tc <call-offset> <call-offset> <base encoding>
4900 case 'c': {
4901 First += 2;
4902 if (parseCallOffset() || parseCallOffset())
4903 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004904 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004905 if (Encoding == nullptr)
4906 return nullptr;
4907 return make<SpecialName>("covariant return thunk to ", Encoding);
4908 }
4909 // extension ::= TC <first type> <number> _ <second type>
4910 // # construction vtable for second-in-first
4911 case 'C': {
4912 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004913 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004914 if (FirstType == nullptr)
4915 return nullptr;
4916 if (parseNumber(true).empty() || !consumeIf('_'))
4917 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004918 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004919 if (SecondType == nullptr)
4920 return nullptr;
4921 return make<CtorVtableSpecialName>(SecondType, FirstType);
4922 }
4923 // TW <object name> # Thread-local wrapper
4924 case 'W': {
4925 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004926 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004927 if (Name == nullptr)
4928 return nullptr;
4929 return make<SpecialName>("thread-local wrapper routine for ", Name);
4930 }
4931 // TH <object name> # Thread-local initialization
4932 case 'H': {
4933 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004934 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004935 if (Name == nullptr)
4936 return nullptr;
4937 return make<SpecialName>("thread-local initialization routine for ", Name);
4938 }
4939 // T <call-offset> <base encoding>
4940 default: {
4941 ++First;
4942 bool IsVirt = look() == 'v';
4943 if (parseCallOffset())
4944 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004945 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004946 if (BaseEncoding == nullptr)
4947 return nullptr;
4948 if (IsVirt)
4949 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4950 else
4951 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4952 }
4953 }
4954 case 'G':
4955 switch (look(1)) {
4956 // GV <object name> # Guard variable for one-time initialization
4957 case 'V': {
4958 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004959 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004960 if (Name == nullptr)
4961 return nullptr;
4962 return make<SpecialName>("guard variable for ", Name);
4963 }
4964 // GR <object name> # reference temporary for object
4965 // GR <object name> _ # First temporary
4966 // GR <object name> <seq-id> _ # Subsequent temporaries
4967 case 'R': {
4968 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004969 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004970 if (Name == nullptr)
4971 return nullptr;
4972 size_t Count;
4973 bool ParsedSeqId = !parseSeqId(&Count);
4974 if (!consumeIf('_') && ParsedSeqId)
4975 return nullptr;
4976 return make<SpecialName>("reference temporary for ", Name);
4977 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004978 // GI <module-name> v
4979 case 'I': {
4980 First += 2;
4981 ModuleName *Module = nullptr;
4982 if (getDerived().parseModuleNameOpt(Module))
4983 return nullptr;
4984 if (Module == nullptr)
4985 return nullptr;
4986 return make<SpecialName>("initializer for module ", Module);
4987 }
Richard Smithc20d1442018-08-20 20:14:49 +00004988 }
4989 }
4990 return nullptr;
4991}
4992
4993// <encoding> ::= <function name> <bare-function-type>
4994// ::= <data name>
4995// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00004996template <typename Derived, typename Alloc>
4997Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07004998 // The template parameters of an encoding are unrelated to those of the
4999 // enclosing context.
5000 class SaveTemplateParams {
5001 AbstractManglingParser *Parser;
5002 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005003 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005004
5005 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005006 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005007 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005008 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005009 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005010 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005011 }
5012 ~SaveTemplateParams() {
5013 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005014 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005015 }
5016 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005017
Richard Smithc20d1442018-08-20 20:14:49 +00005018 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005019 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005020
5021 auto IsEndOfEncoding = [&] {
5022 // The set of chars that can potentially follow an <encoding> (none of which
5023 // can start a <type>). Enumerating these allows us to avoid speculative
5024 // parsing.
5025 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5026 };
5027
5028 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005029 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005030 if (Name == nullptr)
5031 return nullptr;
5032
5033 if (resolveForwardTemplateRefs(NameInfo))
5034 return nullptr;
5035
5036 if (IsEndOfEncoding())
5037 return Name;
5038
5039 Node *Attrs = nullptr;
5040 if (consumeIf("Ua9enable_ifI")) {
5041 size_t BeforeArgs = Names.size();
5042 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005043 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005044 if (Arg == nullptr)
5045 return nullptr;
5046 Names.push_back(Arg);
5047 }
5048 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005049 if (!Attrs)
5050 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005051 }
5052
5053 Node *ReturnType = nullptr;
5054 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005055 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005056 if (ReturnType == nullptr)
5057 return nullptr;
5058 }
5059
5060 if (consumeIf('v'))
5061 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5062 Attrs, NameInfo.CVQualifiers,
5063 NameInfo.ReferenceQualifier);
5064
5065 size_t ParamsBegin = Names.size();
5066 do {
Pavel Labathba825192018-10-16 14:29:14 +00005067 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005068 if (Ty == nullptr)
5069 return nullptr;
5070 Names.push_back(Ty);
5071 } while (!IsEndOfEncoding());
5072
5073 return make<FunctionEncoding>(ReturnType, Name,
5074 popTrailingNodeArray(ParamsBegin),
5075 Attrs, NameInfo.CVQualifiers,
5076 NameInfo.ReferenceQualifier);
5077}
5078
5079template <class Float>
5080struct FloatData;
5081
5082template <>
5083struct FloatData<float>
5084{
5085 static const size_t mangled_size = 8;
5086 static const size_t max_demangled_size = 24;
5087 static constexpr const char* spec = "%af";
5088};
5089
5090template <>
5091struct FloatData<double>
5092{
5093 static const size_t mangled_size = 16;
5094 static const size_t max_demangled_size = 32;
5095 static constexpr const char* spec = "%a";
5096};
5097
5098template <>
5099struct FloatData<long double>
5100{
5101#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5102 defined(__wasm__)
5103 static const size_t mangled_size = 32;
5104#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5105 static const size_t mangled_size = 16;
5106#else
5107 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5108#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005109 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5110 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5111 // Negatives are one character longer than positives.
5112 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5113 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5114 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005115 static constexpr const char *spec = "%LaL";
5116};
5117
Pavel Labathba825192018-10-16 14:29:14 +00005118template <typename Alloc, typename Derived>
5119template <class Float>
5120Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005121 const size_t N = FloatData<Float>::mangled_size;
5122 if (numLeft() <= N)
5123 return nullptr;
5124 StringView Data(First, First + N);
5125 for (char C : Data)
5126 if (!std::isxdigit(C))
5127 return nullptr;
5128 First += N;
5129 if (!consumeIf('E'))
5130 return nullptr;
5131 return make<FloatLiteralImpl<Float>>(Data);
5132}
5133
5134// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005135template <typename Alloc, typename Derived>
5136bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005137 if (!(look() >= '0' && look() <= '9') &&
5138 !(look() >= 'A' && look() <= 'Z'))
5139 return true;
5140
5141 size_t Id = 0;
5142 while (true) {
5143 if (look() >= '0' && look() <= '9') {
5144 Id *= 36;
5145 Id += static_cast<size_t>(look() - '0');
5146 } else if (look() >= 'A' && look() <= 'Z') {
5147 Id *= 36;
5148 Id += static_cast<size_t>(look() - 'A') + 10;
5149 } else {
5150 *Out = Id;
5151 return false;
5152 }
5153 ++First;
5154 }
5155}
5156
5157// <substitution> ::= S <seq-id> _
5158// ::= S_
5159// <substitution> ::= Sa # ::std::allocator
5160// <substitution> ::= Sb # ::std::basic_string
5161// <substitution> ::= Ss # ::std::basic_string < char,
5162// ::std::char_traits<char>,
5163// ::std::allocator<char> >
5164// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5165// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5166// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005167// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005168template <typename Derived, typename Alloc>
5169Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005170 if (!consumeIf('S'))
5171 return nullptr;
5172
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005173 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005174 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005175 switch (look()) {
5176 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005177 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005178 break;
5179 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005180 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005181 break;
5182 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005183 Kind = SpecialSubKind::iostream;
5184 break;
5185 case 'i':
5186 Kind = SpecialSubKind::istream;
5187 break;
5188 case 'o':
5189 Kind = SpecialSubKind::ostream;
5190 break;
5191 case 's':
5192 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005193 break;
5194 default:
5195 return nullptr;
5196 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005197 ++First;
5198 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005199 if (!SpecialSub)
5200 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005201
Richard Smithc20d1442018-08-20 20:14:49 +00005202 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5203 // has ABI tags, the tags are appended to the substitution; the result is a
5204 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005205 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005206 if (WithTags != SpecialSub) {
5207 Subs.push_back(WithTags);
5208 SpecialSub = WithTags;
5209 }
5210 return SpecialSub;
5211 }
5212
5213 // ::= S_
5214 if (consumeIf('_')) {
5215 if (Subs.empty())
5216 return nullptr;
5217 return Subs[0];
5218 }
5219
5220 // ::= S <seq-id> _
5221 size_t Index = 0;
5222 if (parseSeqId(&Index))
5223 return nullptr;
5224 ++Index;
5225 if (!consumeIf('_') || Index >= Subs.size())
5226 return nullptr;
5227 return Subs[Index];
5228}
5229
5230// <template-param> ::= T_ # first template parameter
5231// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005232// ::= TL <level-1> __
5233// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005234template <typename Derived, typename Alloc>
5235Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005236 if (!consumeIf('T'))
5237 return nullptr;
5238
Richard Smithdf1c14c2019-09-06 23:53:21 +00005239 size_t Level = 0;
5240 if (consumeIf('L')) {
5241 if (parsePositiveInteger(&Level))
5242 return nullptr;
5243 ++Level;
5244 if (!consumeIf('_'))
5245 return nullptr;
5246 }
5247
Richard Smithc20d1442018-08-20 20:14:49 +00005248 size_t Index = 0;
5249 if (!consumeIf('_')) {
5250 if (parsePositiveInteger(&Index))
5251 return nullptr;
5252 ++Index;
5253 if (!consumeIf('_'))
5254 return nullptr;
5255 }
5256
Richard Smithc20d1442018-08-20 20:14:49 +00005257 // If we're in a context where this <template-param> refers to a
5258 // <template-arg> further ahead in the mangled name (currently just conversion
5259 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005260 // This can only happen at the outermost level.
5261 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005262 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5263 if (!ForwardRef)
5264 return nullptr;
5265 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5266 ForwardTemplateRefs.push_back(
5267 static_cast<ForwardTemplateReference *>(ForwardRef));
5268 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005269 }
5270
Richard Smithdf1c14c2019-09-06 23:53:21 +00005271 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5272 Index >= TemplateParams[Level]->size()) {
5273 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5274 // list are mangled as the corresponding artificial template type parameter.
5275 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5276 // This will be popped by the ScopedTemplateParamList in
5277 // parseUnnamedTypeName.
5278 if (Level == TemplateParams.size())
5279 TemplateParams.push_back(nullptr);
5280 return make<NameType>("auto");
5281 }
5282
Richard Smithc20d1442018-08-20 20:14:49 +00005283 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005284 }
5285
5286 return (*TemplateParams[Level])[Index];
5287}
5288
5289// <template-param-decl> ::= Ty # type parameter
5290// ::= Tn <type> # non-type parameter
5291// ::= Tt <template-param-decl>* E # template parameter
5292// ::= Tp <template-param-decl> # parameter pack
5293template <typename Derived, typename Alloc>
5294Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5295 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5296 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5297 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5298 if (N) TemplateParams.back()->push_back(N);
5299 return N;
5300 };
5301
5302 if (consumeIf("Ty")) {
5303 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5304 if (!Name)
5305 return nullptr;
5306 return make<TypeTemplateParamDecl>(Name);
5307 }
5308
5309 if (consumeIf("Tn")) {
5310 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5311 if (!Name)
5312 return nullptr;
5313 Node *Type = parseType();
5314 if (!Type)
5315 return nullptr;
5316 return make<NonTypeTemplateParamDecl>(Name, Type);
5317 }
5318
5319 if (consumeIf("Tt")) {
5320 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5321 if (!Name)
5322 return nullptr;
5323 size_t ParamsBegin = Names.size();
5324 ScopedTemplateParamList TemplateTemplateParamParams(this);
5325 while (!consumeIf("E")) {
5326 Node *P = parseTemplateParamDecl();
5327 if (!P)
5328 return nullptr;
5329 Names.push_back(P);
5330 }
5331 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5332 return make<TemplateTemplateParamDecl>(Name, Params);
5333 }
5334
5335 if (consumeIf("Tp")) {
5336 Node *P = parseTemplateParamDecl();
5337 if (!P)
5338 return nullptr;
5339 return make<TemplateParamPackDecl>(P);
5340 }
5341
5342 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005343}
5344
5345// <template-arg> ::= <type> # type or template
5346// ::= X <expression> E # expression
5347// ::= <expr-primary> # simple expressions
5348// ::= J <template-arg>* E # argument pack
5349// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005350template <typename Derived, typename Alloc>
5351Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005352 switch (look()) {
5353 case 'X': {
5354 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005355 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005356 if (Arg == nullptr || !consumeIf('E'))
5357 return nullptr;
5358 return Arg;
5359 }
5360 case 'J': {
5361 ++First;
5362 size_t ArgsBegin = Names.size();
5363 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005364 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005365 if (Arg == nullptr)
5366 return nullptr;
5367 Names.push_back(Arg);
5368 }
5369 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5370 return make<TemplateArgumentPack>(Args);
5371 }
5372 case 'L': {
5373 // ::= LZ <encoding> E # extension
5374 if (look(1) == 'Z') {
5375 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005376 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005377 if (Arg == nullptr || !consumeIf('E'))
5378 return nullptr;
5379 return Arg;
5380 }
5381 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005382 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005383 }
5384 default:
Pavel Labathba825192018-10-16 14:29:14 +00005385 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005386 }
5387}
5388
5389// <template-args> ::= I <template-arg>* E
5390// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005391template <typename Derived, typename Alloc>
5392Node *
5393AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005394 if (!consumeIf('I'))
5395 return nullptr;
5396
5397 // <template-params> refer to the innermost <template-args>. Clear out any
5398 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005399 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005400 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005401 TemplateParams.push_back(&OuterTemplateParams);
5402 OuterTemplateParams.clear();
5403 }
Richard Smithc20d1442018-08-20 20:14:49 +00005404
5405 size_t ArgsBegin = Names.size();
5406 while (!consumeIf('E')) {
5407 if (TagTemplates) {
5408 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005409 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005410 TemplateParams = std::move(OldParams);
5411 if (Arg == nullptr)
5412 return nullptr;
5413 Names.push_back(Arg);
5414 Node *TableEntry = Arg;
5415 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5416 TableEntry = make<ParameterPack>(
5417 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005418 if (!TableEntry)
5419 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005420 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005421 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005422 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005423 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005424 if (Arg == nullptr)
5425 return nullptr;
5426 Names.push_back(Arg);
5427 }
5428 }
5429 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5430}
5431
5432// <mangled-name> ::= _Z <encoding>
5433// ::= <type>
5434// extension ::= ___Z <encoding> _block_invoke
5435// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5436// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005437template <typename Derived, typename Alloc>
5438Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005439 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005440 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005441 if (Encoding == nullptr)
5442 return nullptr;
5443 if (look() == '.') {
5444 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5445 First = Last;
5446 }
5447 if (numLeft() != 0)
5448 return nullptr;
5449 return Encoding;
5450 }
5451
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005452 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005453 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005454 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5455 return nullptr;
5456 bool RequireNumber = consumeIf('_');
5457 if (parseNumber().empty() && RequireNumber)
5458 return nullptr;
5459 if (look() == '.')
5460 First = Last;
5461 if (numLeft() != 0)
5462 return nullptr;
5463 return make<SpecialName>("invocation function for block in ", Encoding);
5464 }
5465
Pavel Labathba825192018-10-16 14:29:14 +00005466 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005467 if (numLeft() != 0)
5468 return nullptr;
5469 return Ty;
5470}
5471
Pavel Labathba825192018-10-16 14:29:14 +00005472template <typename Alloc>
5473struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5474 using AbstractManglingParser<ManglingParser<Alloc>,
5475 Alloc>::AbstractManglingParser;
5476};
5477
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005478DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005479
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005480#endif // DEMANGLE_ITANIUMDEMANGLE_H