blob: 90f62bab0bd9f48ac49b013b07b141805904c27d [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);
1384 if (OB.back() == '>')
1385 OB += " ";
1386 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +00001387 }
1388};
1389
Richard Smithb485b352018-08-24 23:30:26 +00001390/// A forward-reference to a template argument that was not known at the point
1391/// where the template parameter name was parsed in a mangling.
1392///
1393/// This is created when demangling the name of a specialization of a
1394/// conversion function template:
1395///
1396/// \code
1397/// struct A {
1398/// template<typename T> operator T*();
1399/// };
1400/// \endcode
1401///
1402/// When demangling a specialization of the conversion function template, we
1403/// encounter the name of the template (including the \c T) before we reach
1404/// the template argument list, so we cannot substitute the parameter name
1405/// for the corresponding argument while parsing. Instead, we create a
1406/// \c ForwardTemplateReference node that is resolved after we parse the
1407/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001408struct ForwardTemplateReference : Node {
1409 size_t Index;
1410 Node *Ref = nullptr;
1411
1412 // If we're currently printing this node. It is possible (though invalid) for
1413 // a forward template reference to refer to itself via a substitution. This
1414 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1415 // out if more than one print* function is active.
1416 mutable bool Printing = false;
1417
1418 ForwardTemplateReference(size_t Index_)
1419 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1420 Cache::Unknown),
1421 Index(Index_) {}
1422
1423 // We don't provide a matcher for these, because the value of the node is
1424 // not determined by its construction parameters, and it generally needs
1425 // special handling.
1426 template<typename Fn> void match(Fn F) const = delete;
1427
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001428 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001429 if (Printing)
1430 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001431 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001432 return Ref->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001433 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001434 bool hasArraySlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001435 if (Printing)
1436 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001437 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001438 return Ref->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001439 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001440 bool hasFunctionSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001441 if (Printing)
1442 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001443 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001444 return Ref->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001445 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001446 const Node *getSyntaxNode(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001447 if (Printing)
1448 return this;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001449 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001450 return Ref->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001451 }
1452
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001453 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001454 if (Printing)
1455 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001456 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001457 Ref->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001458 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001459 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001460 if (Printing)
1461 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001462 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001463 Ref->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001464 }
1465};
1466
1467struct NameWithTemplateArgs : Node {
1468 // name<template_args>
1469 Node *Name;
1470 Node *TemplateArgs;
1471
1472 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1473 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1474
1475 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1476
1477 StringView getBaseName() const override { return Name->getBaseName(); }
1478
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001479 void printLeft(OutputBuffer &OB) const override {
1480 Name->print(OB);
1481 TemplateArgs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001482 }
1483};
1484
1485class GlobalQualifiedName final : public Node {
1486 Node *Child;
1487
1488public:
1489 GlobalQualifiedName(Node* Child_)
1490 : Node(KGlobalQualifiedName), Child(Child_) {}
1491
1492 template<typename Fn> void match(Fn F) const { F(Child); }
1493
1494 StringView getBaseName() const override { return Child->getBaseName(); }
1495
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001496 void printLeft(OutputBuffer &OB) const override {
1497 OB += "::";
1498 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001499 }
1500};
1501
Richard Smithc20d1442018-08-20 20:14:49 +00001502enum class SpecialSubKind {
1503 allocator,
1504 basic_string,
1505 string,
1506 istream,
1507 ostream,
1508 iostream,
1509};
1510
1511class ExpandedSpecialSubstitution final : public Node {
1512 SpecialSubKind SSK;
1513
1514public:
1515 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1516 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1517
1518 template<typename Fn> void match(Fn F) const { F(SSK); }
1519
1520 StringView getBaseName() const override {
1521 switch (SSK) {
1522 case SpecialSubKind::allocator:
1523 return StringView("allocator");
1524 case SpecialSubKind::basic_string:
1525 return StringView("basic_string");
1526 case SpecialSubKind::string:
1527 return StringView("basic_string");
1528 case SpecialSubKind::istream:
1529 return StringView("basic_istream");
1530 case SpecialSubKind::ostream:
1531 return StringView("basic_ostream");
1532 case SpecialSubKind::iostream:
1533 return StringView("basic_iostream");
1534 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001535 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001536 }
1537
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001538 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001539 switch (SSK) {
1540 case SpecialSubKind::allocator:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001541 OB += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001542 break;
1543 case SpecialSubKind::basic_string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001544 OB += "std::basic_string";
Richard Smithb485b352018-08-24 23:30:26 +00001545 break;
Richard Smithc20d1442018-08-20 20:14:49 +00001546 case SpecialSubKind::string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001547 OB += "std::basic_string<char, std::char_traits<char>, "
1548 "std::allocator<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001549 break;
1550 case SpecialSubKind::istream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001551 OB += "std::basic_istream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001552 break;
1553 case SpecialSubKind::ostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001554 OB += "std::basic_ostream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001555 break;
1556 case SpecialSubKind::iostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001557 OB += "std::basic_iostream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001558 break;
1559 }
1560 }
1561};
1562
1563class SpecialSubstitution final : public Node {
1564public:
1565 SpecialSubKind SSK;
1566
1567 SpecialSubstitution(SpecialSubKind SSK_)
1568 : Node(KSpecialSubstitution), SSK(SSK_) {}
1569
1570 template<typename Fn> void match(Fn F) const { F(SSK); }
1571
1572 StringView getBaseName() const override {
1573 switch (SSK) {
1574 case SpecialSubKind::allocator:
1575 return StringView("allocator");
1576 case SpecialSubKind::basic_string:
1577 return StringView("basic_string");
1578 case SpecialSubKind::string:
1579 return StringView("string");
1580 case SpecialSubKind::istream:
1581 return StringView("istream");
1582 case SpecialSubKind::ostream:
1583 return StringView("ostream");
1584 case SpecialSubKind::iostream:
1585 return StringView("iostream");
1586 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001587 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001588 }
1589
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001590 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001591 switch (SSK) {
1592 case SpecialSubKind::allocator:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001593 OB += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001594 break;
1595 case SpecialSubKind::basic_string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001596 OB += "std::basic_string";
Richard Smithc20d1442018-08-20 20:14:49 +00001597 break;
1598 case SpecialSubKind::string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001599 OB += "std::string";
Richard Smithc20d1442018-08-20 20:14:49 +00001600 break;
1601 case SpecialSubKind::istream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001602 OB += "std::istream";
Richard Smithc20d1442018-08-20 20:14:49 +00001603 break;
1604 case SpecialSubKind::ostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001605 OB += "std::ostream";
Richard Smithc20d1442018-08-20 20:14:49 +00001606 break;
1607 case SpecialSubKind::iostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001608 OB += "std::iostream";
Richard Smithc20d1442018-08-20 20:14:49 +00001609 break;
1610 }
1611 }
1612};
1613
1614class CtorDtorName final : public Node {
1615 const Node *Basename;
1616 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001617 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001618
1619public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001620 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1621 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1622 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001623
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001624 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001625
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001626 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001627 if (IsDtor)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001628 OB += "~";
1629 OB += Basename->getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001630 }
1631};
1632
1633class DtorName : public Node {
1634 const Node *Base;
1635
1636public:
1637 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1638
1639 template<typename Fn> void match(Fn F) const { F(Base); }
1640
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001641 void printLeft(OutputBuffer &OB) const override {
1642 OB += "~";
1643 Base->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001644 }
1645};
1646
1647class UnnamedTypeName : public Node {
1648 const StringView Count;
1649
1650public:
1651 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1652
1653 template<typename Fn> void match(Fn F) const { F(Count); }
1654
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001655 void printLeft(OutputBuffer &OB) const override {
1656 OB += "'unnamed";
1657 OB += Count;
1658 OB += "\'";
Richard Smithc20d1442018-08-20 20:14:49 +00001659 }
1660};
1661
1662class ClosureTypeName : public Node {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001663 NodeArray TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00001664 NodeArray Params;
1665 StringView Count;
1666
1667public:
Richard Smithdf1c14c2019-09-06 23:53:21 +00001668 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1669 StringView Count_)
1670 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1671 Params(Params_), Count(Count_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001672
Richard Smithdf1c14c2019-09-06 23:53:21 +00001673 template<typename Fn> void match(Fn F) const {
1674 F(TemplateParams, Params, Count);
1675 }
1676
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001677 void printDeclarator(OutputBuffer &OB) const {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001678 if (!TemplateParams.empty()) {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001679 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001680 OB += "<";
1681 TemplateParams.printWithComma(OB);
1682 OB += ">";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001683 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001684 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001685 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001686 OB.printClose();
Richard Smithdf1c14c2019-09-06 23:53:21 +00001687 }
Richard Smithc20d1442018-08-20 20:14:49 +00001688
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001689 void printLeft(OutputBuffer &OB) const override {
1690 OB += "\'lambda";
1691 OB += Count;
1692 OB += "\'";
1693 printDeclarator(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001694 }
1695};
1696
1697class StructuredBindingName : public Node {
1698 NodeArray Bindings;
1699public:
1700 StructuredBindingName(NodeArray Bindings_)
1701 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1702
1703 template<typename Fn> void match(Fn F) const { F(Bindings); }
1704
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001705 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001706 OB.printOpen('[');
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001707 Bindings.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001708 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001709 }
1710};
1711
1712// -- Expression Nodes --
1713
1714class BinaryExpr : public Node {
1715 const Node *LHS;
1716 const StringView InfixOperator;
1717 const Node *RHS;
1718
1719public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001720 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
1721 Prec Prec_)
1722 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
1723 RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001724
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001725 template <typename Fn> void match(Fn F) const {
1726 F(LHS, InfixOperator, RHS, getPrecedence());
1727 }
Richard Smithc20d1442018-08-20 20:14:49 +00001728
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001729 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell18505102022-03-25 04:34:19 -07001730 bool ParenAll = OB.isGtInsideTemplateArgs() &&
1731 (InfixOperator == ">" || InfixOperator == ">>");
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001732 if (ParenAll)
1733 OB.printOpen();
1734 // Assignment is right associative, with special LHS precedence.
1735 bool IsAssign = getPrecedence() == Prec::Assign;
1736 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1737 // No space before comma operator
1738 if (!(InfixOperator == ","))
1739 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001740 OB += InfixOperator;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001741 OB += " ";
1742 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1743 if (ParenAll)
1744 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001745 }
1746};
1747
1748class ArraySubscriptExpr : public Node {
1749 const Node *Op1;
1750 const Node *Op2;
1751
1752public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001753 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1754 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001755
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001756 template <typename Fn> void match(Fn F) const {
1757 F(Op1, Op2, getPrecedence());
1758 }
Richard Smithc20d1442018-08-20 20:14:49 +00001759
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001760 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001761 Op1->printAsOperand(OB, getPrecedence());
1762 OB.printOpen('[');
1763 Op2->printAsOperand(OB);
1764 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001765 }
1766};
1767
1768class PostfixExpr : public Node {
1769 const Node *Child;
1770 const StringView Operator;
1771
1772public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001773 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
1774 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001775
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001776 template <typename Fn> void match(Fn F) const {
1777 F(Child, Operator, getPrecedence());
1778 }
Richard Smithc20d1442018-08-20 20:14:49 +00001779
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001780 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001781 Child->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001782 OB += Operator;
Richard Smithc20d1442018-08-20 20:14:49 +00001783 }
1784};
1785
1786class ConditionalExpr : public Node {
1787 const Node *Cond;
1788 const Node *Then;
1789 const Node *Else;
1790
1791public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001792 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1793 Prec Prec_)
1794 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001795
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001796 template <typename Fn> void match(Fn F) const {
1797 F(Cond, Then, Else, getPrecedence());
1798 }
Richard Smithc20d1442018-08-20 20:14:49 +00001799
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001800 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001801 Cond->printAsOperand(OB, getPrecedence());
1802 OB += " ? ";
1803 Then->printAsOperand(OB);
1804 OB += " : ";
1805 Else->printAsOperand(OB, Prec::Assign, true);
Richard Smithc20d1442018-08-20 20:14:49 +00001806 }
1807};
1808
1809class MemberExpr : public Node {
1810 const Node *LHS;
1811 const StringView Kind;
1812 const Node *RHS;
1813
1814public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001815 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
1816 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001817
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001818 template <typename Fn> void match(Fn F) const {
1819 F(LHS, Kind, RHS, getPrecedence());
1820 }
Richard Smithc20d1442018-08-20 20:14:49 +00001821
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001822 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001823 LHS->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001824 OB += Kind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001825 RHS->printAsOperand(OB, getPrecedence(), false);
Richard Smithc20d1442018-08-20 20:14:49 +00001826 }
1827};
1828
Richard Smith1865d2f2020-10-22 19:29:36 -07001829class SubobjectExpr : public Node {
1830 const Node *Type;
1831 const Node *SubExpr;
1832 StringView Offset;
1833 NodeArray UnionSelectors;
1834 bool OnePastTheEnd;
1835
1836public:
1837 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1838 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1839 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1840 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1841
1842 template<typename Fn> void match(Fn F) const {
1843 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1844 }
1845
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001846 void printLeft(OutputBuffer &OB) const override {
1847 SubExpr->print(OB);
1848 OB += ".<";
1849 Type->print(OB);
1850 OB += " at offset ";
Richard Smith1865d2f2020-10-22 19:29:36 -07001851 if (Offset.empty()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001852 OB += "0";
Richard Smith1865d2f2020-10-22 19:29:36 -07001853 } else if (Offset[0] == 'n') {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001854 OB += "-";
1855 OB += Offset.dropFront();
Richard Smith1865d2f2020-10-22 19:29:36 -07001856 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001857 OB += Offset;
Richard Smith1865d2f2020-10-22 19:29:36 -07001858 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001859 OB += ">";
Richard Smith1865d2f2020-10-22 19:29:36 -07001860 }
1861};
1862
Richard Smithc20d1442018-08-20 20:14:49 +00001863class EnclosingExpr : public Node {
1864 const StringView Prefix;
1865 const Node *Infix;
1866 const StringView Postfix;
1867
1868public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001869 EnclosingExpr(StringView Prefix_, const Node *Infix_,
1870 Prec Prec_ = Prec::Primary)
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001871 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001872
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001873 template <typename Fn> void match(Fn F) const {
1874 F(Prefix, Infix, getPrecedence());
1875 }
Richard Smithc20d1442018-08-20 20:14:49 +00001876
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001877 void printLeft(OutputBuffer &OB) const override {
1878 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001879 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001880 Infix->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001881 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001882 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +00001883 }
1884};
1885
1886class CastExpr : public Node {
1887 // cast_kind<to>(from)
1888 const StringView CastKind;
1889 const Node *To;
1890 const Node *From;
1891
1892public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001893 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
1894 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001895
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001896 template <typename Fn> void match(Fn F) const {
1897 F(CastKind, To, From, getPrecedence());
1898 }
Richard Smithc20d1442018-08-20 20:14:49 +00001899
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001900 void printLeft(OutputBuffer &OB) const override {
1901 OB += CastKind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001902 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001903 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001904 OB += "<";
1905 To->printLeft(OB);
1906 if (OB.back() == '>')
1907 OB += " ";
1908 OB += ">";
1909 }
1910 OB.printOpen();
1911 From->printAsOperand(OB);
1912 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001913 }
1914};
1915
1916class SizeofParamPackExpr : public Node {
1917 const Node *Pack;
1918
1919public:
1920 SizeofParamPackExpr(const Node *Pack_)
1921 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1922
1923 template<typename Fn> void match(Fn F) const { F(Pack); }
1924
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001925 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001926 OB += "sizeof...";
1927 OB.printOpen();
Richard Smithc20d1442018-08-20 20:14:49 +00001928 ParameterPackExpansion PPE(Pack);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001929 PPE.printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001930 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001931 }
1932};
1933
1934class CallExpr : public Node {
1935 const Node *Callee;
1936 NodeArray Args;
1937
1938public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001939 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
1940 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001941
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001942 template <typename Fn> void match(Fn F) const {
1943 F(Callee, Args, getPrecedence());
1944 }
Richard Smithc20d1442018-08-20 20:14:49 +00001945
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001946 void printLeft(OutputBuffer &OB) const override {
1947 Callee->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001948 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001949 Args.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001950 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001951 }
1952};
1953
1954class NewExpr : public Node {
1955 // new (expr_list) type(init_list)
1956 NodeArray ExprList;
1957 Node *Type;
1958 NodeArray InitList;
1959 bool IsGlobal; // ::operator new ?
1960 bool IsArray; // new[] ?
1961public:
1962 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001963 bool IsArray_, Prec Prec_)
1964 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
1965 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001966
1967 template<typename Fn> void match(Fn F) const {
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001968 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00001969 }
1970
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001971 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001972 if (IsGlobal)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001973 OB += "::";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001974 OB += "new";
Richard Smithc20d1442018-08-20 20:14:49 +00001975 if (IsArray)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001976 OB += "[]";
Richard Smithc20d1442018-08-20 20:14:49 +00001977 if (!ExprList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001978 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001979 ExprList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001980 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001981 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001982 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001983 Type->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001984 if (!InitList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001985 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001986 InitList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001987 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001988 }
Richard Smithc20d1442018-08-20 20:14:49 +00001989 }
1990};
1991
1992class DeleteExpr : public Node {
1993 Node *Op;
1994 bool IsGlobal;
1995 bool IsArray;
1996
1997public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001998 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
1999 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
2000 IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002001
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002002 template <typename Fn> void match(Fn F) const {
2003 F(Op, IsGlobal, IsArray, getPrecedence());
2004 }
Richard Smithc20d1442018-08-20 20:14:49 +00002005
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002006 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002007 if (IsGlobal)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002008 OB += "::";
2009 OB += "delete";
Richard Smithc20d1442018-08-20 20:14:49 +00002010 if (IsArray)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08002011 OB += "[]";
2012 OB += ' ';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002013 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002014 }
2015};
2016
2017class PrefixExpr : public Node {
2018 StringView Prefix;
2019 Node *Child;
2020
2021public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002022 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
2023 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
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(Prefix, Child, 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 {
2030 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002031 Child->printAsOperand(OB, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00002032 }
2033};
2034
2035class FunctionParam : public Node {
2036 StringView Number;
2037
2038public:
2039 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
2040
2041 template<typename Fn> void match(Fn F) const { F(Number); }
2042
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002043 void printLeft(OutputBuffer &OB) const override {
2044 OB += "fp";
2045 OB += Number;
Richard Smithc20d1442018-08-20 20:14:49 +00002046 }
2047};
2048
2049class ConversionExpr : public Node {
2050 const Node *Type;
2051 NodeArray Expressions;
2052
2053public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002054 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2055 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002056
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002057 template <typename Fn> void match(Fn F) const {
2058 F(Type, Expressions, getPrecedence());
2059 }
Richard Smithc20d1442018-08-20 20:14:49 +00002060
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002061 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002062 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002063 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002064 OB.printClose();
2065 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002066 Expressions.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002067 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002068 }
2069};
2070
Richard Smith1865d2f2020-10-22 19:29:36 -07002071class PointerToMemberConversionExpr : public Node {
2072 const Node *Type;
2073 const Node *SubExpr;
2074 StringView Offset;
2075
2076public:
2077 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002078 StringView Offset_, Prec Prec_)
2079 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2080 SubExpr(SubExpr_), Offset(Offset_) {}
Richard Smith1865d2f2020-10-22 19:29:36 -07002081
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002082 template <typename Fn> void match(Fn F) const {
2083 F(Type, SubExpr, Offset, getPrecedence());
2084 }
Richard Smith1865d2f2020-10-22 19:29:36 -07002085
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002086 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002087 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002088 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002089 OB.printClose();
2090 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002091 SubExpr->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002092 OB.printClose();
Richard Smith1865d2f2020-10-22 19:29:36 -07002093 }
2094};
2095
Richard Smithc20d1442018-08-20 20:14:49 +00002096class InitListExpr : public Node {
2097 const Node *Ty;
2098 NodeArray Inits;
2099public:
2100 InitListExpr(const Node *Ty_, NodeArray Inits_)
2101 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2102
2103 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2104
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002105 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002106 if (Ty)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002107 Ty->print(OB);
2108 OB += '{';
2109 Inits.printWithComma(OB);
2110 OB += '}';
Richard Smithc20d1442018-08-20 20:14:49 +00002111 }
2112};
2113
2114class BracedExpr : public Node {
2115 const Node *Elem;
2116 const Node *Init;
2117 bool IsArray;
2118public:
2119 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2120 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2121
2122 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
2123
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002124 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002125 if (IsArray) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002126 OB += '[';
2127 Elem->print(OB);
2128 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002129 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002130 OB += '.';
2131 Elem->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002132 }
2133 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002134 OB += " = ";
2135 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002136 }
2137};
2138
2139class BracedRangeExpr : public Node {
2140 const Node *First;
2141 const Node *Last;
2142 const Node *Init;
2143public:
2144 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2145 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2146
2147 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2148
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002149 void printLeft(OutputBuffer &OB) const override {
2150 OB += '[';
2151 First->print(OB);
2152 OB += " ... ";
2153 Last->print(OB);
2154 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002155 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002156 OB += " = ";
2157 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002158 }
2159};
2160
2161class FoldExpr : public Node {
2162 const Node *Pack, *Init;
2163 StringView OperatorName;
2164 bool IsLeftFold;
2165
2166public:
2167 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
2168 const Node *Init_)
2169 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2170 IsLeftFold(IsLeftFold_) {}
2171
2172 template<typename Fn> void match(Fn F) const {
2173 F(IsLeftFold, OperatorName, Pack, Init);
2174 }
2175
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002176 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002177 auto PrintPack = [&] {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002178 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002179 ParameterPackExpansion(Pack).print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002180 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002181 };
2182
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002183 OB.printOpen();
2184 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2185 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2186 // Fold expr operands are cast-expressions
2187 if (!IsLeftFold || Init != nullptr) {
2188 // '(init|pack) op '
2189 if (IsLeftFold)
2190 Init->printAsOperand(OB, Prec::Cast, true);
2191 else
2192 PrintPack();
2193 OB << " " << OperatorName << " ";
Richard Smithc20d1442018-08-20 20:14:49 +00002194 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002195 OB << "...";
2196 if (IsLeftFold || Init != nullptr) {
2197 // ' op (init|pack)'
2198 OB << " " << OperatorName << " ";
2199 if (IsLeftFold)
2200 PrintPack();
2201 else
2202 Init->printAsOperand(OB, Prec::Cast, true);
2203 }
2204 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002205 }
2206};
2207
2208class ThrowExpr : public Node {
2209 const Node *Op;
2210
2211public:
2212 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2213
2214 template<typename Fn> void match(Fn F) const { F(Op); }
2215
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002216 void printLeft(OutputBuffer &OB) const override {
2217 OB += "throw ";
2218 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002219 }
2220};
2221
2222class BoolExpr : public Node {
2223 bool Value;
2224
2225public:
2226 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2227
2228 template<typename Fn> void match(Fn F) const { F(Value); }
2229
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002230 void printLeft(OutputBuffer &OB) const override {
2231 OB += Value ? StringView("true") : StringView("false");
Richard Smithc20d1442018-08-20 20:14:49 +00002232 }
2233};
2234
Richard Smithdf1c14c2019-09-06 23:53:21 +00002235class StringLiteral : public Node {
2236 const Node *Type;
2237
2238public:
2239 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2240
2241 template<typename Fn> void match(Fn F) const { F(Type); }
2242
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002243 void printLeft(OutputBuffer &OB) const override {
2244 OB += "\"<";
2245 Type->print(OB);
2246 OB += ">\"";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002247 }
2248};
2249
2250class LambdaExpr : public Node {
2251 const Node *Type;
2252
Richard Smithdf1c14c2019-09-06 23:53:21 +00002253public:
2254 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2255
2256 template<typename Fn> void match(Fn F) const { F(Type); }
2257
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002258 void printLeft(OutputBuffer &OB) const override {
2259 OB += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002260 if (Type->getKind() == KClosureTypeName)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002261 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2262 OB += "{...}";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002263 }
2264};
2265
Erik Pilkington0a170f12020-05-13 14:13:37 -04002266class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002267 // ty(integer)
2268 const Node *Ty;
2269 StringView Integer;
2270
2271public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002272 EnumLiteral(const Node *Ty_, StringView Integer_)
2273 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002274
2275 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2276
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002277 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002278 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002279 Ty->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002280 OB.printClose();
Erik Pilkington0a170f12020-05-13 14:13:37 -04002281
2282 if (Integer[0] == 'n')
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002283 OB << "-" << Integer.dropFront(1);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002284 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002285 OB << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002286 }
2287};
2288
2289class IntegerLiteral : public Node {
2290 StringView Type;
2291 StringView Value;
2292
2293public:
2294 IntegerLiteral(StringView Type_, StringView Value_)
2295 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2296
2297 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2298
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002299 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002300 if (Type.size() > 3) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002301 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002302 OB += Type;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002303 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002304 }
2305
2306 if (Value[0] == 'n') {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002307 OB += '-';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002308 OB += Value.dropFront(1);
Richard Smithc20d1442018-08-20 20:14:49 +00002309 } else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002310 OB += Value;
Richard Smithc20d1442018-08-20 20:14:49 +00002311
2312 if (Type.size() <= 3)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002313 OB += Type;
Richard Smithc20d1442018-08-20 20:14:49 +00002314 }
2315};
2316
2317template <class Float> struct FloatData;
2318
2319namespace float_literal_impl {
2320constexpr Node::Kind getFloatLiteralKind(float *) {
2321 return Node::KFloatLiteral;
2322}
2323constexpr Node::Kind getFloatLiteralKind(double *) {
2324 return Node::KDoubleLiteral;
2325}
2326constexpr Node::Kind getFloatLiteralKind(long double *) {
2327 return Node::KLongDoubleLiteral;
2328}
2329}
2330
2331template <class Float> class FloatLiteralImpl : public Node {
2332 const StringView Contents;
2333
2334 static constexpr Kind KindForClass =
2335 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2336
2337public:
2338 FloatLiteralImpl(StringView Contents_)
2339 : Node(KindForClass), Contents(Contents_) {}
2340
2341 template<typename Fn> void match(Fn F) const { F(Contents); }
2342
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002343 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002344 const char *first = Contents.begin();
2345 const char *last = Contents.end() + 1;
2346
2347 const size_t N = FloatData<Float>::mangled_size;
2348 if (static_cast<std::size_t>(last - first) > N) {
2349 last = first + N;
2350 union {
2351 Float value;
2352 char buf[sizeof(Float)];
2353 };
2354 const char *t = first;
2355 char *e = buf;
2356 for (; t != last; ++t, ++e) {
2357 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2358 : static_cast<unsigned>(*t - 'a' + 10);
2359 ++t;
2360 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2361 : static_cast<unsigned>(*t - 'a' + 10);
2362 *e = static_cast<char>((d1 << 4) + d0);
2363 }
2364#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2365 std::reverse(buf, e);
2366#endif
2367 char num[FloatData<Float>::max_demangled_size] = {0};
2368 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002369 OB += StringView(num, num + n);
Richard Smithc20d1442018-08-20 20:14:49 +00002370 }
2371 }
2372};
2373
2374using FloatLiteral = FloatLiteralImpl<float>;
2375using DoubleLiteral = FloatLiteralImpl<double>;
2376using LongDoubleLiteral = FloatLiteralImpl<long double>;
2377
2378/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2379/// appropriate derived class.
2380template<typename Fn>
2381void Node::visit(Fn F) const {
2382 switch (K) {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002383#define NODE(X) \
2384 case K##X: \
2385 return F(static_cast<const X *>(this));
2386#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002387 }
2388 assert(0 && "unknown mangling node kind");
2389}
2390
2391/// Determine the kind of a node from its type.
2392template<typename NodeT> struct NodeKind;
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002393#define NODE(X) \
2394 template <> struct NodeKind<X> { \
2395 static constexpr Node::Kind Kind = Node::K##X; \
2396 static constexpr const char *name() { return #X; } \
Richard Smithc20d1442018-08-20 20:14:49 +00002397 };
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002398#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002399
Pavel Labathba825192018-10-16 14:29:14 +00002400template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002401 const char *First;
2402 const char *Last;
2403
2404 // Name stack, this is used by the parser to hold temporary names that were
2405 // parsed. The parser collapses multiple names into new nodes to construct
2406 // the AST. Once the parser is finished, names.size() == 1.
2407 PODSmallVector<Node *, 32> Names;
2408
2409 // Substitution table. Itanium supports name substitutions as a means of
2410 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2411 // table.
2412 PODSmallVector<Node *, 32> Subs;
2413
Richard Smithdf1c14c2019-09-06 23:53:21 +00002414 using TemplateParamList = PODSmallVector<Node *, 8>;
2415
2416 class ScopedTemplateParamList {
2417 AbstractManglingParser *Parser;
2418 size_t OldNumTemplateParamLists;
2419 TemplateParamList Params;
2420
2421 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002422 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2423 : Parser(TheParser),
2424 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002425 Parser->TemplateParams.push_back(&Params);
2426 }
2427 ~ScopedTemplateParamList() {
2428 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2429 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2430 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002431 };
2432
Richard Smithc20d1442018-08-20 20:14:49 +00002433 // Template parameter table. Like the above, but referenced like "T42_".
2434 // This has a smaller size compared to Subs and Names because it can be
2435 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002436 TemplateParamList OuterTemplateParams;
2437
2438 // Lists of template parameters indexed by template parameter depth,
2439 // referenced like "TL2_4_". If nonempty, element 0 is always
2440 // OuterTemplateParams; inner elements are always template parameter lists of
2441 // lambda expressions. For a generic lambda with no explicit template
2442 // parameter list, the corresponding parameter list pointer will be null.
2443 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002444
2445 // Set of unresolved forward <template-param> references. These can occur in a
2446 // conversion operator's type, and are resolved in the enclosing <encoding>.
2447 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2448
Richard Smithc20d1442018-08-20 20:14:49 +00002449 bool TryToParseTemplateArgs = true;
2450 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002451 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2452
2453 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002454
2455 Alloc ASTAllocator;
2456
Pavel Labathba825192018-10-16 14:29:14 +00002457 AbstractManglingParser(const char *First_, const char *Last_)
2458 : First(First_), Last(Last_) {}
2459
2460 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002461
2462 void reset(const char *First_, const char *Last_) {
2463 First = First_;
2464 Last = Last_;
2465 Names.clear();
2466 Subs.clear();
2467 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002468 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002469 TryToParseTemplateArgs = true;
2470 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002471 for (int I = 0; I != 3; ++I)
2472 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002473 ASTAllocator.reset();
2474 }
2475
Richard Smithb485b352018-08-24 23:30:26 +00002476 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002477 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2478 }
2479
2480 template <class It> NodeArray makeNodeArray(It begin, It end) {
2481 size_t sz = static_cast<size_t>(end - begin);
2482 void *mem = ASTAllocator.allocateNodeArray(sz);
2483 Node **data = new (mem) Node *[sz];
2484 std::copy(begin, end, data);
2485 return NodeArray(data, sz);
2486 }
2487
2488 NodeArray popTrailingNodeArray(size_t FromPosition) {
2489 assert(FromPosition <= Names.size());
2490 NodeArray res =
2491 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2492 Names.dropBack(FromPosition);
2493 return res;
2494 }
2495
2496 bool consumeIf(StringView S) {
2497 if (StringView(First, Last).startsWith(S)) {
2498 First += S.size();
2499 return true;
2500 }
2501 return false;
2502 }
2503
2504 bool consumeIf(char C) {
2505 if (First != Last && *First == C) {
2506 ++First;
2507 return true;
2508 }
2509 return false;
2510 }
2511
2512 char consume() { return First != Last ? *First++ : '\0'; }
2513
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08002514 char look(unsigned Lookahead = 0) const {
Richard Smithc20d1442018-08-20 20:14:49 +00002515 if (static_cast<size_t>(Last - First) <= Lookahead)
2516 return '\0';
2517 return First[Lookahead];
2518 }
2519
2520 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2521
2522 StringView parseNumber(bool AllowNegative = false);
2523 Qualifiers parseCVQualifiers();
2524 bool parsePositiveInteger(size_t *Out);
2525 StringView parseBareSourceName();
2526
2527 bool parseSeqId(size_t *Out);
2528 Node *parseSubstitution();
2529 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002530 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002531 Node *parseTemplateArgs(bool TagTemplates = false);
2532 Node *parseTemplateArg();
2533
2534 /// Parse the <expr> production.
2535 Node *parseExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002536 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2537 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00002538 Node *parseIntegerLiteral(StringView Lit);
2539 Node *parseExprPrimary();
2540 template <class Float> Node *parseFloatingLiteral();
2541 Node *parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00002542 Node *parseConversionExpr();
2543 Node *parseBracedExpr();
2544 Node *parseFoldExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002545 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07002546 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002547
2548 /// Parse the <type> production.
2549 Node *parseType();
2550 Node *parseFunctionType();
2551 Node *parseVectorType();
2552 Node *parseDecltype();
2553 Node *parseArrayType();
2554 Node *parsePointerToMemberType();
2555 Node *parseClassEnumType();
2556 Node *parseQualifiedType();
2557
2558 Node *parseEncoding();
2559 bool parseCallOffset();
2560 Node *parseSpecialName();
2561
2562 /// Holds some extra information about a <name> that is being parsed. This
2563 /// information is only pertinent if the <name> refers to an <encoding>.
2564 struct NameState {
2565 bool CtorDtorConversion = false;
2566 bool EndsWithTemplateArgs = false;
2567 Qualifiers CVQualifiers = QualNone;
2568 FunctionRefQual ReferenceQualifier = FrefQualNone;
2569 size_t ForwardTemplateRefsBegin;
2570
Pavel Labathba825192018-10-16 14:29:14 +00002571 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002572 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2573 };
2574
2575 bool resolveForwardTemplateRefs(NameState &State) {
2576 size_t I = State.ForwardTemplateRefsBegin;
2577 size_t E = ForwardTemplateRefs.size();
2578 for (; I < E; ++I) {
2579 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002580 if (TemplateParams.empty() || !TemplateParams[0] ||
2581 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002582 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002583 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002584 }
2585 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2586 return false;
2587 }
2588
2589 /// Parse the <name> production>
2590 Node *parseName(NameState *State = nullptr);
2591 Node *parseLocalName(NameState *State);
2592 Node *parseOperatorName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002593 bool parseModuleNameOpt(ModuleName *&Module);
2594 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
Richard Smithc20d1442018-08-20 20:14:49 +00002595 Node *parseUnnamedTypeName(NameState *State);
2596 Node *parseSourceName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002597 Node *parseUnscopedName(NameState *State, bool *isSubstName);
Richard Smithc20d1442018-08-20 20:14:49 +00002598 Node *parseNestedName(NameState *State);
2599 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2600
2601 Node *parseAbiTags(Node *N);
2602
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002603 struct OperatorInfo {
2604 enum OIKind : unsigned char {
2605 Prefix, // Prefix unary: @ expr
2606 Postfix, // Postfix unary: expr @
2607 Binary, // Binary: lhs @ rhs
2608 Array, // Array index: lhs [ rhs ]
2609 Member, // Member access: lhs @ rhs
2610 New, // New
2611 Del, // Delete
2612 Call, // Function call: expr (expr*)
2613 CCast, // C cast: (type)expr
2614 Conditional, // Conditional: expr ? expr : expr
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08002615 NameOnly, // Overload only, not allowed in expression.
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002616 // Below do not have operator names
2617 NamedCast, // Named cast, @<type>(expr)
2618 OfIdOp, // alignof, sizeof, typeid
2619
2620 Unnameable = NamedCast,
2621 };
2622 char Enc[2]; // Encoding
2623 OIKind Kind; // Kind of operator
2624 bool Flag : 1; // Entry-specific flag
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002625 Node::Prec Prec : 7; // Precedence
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002626 const char *Name; // Spelling
2627
2628 public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002629 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2630 const char *N)
2631 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002632
2633 public:
2634 bool operator<(const OperatorInfo &Other) const {
2635 return *this < Other.Enc;
2636 }
2637 bool operator<(const char *Peek) const {
2638 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2639 }
2640 bool operator==(const char *Peek) const {
2641 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2642 }
2643 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2644
2645 public:
2646 StringView getSymbol() const {
2647 StringView Res = Name;
2648 if (Kind < Unnameable) {
2649 assert(Res.startsWith("operator") &&
2650 "operator name does not start with 'operator'");
2651 Res = Res.dropFront(sizeof("operator") - 1);
2652 Res.consumeFront(' ');
2653 }
2654 return Res;
2655 }
2656 StringView getName() const { return Name; }
2657 OIKind getKind() const { return Kind; }
2658 bool getFlag() const { return Flag; }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002659 Node::Prec getPrecedence() const { return Prec; }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002660 };
2661 const OperatorInfo *parseOperatorEncoding();
2662
Richard Smithc20d1442018-08-20 20:14:49 +00002663 /// Parse the <unresolved-name> production.
Nathan Sidwell77c52e22022-01-28 11:59:03 -08002664 Node *parseUnresolvedName(bool Global);
Richard Smithc20d1442018-08-20 20:14:49 +00002665 Node *parseSimpleId();
2666 Node *parseBaseUnresolvedName();
2667 Node *parseUnresolvedType();
2668 Node *parseDestructorName();
2669
2670 /// Top-level entry point into the parser.
2671 Node *parse();
2672};
2673
2674const char* parse_discriminator(const char* first, const char* last);
2675
2676// <name> ::= <nested-name> // N
2677// ::= <local-name> # See Scope Encoding below // Z
2678// ::= <unscoped-template-name> <template-args>
2679// ::= <unscoped-name>
2680//
2681// <unscoped-template-name> ::= <unscoped-name>
2682// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002683template <typename Derived, typename Alloc>
2684Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002685 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002686 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002687 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002688 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002689
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002690 Node *Result = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002691 bool IsSubst = false;
2692
2693 Result = getDerived().parseUnscopedName(State, &IsSubst);
2694 if (!Result)
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002695 return nullptr;
2696
2697 if (look() == 'I') {
2698 // ::= <unscoped-template-name> <template-args>
2699 if (!IsSubst)
2700 // An unscoped-template-name is substitutable.
2701 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00002702 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002703 if (TA == nullptr)
2704 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002705 if (State)
2706 State->EndsWithTemplateArgs = true;
2707 Result = make<NameWithTemplateArgs>(Result, TA);
2708 } else if (IsSubst) {
2709 // The substitution case must be followed by <template-args>.
2710 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002711 }
2712
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002713 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00002714}
2715
2716// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2717// := Z <function encoding> E s [<discriminator>]
2718// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002719template <typename Derived, typename Alloc>
2720Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002721 if (!consumeIf('Z'))
2722 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002723 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002724 if (Encoding == nullptr || !consumeIf('E'))
2725 return nullptr;
2726
2727 if (consumeIf('s')) {
2728 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002729 auto *StringLitName = make<NameType>("string literal");
2730 if (!StringLitName)
2731 return nullptr;
2732 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002733 }
2734
2735 if (consumeIf('d')) {
2736 parseNumber(true);
2737 if (!consumeIf('_'))
2738 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002739 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002740 if (N == nullptr)
2741 return nullptr;
2742 return make<LocalName>(Encoding, N);
2743 }
2744
Pavel Labathba825192018-10-16 14:29:14 +00002745 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002746 if (Entity == nullptr)
2747 return nullptr;
2748 First = parse_discriminator(First, Last);
2749 return make<LocalName>(Encoding, Entity);
2750}
2751
Nathan Sidwellac492da2022-04-05 09:25:47 -07002752// <unscoped-name> ::= <unqualified-name>
2753// ::= St <unqualified-name> # ::std::
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08002754// [*] extension
Pavel Labathba825192018-10-16 14:29:14 +00002755template <typename Derived, typename Alloc>
2756Node *
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002757AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2758 bool *IsSubst) {
2759
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002760 Node *Std = nullptr;
2761 if (consumeIf("St")) {
2762 Std = make<NameType>("std");
2763 if (Std == nullptr)
Nathan Sidwell200e97c2022-01-21 11:37:01 -08002764 return nullptr;
2765 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002766
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002767 Node *Res = nullptr;
2768 ModuleName *Module = nullptr;
2769 if (look() == 'S') {
2770 Node *S = getDerived().parseSubstitution();
2771 if (!S)
2772 return nullptr;
2773 if (S->getKind() == Node::KModuleName)
2774 Module = static_cast<ModuleName *>(S);
2775 else if (IsSubst && Std == nullptr) {
2776 Res = S;
2777 *IsSubst = true;
2778 } else {
2779 return nullptr;
2780 }
2781 }
2782
Nathan Sidwellac492da2022-04-05 09:25:47 -07002783 if (Res == nullptr || Std != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002784 Res = getDerived().parseUnqualifiedName(State, Std, Module);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002785 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002786
2787 return Res;
Richard Smithc20d1442018-08-20 20:14:49 +00002788}
2789
Nathan Sidwellac492da2022-04-05 09:25:47 -07002790// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002791// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
Nathan Sidwellac492da2022-04-05 09:25:47 -07002792// ::= [<module-name>] L? <source-name> [<abi-tags>]
2793// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002794// # structured binding declaration
Nathan Sidwellac492da2022-04-05 09:25:47 -07002795// ::= [<module-name>] L? DC <source-name>+ E
Pavel Labathba825192018-10-16 14:29:14 +00002796template <typename Derived, typename Alloc>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002797Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2798 NameState *State, Node *Scope, ModuleName *Module) {
2799 if (getDerived().parseModuleNameOpt(Module))
2800 return nullptr;
2801
Nathan Sidwellac492da2022-04-05 09:25:47 -07002802 consumeIf('L');
2803
Richard Smithc20d1442018-08-20 20:14:49 +00002804 Node *Result;
Nathan Sidwellac492da2022-04-05 09:25:47 -07002805 if (look() >= '1' && look() <= '9') {
Pavel Labathba825192018-10-16 14:29:14 +00002806 Result = getDerived().parseSourceName(State);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002807 } else if (look() == 'U') {
2808 Result = getDerived().parseUnnamedTypeName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002809 } else if (consumeIf("DC")) {
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002810 // Structured binding
Richard Smithc20d1442018-08-20 20:14:49 +00002811 size_t BindingsBegin = Names.size();
2812 do {
Pavel Labathba825192018-10-16 14:29:14 +00002813 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002814 if (Binding == nullptr)
2815 return nullptr;
2816 Names.push_back(Binding);
2817 } while (!consumeIf('E'));
2818 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002819 } else if (look() == 'C' || look() == 'D') {
2820 // A <ctor-dtor-name>.
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002821 if (Scope == nullptr || Module != nullptr)
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002822 return nullptr;
2823 Result = getDerived().parseCtorDtorName(Scope, State);
2824 } else {
Pavel Labathba825192018-10-16 14:29:14 +00002825 Result = getDerived().parseOperatorName(State);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002826 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002827
David Blaikie019fb1b2022-03-30 20:18:40 +00002828 if (Result != nullptr && Module != nullptr)
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002829 Result = make<ModuleEntity>(Module, Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002830 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002831 Result = getDerived().parseAbiTags(Result);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002832 if (Result != nullptr && Scope != nullptr)
2833 Result = make<NestedName>(Scope, Result);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002834
Richard Smithc20d1442018-08-20 20:14:49 +00002835 return Result;
2836}
2837
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002838// <module-name> ::= <module-subname>
2839// ::= <module-name> <module-subname>
2840// ::= <substitution> # passed in by caller
2841// <module-subname> ::= W <source-name>
2842// ::= W P <source-name>
2843template <typename Derived, typename Alloc>
2844bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2845 ModuleName *&Module) {
2846 while (consumeIf('W')) {
2847 bool IsPartition = consumeIf('P');
2848 Node *Sub = getDerived().parseSourceName(nullptr);
2849 if (!Sub)
2850 return true;
2851 Module =
2852 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2853 Subs.push_back(Module);
2854 }
2855
2856 return false;
2857}
2858
Richard Smithc20d1442018-08-20 20:14:49 +00002859// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2860// ::= <closure-type-name>
2861//
2862// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2863//
2864// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002865template <typename Derived, typename Alloc>
2866Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002867AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2868 // <template-params> refer to the innermost <template-args>. Clear out any
2869 // outer args that we may have inserted into TemplateParams.
2870 if (State != nullptr)
2871 TemplateParams.clear();
2872
Richard Smithc20d1442018-08-20 20:14:49 +00002873 if (consumeIf("Ut")) {
2874 StringView Count = parseNumber();
2875 if (!consumeIf('_'))
2876 return nullptr;
2877 return make<UnnamedTypeName>(Count);
2878 }
2879 if (consumeIf("Ul")) {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08002880 ScopedOverride<size_t> SwapParams(ParsingLambdaParamsAtLevel,
Richard Smithdf1c14c2019-09-06 23:53:21 +00002881 TemplateParams.size());
2882 ScopedTemplateParamList LambdaTemplateParams(this);
2883
2884 size_t ParamsBegin = Names.size();
2885 while (look() == 'T' &&
2886 StringView("yptn").find(look(1)) != StringView::npos) {
2887 Node *T = parseTemplateParamDecl();
2888 if (!T)
2889 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002890 Names.push_back(T);
2891 }
2892 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2893
2894 // FIXME: If TempParams is empty and none of the function parameters
2895 // includes 'auto', we should remove LambdaTemplateParams from the
2896 // TemplateParams list. Unfortunately, we don't find out whether there are
2897 // any 'auto' parameters until too late in an example such as:
2898 //
2899 // template<typename T> void f(
2900 // decltype([](decltype([]<typename T>(T v) {}),
2901 // auto) {})) {}
2902 // template<typename T> void f(
2903 // decltype([](decltype([]<typename T>(T w) {}),
2904 // int) {})) {}
2905 //
2906 // Here, the type of v is at level 2 but the type of w is at level 1. We
2907 // don't find this out until we encounter the type of the next parameter.
2908 //
2909 // However, compilers can't actually cope with the former example in
2910 // practice, and it's likely to be made ill-formed in future, so we don't
2911 // need to support it here.
2912 //
2913 // If we encounter an 'auto' in the function parameter types, we will
2914 // recreate a template parameter scope for it, but any intervening lambdas
2915 // will be parsed in the 'wrong' template parameter depth.
2916 if (TempParams.empty())
2917 TemplateParams.pop_back();
2918
Richard Smithc20d1442018-08-20 20:14:49 +00002919 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002920 do {
Pavel Labathba825192018-10-16 14:29:14 +00002921 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002922 if (P == nullptr)
2923 return nullptr;
2924 Names.push_back(P);
2925 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002926 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002927 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2928
Richard Smithc20d1442018-08-20 20:14:49 +00002929 StringView Count = parseNumber();
2930 if (!consumeIf('_'))
2931 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002932 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002933 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002934 if (consumeIf("Ub")) {
2935 (void)parseNumber();
2936 if (!consumeIf('_'))
2937 return nullptr;
2938 return make<NameType>("'block-literal'");
2939 }
Richard Smithc20d1442018-08-20 20:14:49 +00002940 return nullptr;
2941}
2942
2943// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002944template <typename Derived, typename Alloc>
2945Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002946 size_t Length = 0;
2947 if (parsePositiveInteger(&Length))
2948 return nullptr;
2949 if (numLeft() < Length || Length == 0)
2950 return nullptr;
2951 StringView Name(First, First + Length);
2952 First += Length;
2953 if (Name.startsWith("_GLOBAL__N"))
2954 return make<NameType>("(anonymous namespace)");
2955 return make<NameType>(Name);
2956}
2957
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002958// If the next 2 chars are an operator encoding, consume them and return their
2959// OperatorInfo. Otherwise return nullptr.
2960template <typename Derived, typename Alloc>
2961const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
2962AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
2963 static const OperatorInfo Ops[] = {
2964 // Keep ordered by encoding
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002965 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
2966 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
2967 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
2968 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
2969 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
2970 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary,
2971 "alignof "},
2972 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
2973 "operator co_await"},
2974 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
2975 "alignof "},
2976 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
2977 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
2978 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
2979 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
2980 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast,
2981 "operator"}, // C Cast
2982 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
2983 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
2984 "operator delete[]"},
2985 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
2986 "dynamic_cast"},
2987 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
2988 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
2989 "operator delete"},
2990 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2991 "operator.*"},
2992 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
2993 "operator."},
2994 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
2995 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
2996 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
2997 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
2998 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
2999 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
3000 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
3001 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
3002 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
3003 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
3004 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
3005 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
3006 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
3007 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
3008 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3009 "operator*"},
3010 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
3011 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
3012 "operator new[]"},
3013 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
3014 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
3015 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
3016 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary,
3017 "operator new"},
3018 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
3019 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
3020 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
3021 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
3022 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
3023 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3024 "operator->*"},
3025 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
3026 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
3027 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
3028 "operator->"},
3029 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
3030 "operator?"},
3031 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
3032 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
3033 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3034 "reinterpret_cast"},
3035 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3036 "operator%"},
3037 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3038 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3039 "static_cast"},
3040 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3041 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3042 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
3043 "sizeof "},
3044 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3045 "typeid "},
3046 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix,
3047 "typeid "},
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003048 };
3049 const auto NumOps = sizeof(Ops) / sizeof(Ops[0]);
3050
3051#ifndef NDEBUG
3052 {
3053 // Verify table order.
3054 static bool Done;
3055 if (!Done) {
3056 Done = true;
3057 for (const auto *Op = &Ops[0]; Op != &Ops[NumOps - 1]; Op++)
3058 assert(Op[0] < Op[1] && "Operator table is not ordered");
3059 }
3060 }
3061#endif
3062
3063 if (numLeft() < 2)
3064 return nullptr;
3065
3066 auto Op = std::lower_bound(
3067 &Ops[0], &Ops[NumOps], First,
3068 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3069 if (Op == &Ops[NumOps] || *Op != First)
3070 return nullptr;
3071
3072 First += 2;
3073 return Op;
3074}
3075
3076// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003077// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003078// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003079template <typename Derived, typename Alloc>
3080Node *
3081AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003082 if (const auto *Op = parseOperatorEncoding()) {
3083 if (Op->getKind() == OperatorInfo::CCast) {
3084 // ::= cv <type> # (cast)
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003085 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);
Richard Smithc20d1442018-08-20 20:14:49 +00003086 // If we're parsing an encoding, State != nullptr and the conversion
3087 // operators' <type> could have a <template-param> that refers to some
3088 // <template-arg>s further ahead in the mangled name.
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003089 ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,
Richard Smithc20d1442018-08-20 20:14:49 +00003090 PermitForwardTemplateReferences ||
3091 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003092 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003093 if (Ty == nullptr)
3094 return nullptr;
3095 if (State) State->CtorDtorConversion = true;
3096 return make<ConversionOperatorType>(Ty);
3097 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003098
3099 if (Op->getKind() >= OperatorInfo::Unnameable)
3100 /* Not a nameable operator. */
3101 return nullptr;
3102 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3103 /* Not a nameable MemberExpr */
3104 return nullptr;
3105
3106 return make<NameType>(Op->getName());
3107 }
3108
3109 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003110 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003111 Node *SN = getDerived().parseSourceName(State);
3112 if (SN == nullptr)
3113 return nullptr;
3114 return make<LiteralOperator>(SN);
3115 }
3116
3117 if (consumeIf('v')) {
3118 // ::= v <digit> <source-name> # vendor extended operator
3119 if (look() >= '0' && look() <= '9') {
3120 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003121 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003122 if (SN == nullptr)
3123 return nullptr;
3124 return make<ConversionOperatorType>(SN);
3125 }
3126 return nullptr;
3127 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003128
Richard Smithc20d1442018-08-20 20:14:49 +00003129 return nullptr;
3130}
3131
3132// <ctor-dtor-name> ::= C1 # complete object constructor
3133// ::= C2 # base object constructor
3134// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003135// extension ::= C4 # gcc old-style "[unified]" constructor
3136// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003137// ::= D0 # deleting destructor
3138// ::= D1 # complete object destructor
3139// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003140// extension ::= D4 # gcc old-style "[unified]" destructor
3141// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003142template <typename Derived, typename Alloc>
3143Node *
3144AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3145 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003146 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3147 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3148 switch (SSK) {
3149 case SpecialSubKind::string:
3150 case SpecialSubKind::istream:
3151 case SpecialSubKind::ostream:
3152 case SpecialSubKind::iostream:
3153 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00003154 if (!SoFar)
3155 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00003156 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003157 default:
3158 break;
3159 }
3160 }
3161
3162 if (consumeIf('C')) {
3163 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003164 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3165 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003166 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003167 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003168 ++First;
3169 if (State) State->CtorDtorConversion = true;
3170 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003171 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003172 return nullptr;
3173 }
Nico Weber29294792019-04-03 23:14:33 +00003174 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003175 }
3176
Nico Weber29294792019-04-03 23:14:33 +00003177 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3178 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003179 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003180 First += 2;
3181 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003182 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003183 }
3184
3185 return nullptr;
3186}
3187
Nathan Sidwellac492da2022-04-05 09:25:47 -07003188// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3189// <unqualified-name> E
3190// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3191// <template-args> E
Richard Smithc20d1442018-08-20 20:14:49 +00003192//
Nathan Sidwellac492da2022-04-05 09:25:47 -07003193// <prefix> ::= <prefix> <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003194// ::= <template-prefix> <template-args>
3195// ::= <template-param>
3196// ::= <decltype>
3197// ::= # empty
3198// ::= <substitution>
3199// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003200// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003201//
3202// <data-member-prefix> := <member source-name> [<template-args>] M
3203//
3204// <template-prefix> ::= <prefix> <template unqualified-name>
3205// ::= <template-param>
3206// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003207template <typename Derived, typename Alloc>
3208Node *
3209AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003210 if (!consumeIf('N'))
3211 return nullptr;
3212
3213 Qualifiers CVTmp = parseCVQualifiers();
3214 if (State) State->CVQualifiers = CVTmp;
3215
3216 if (consumeIf('O')) {
3217 if (State) State->ReferenceQualifier = FrefQualRValue;
3218 } else if (consumeIf('R')) {
3219 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003220 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003221 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003222 }
Richard Smithc20d1442018-08-20 20:14:49 +00003223
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003224 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003225 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003226 if (State)
3227 // Only set end-with-template on the case that does that.
3228 State->EndsWithTemplateArgs = false;
3229
Richard Smithc20d1442018-08-20 20:14:49 +00003230 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003231 // ::= <template-param>
3232 if (SoFar != nullptr)
3233 return nullptr; // Cannot have a prefix.
3234 SoFar = getDerived().parseTemplateParam();
3235 } else if (look() == 'I') {
3236 // ::= <template-prefix> <template-args>
3237 if (SoFar == nullptr)
3238 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003239 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003240 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003241 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003242 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3243 // Semantically <template-args> <template-args> cannot be generated by a
3244 // C++ entity. There will always be [something like] a name between
3245 // them.
3246 return nullptr;
3247 if (State)
3248 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003249 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003250 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3251 // ::= <decltype>
3252 if (SoFar != nullptr)
3253 return nullptr; // Cannot have a prefix.
3254 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003255 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003256 ModuleName *Module = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003257
3258 if (look() == 'S') {
3259 // ::= <substitution>
3260 Node *S = nullptr;
3261 if (look(1) == 't') {
3262 First += 2;
3263 S = make<NameType>("std");
3264 } else {
3265 S = getDerived().parseSubstitution();
3266 }
3267 if (!S)
3268 return nullptr;
3269 if (S->getKind() == Node::KModuleName) {
3270 Module = static_cast<ModuleName *>(S);
Nathan Sidwellac492da2022-04-05 09:25:47 -07003271 } else if (SoFar != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003272 return nullptr; // Cannot have a prefix.
3273 } else {
3274 SoFar = S;
3275 continue; // Do not push a new substitution.
3276 }
3277 }
3278
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003279 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003280 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003281 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003282
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003283 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003284 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003285 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003286
3287 // No longer used.
3288 // <data-member-prefix> := <member source-name> [<template-args>] M
3289 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003290 }
3291
3292 if (SoFar == nullptr || Subs.empty())
3293 return nullptr;
3294
3295 Subs.pop_back();
3296 return SoFar;
3297}
3298
3299// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003300template <typename Derived, typename Alloc>
3301Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3302 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003303 if (SN == nullptr)
3304 return nullptr;
3305 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003306 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003307 if (TA == nullptr)
3308 return nullptr;
3309 return make<NameWithTemplateArgs>(SN, TA);
3310 }
3311 return SN;
3312}
3313
3314// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3315// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003316template <typename Derived, typename Alloc>
3317Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003318 Node *Result;
3319 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003320 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003321 else
Pavel Labathba825192018-10-16 14:29:14 +00003322 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003323 if (Result == nullptr)
3324 return nullptr;
3325 return make<DtorName>(Result);
3326}
3327
3328// <unresolved-type> ::= <template-param>
3329// ::= <decltype>
3330// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003331template <typename Derived, typename Alloc>
3332Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003333 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003334 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003335 if (TP == nullptr)
3336 return nullptr;
3337 Subs.push_back(TP);
3338 return TP;
3339 }
3340 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003341 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003342 if (DT == nullptr)
3343 return nullptr;
3344 Subs.push_back(DT);
3345 return DT;
3346 }
Pavel Labathba825192018-10-16 14:29:14 +00003347 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003348}
3349
3350// <base-unresolved-name> ::= <simple-id> # unresolved name
3351// extension ::= <operator-name> # unresolved operator-function-id
3352// extension ::= <operator-name> <template-args> # unresolved operator template-id
3353// ::= on <operator-name> # unresolved operator-function-id
3354// ::= on <operator-name> <template-args> # unresolved operator template-id
3355// ::= dn <destructor-name> # destructor or pseudo-destructor;
3356// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003357template <typename Derived, typename Alloc>
3358Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003359 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003360 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003361
3362 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003363 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003364
3365 consumeIf("on");
3366
Pavel Labathba825192018-10-16 14:29:14 +00003367 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003368 if (Oper == nullptr)
3369 return nullptr;
3370 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003371 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003372 if (TA == nullptr)
3373 return nullptr;
3374 return make<NameWithTemplateArgs>(Oper, TA);
3375 }
3376 return Oper;
3377}
3378
3379// <unresolved-name>
3380// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3381// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3382// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3383// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003384// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003385// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3386// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3387// # T::N::x /decltype(p)::N::x
3388// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3389//
3390// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003391template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003392Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003393 Node *SoFar = nullptr;
3394
3395 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3396 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3397 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003398 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003399 if (SoFar == nullptr)
3400 return nullptr;
3401
3402 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003403 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003404 if (TA == nullptr)
3405 return nullptr;
3406 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003407 if (!SoFar)
3408 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003409 }
3410
3411 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003412 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003413 if (Qual == nullptr)
3414 return nullptr;
3415 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003416 if (!SoFar)
3417 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003418 }
3419
Pavel Labathba825192018-10-16 14:29:14 +00003420 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003421 if (Base == nullptr)
3422 return nullptr;
3423 return make<QualifiedName>(SoFar, Base);
3424 }
3425
Richard Smithc20d1442018-08-20 20:14:49 +00003426 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3427 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003428 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003429 if (SoFar == nullptr)
3430 return nullptr;
3431 if (Global)
3432 SoFar = make<GlobalQualifiedName>(SoFar);
3433 return SoFar;
3434 }
3435
3436 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3437 if (std::isdigit(look())) {
3438 do {
Pavel Labathba825192018-10-16 14:29:14 +00003439 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003440 if (Qual == nullptr)
3441 return nullptr;
3442 if (SoFar)
3443 SoFar = make<QualifiedName>(SoFar, Qual);
3444 else if (Global)
3445 SoFar = make<GlobalQualifiedName>(Qual);
3446 else
3447 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003448 if (!SoFar)
3449 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003450 } while (!consumeIf('E'));
3451 }
3452 // sr <unresolved-type> <base-unresolved-name>
3453 // sr <unresolved-type> <template-args> <base-unresolved-name>
3454 else {
Pavel Labathba825192018-10-16 14:29:14 +00003455 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003456 if (SoFar == nullptr)
3457 return nullptr;
3458
3459 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003460 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003461 if (TA == nullptr)
3462 return nullptr;
3463 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003464 if (!SoFar)
3465 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003466 }
3467 }
3468
3469 assert(SoFar != nullptr);
3470
Pavel Labathba825192018-10-16 14:29:14 +00003471 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003472 if (Base == nullptr)
3473 return nullptr;
3474 return make<QualifiedName>(SoFar, Base);
3475}
3476
3477// <abi-tags> ::= <abi-tag> [<abi-tags>]
3478// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003479template <typename Derived, typename Alloc>
3480Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003481 while (consumeIf('B')) {
3482 StringView SN = parseBareSourceName();
3483 if (SN.empty())
3484 return nullptr;
3485 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003486 if (!N)
3487 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003488 }
3489 return N;
3490}
3491
3492// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003493template <typename Alloc, typename Derived>
3494StringView
3495AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003496 const char *Tmp = First;
3497 if (AllowNegative)
3498 consumeIf('n');
3499 if (numLeft() == 0 || !std::isdigit(*First))
3500 return StringView();
3501 while (numLeft() != 0 && std::isdigit(*First))
3502 ++First;
3503 return StringView(Tmp, First);
3504}
3505
3506// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003507template <typename Alloc, typename Derived>
3508bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003509 *Out = 0;
3510 if (look() < '0' || look() > '9')
3511 return true;
3512 while (look() >= '0' && look() <= '9') {
3513 *Out *= 10;
3514 *Out += static_cast<size_t>(consume() - '0');
3515 }
3516 return false;
3517}
3518
Pavel Labathba825192018-10-16 14:29:14 +00003519template <typename Alloc, typename Derived>
3520StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003521 size_t Int = 0;
3522 if (parsePositiveInteger(&Int) || numLeft() < Int)
3523 return StringView();
3524 StringView R(First, First + Int);
3525 First += Int;
3526 return R;
3527}
3528
3529// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3530//
3531// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3532// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3533// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3534//
3535// <ref-qualifier> ::= R # & ref-qualifier
3536// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003537template <typename Derived, typename Alloc>
3538Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003539 Qualifiers CVQuals = parseCVQualifiers();
3540
3541 Node *ExceptionSpec = nullptr;
3542 if (consumeIf("Do")) {
3543 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003544 if (!ExceptionSpec)
3545 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003546 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003547 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003548 if (E == nullptr || !consumeIf('E'))
3549 return nullptr;
3550 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003551 if (!ExceptionSpec)
3552 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003553 } else if (consumeIf("Dw")) {
3554 size_t SpecsBegin = Names.size();
3555 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003556 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003557 if (T == nullptr)
3558 return nullptr;
3559 Names.push_back(T);
3560 }
3561 ExceptionSpec =
3562 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003563 if (!ExceptionSpec)
3564 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003565 }
3566
3567 consumeIf("Dx"); // transaction safe
3568
3569 if (!consumeIf('F'))
3570 return nullptr;
3571 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003572 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003573 if (ReturnType == nullptr)
3574 return nullptr;
3575
3576 FunctionRefQual ReferenceQualifier = FrefQualNone;
3577 size_t ParamsBegin = Names.size();
3578 while (true) {
3579 if (consumeIf('E'))
3580 break;
3581 if (consumeIf('v'))
3582 continue;
3583 if (consumeIf("RE")) {
3584 ReferenceQualifier = FrefQualLValue;
3585 break;
3586 }
3587 if (consumeIf("OE")) {
3588 ReferenceQualifier = FrefQualRValue;
3589 break;
3590 }
Pavel Labathba825192018-10-16 14:29:14 +00003591 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003592 if (T == nullptr)
3593 return nullptr;
3594 Names.push_back(T);
3595 }
3596
3597 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3598 return make<FunctionType>(ReturnType, Params, CVQuals,
3599 ReferenceQualifier, ExceptionSpec);
3600}
3601
3602// extension:
3603// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3604// ::= Dv [<dimension expression>] _ <element type>
3605// <extended element type> ::= <element type>
3606// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003607template <typename Derived, typename Alloc>
3608Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003609 if (!consumeIf("Dv"))
3610 return nullptr;
3611 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003612 Node *DimensionNumber = make<NameType>(parseNumber());
3613 if (!DimensionNumber)
3614 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003615 if (!consumeIf('_'))
3616 return nullptr;
3617 if (consumeIf('p'))
3618 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003619 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003620 if (ElemType == nullptr)
3621 return nullptr;
3622 return make<VectorType>(ElemType, DimensionNumber);
3623 }
3624
3625 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003626 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003627 if (!DimExpr)
3628 return nullptr;
3629 if (!consumeIf('_'))
3630 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003631 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003632 if (!ElemType)
3633 return nullptr;
3634 return make<VectorType>(ElemType, DimExpr);
3635 }
Pavel Labathba825192018-10-16 14:29:14 +00003636 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003637 if (!ElemType)
3638 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003639 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003640}
3641
3642// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3643// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003644template <typename Derived, typename Alloc>
3645Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003646 if (!consumeIf('D'))
3647 return nullptr;
3648 if (!consumeIf('t') && !consumeIf('T'))
3649 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003650 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003651 if (E == nullptr)
3652 return nullptr;
3653 if (!consumeIf('E'))
3654 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003655 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003656}
3657
3658// <array-type> ::= A <positive dimension number> _ <element type>
3659// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003660template <typename Derived, typename Alloc>
3661Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003662 if (!consumeIf('A'))
3663 return nullptr;
3664
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003665 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003666
Richard Smithc20d1442018-08-20 20:14:49 +00003667 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003668 Dimension = make<NameType>(parseNumber());
3669 if (!Dimension)
3670 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003671 if (!consumeIf('_'))
3672 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003673 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003674 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003675 if (DimExpr == nullptr)
3676 return nullptr;
3677 if (!consumeIf('_'))
3678 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003679 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003680 }
3681
Pavel Labathba825192018-10-16 14:29:14 +00003682 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003683 if (Ty == nullptr)
3684 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003685 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003686}
3687
3688// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003689template <typename Derived, typename Alloc>
3690Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003691 if (!consumeIf('M'))
3692 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003693 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003694 if (ClassType == nullptr)
3695 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003696 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003697 if (MemberType == nullptr)
3698 return nullptr;
3699 return make<PointerToMemberType>(ClassType, MemberType);
3700}
3701
3702// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3703// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3704// ::= Tu <name> # dependent elaborated type specifier using 'union'
3705// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003706template <typename Derived, typename Alloc>
3707Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003708 StringView ElabSpef;
3709 if (consumeIf("Ts"))
3710 ElabSpef = "struct";
3711 else if (consumeIf("Tu"))
3712 ElabSpef = "union";
3713 else if (consumeIf("Te"))
3714 ElabSpef = "enum";
3715
Pavel Labathba825192018-10-16 14:29:14 +00003716 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003717 if (Name == nullptr)
3718 return nullptr;
3719
3720 if (!ElabSpef.empty())
3721 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3722
3723 return Name;
3724}
3725
3726// <qualified-type> ::= <qualifiers> <type>
3727// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3728// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003729template <typename Derived, typename Alloc>
3730Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003731 if (consumeIf('U')) {
3732 StringView Qual = parseBareSourceName();
3733 if (Qual.empty())
3734 return nullptr;
3735
Richard Smithc20d1442018-08-20 20:14:49 +00003736 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3737 if (Qual.startsWith("objcproto")) {
3738 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3739 StringView Proto;
3740 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003741 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()),
3742 SaveLast(Last, ProtoSourceName.end());
Richard Smithc20d1442018-08-20 20:14:49 +00003743 Proto = parseBareSourceName();
3744 }
3745 if (Proto.empty())
3746 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003747 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003748 if (Child == nullptr)
3749 return nullptr;
3750 return make<ObjCProtoName>(Child, Proto);
3751 }
3752
Alex Orlovf50df922021-03-24 10:21:32 +04003753 Node *TA = nullptr;
3754 if (look() == 'I') {
3755 TA = getDerived().parseTemplateArgs();
3756 if (TA == nullptr)
3757 return nullptr;
3758 }
3759
Pavel Labathba825192018-10-16 14:29:14 +00003760 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003761 if (Child == nullptr)
3762 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003763 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003764 }
3765
3766 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003767 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003768 if (Ty == nullptr)
3769 return nullptr;
3770 if (Quals != QualNone)
3771 Ty = make<QualType>(Ty, Quals);
3772 return Ty;
3773}
3774
3775// <type> ::= <builtin-type>
3776// ::= <qualified-type>
3777// ::= <function-type>
3778// ::= <class-enum-type>
3779// ::= <array-type>
3780// ::= <pointer-to-member-type>
3781// ::= <template-param>
3782// ::= <template-template-param> <template-args>
3783// ::= <decltype>
3784// ::= P <type> # pointer
3785// ::= R <type> # l-value reference
3786// ::= O <type> # r-value reference (C++11)
3787// ::= C <type> # complex pair (C99)
3788// ::= G <type> # imaginary (C99)
3789// ::= <substitution> # See Compression below
3790// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3791// extension ::= <vector-type> # <vector-type> starts with Dv
3792//
3793// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3794// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003795template <typename Derived, typename Alloc>
3796Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003797 Node *Result = nullptr;
3798
Richard Smithc20d1442018-08-20 20:14:49 +00003799 switch (look()) {
3800 // ::= <qualified-type>
3801 case 'r':
3802 case 'V':
3803 case 'K': {
3804 unsigned AfterQuals = 0;
3805 if (look(AfterQuals) == 'r') ++AfterQuals;
3806 if (look(AfterQuals) == 'V') ++AfterQuals;
3807 if (look(AfterQuals) == 'K') ++AfterQuals;
3808
3809 if (look(AfterQuals) == 'F' ||
3810 (look(AfterQuals) == 'D' &&
3811 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3812 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003813 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003814 break;
3815 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003816 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003817 }
3818 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003819 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003820 break;
3821 }
3822 // <builtin-type> ::= v # void
3823 case 'v':
3824 ++First;
3825 return make<NameType>("void");
3826 // ::= w # wchar_t
3827 case 'w':
3828 ++First;
3829 return make<NameType>("wchar_t");
3830 // ::= b # bool
3831 case 'b':
3832 ++First;
3833 return make<NameType>("bool");
3834 // ::= c # char
3835 case 'c':
3836 ++First;
3837 return make<NameType>("char");
3838 // ::= a # signed char
3839 case 'a':
3840 ++First;
3841 return make<NameType>("signed char");
3842 // ::= h # unsigned char
3843 case 'h':
3844 ++First;
3845 return make<NameType>("unsigned char");
3846 // ::= s # short
3847 case 's':
3848 ++First;
3849 return make<NameType>("short");
3850 // ::= t # unsigned short
3851 case 't':
3852 ++First;
3853 return make<NameType>("unsigned short");
3854 // ::= i # int
3855 case 'i':
3856 ++First;
3857 return make<NameType>("int");
3858 // ::= j # unsigned int
3859 case 'j':
3860 ++First;
3861 return make<NameType>("unsigned int");
3862 // ::= l # long
3863 case 'l':
3864 ++First;
3865 return make<NameType>("long");
3866 // ::= m # unsigned long
3867 case 'm':
3868 ++First;
3869 return make<NameType>("unsigned long");
3870 // ::= x # long long, __int64
3871 case 'x':
3872 ++First;
3873 return make<NameType>("long long");
3874 // ::= y # unsigned long long, __int64
3875 case 'y':
3876 ++First;
3877 return make<NameType>("unsigned long long");
3878 // ::= n # __int128
3879 case 'n':
3880 ++First;
3881 return make<NameType>("__int128");
3882 // ::= o # unsigned __int128
3883 case 'o':
3884 ++First;
3885 return make<NameType>("unsigned __int128");
3886 // ::= f # float
3887 case 'f':
3888 ++First;
3889 return make<NameType>("float");
3890 // ::= d # double
3891 case 'd':
3892 ++First;
3893 return make<NameType>("double");
3894 // ::= e # long double, __float80
3895 case 'e':
3896 ++First;
3897 return make<NameType>("long double");
3898 // ::= g # __float128
3899 case 'g':
3900 ++First;
3901 return make<NameType>("__float128");
3902 // ::= z # ellipsis
3903 case 'z':
3904 ++First;
3905 return make<NameType>("...");
3906
3907 // <builtin-type> ::= u <source-name> # vendor extended type
3908 case 'u': {
3909 ++First;
3910 StringView Res = parseBareSourceName();
3911 if (Res.empty())
3912 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003913 // Typically, <builtin-type>s are not considered substitution candidates,
3914 // but the exception to that exception is vendor extended types (Itanium C++
3915 // ABI 5.9.1).
3916 Result = make<NameType>(Res);
3917 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003918 }
3919 case 'D':
3920 switch (look(1)) {
3921 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3922 case 'd':
3923 First += 2;
3924 return make<NameType>("decimal64");
3925 // ::= De # IEEE 754r decimal floating point (128 bits)
3926 case 'e':
3927 First += 2;
3928 return make<NameType>("decimal128");
3929 // ::= Df # IEEE 754r decimal floating point (32 bits)
3930 case 'f':
3931 First += 2;
3932 return make<NameType>("decimal32");
3933 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3934 case 'h':
3935 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003936 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003937 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3938 case 'F': {
3939 First += 2;
3940 Node *DimensionNumber = make<NameType>(parseNumber());
3941 if (!DimensionNumber)
3942 return nullptr;
3943 if (!consumeIf('_'))
3944 return nullptr;
3945 return make<BinaryFPType>(DimensionNumber);
3946 }
Senran Zhange025ba52022-03-27 00:04:23 +08003947 // ::= DB <number> _ # C23 signed _BitInt(N)
3948 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
3949 // ::= DU <number> _ # C23 unsigned _BitInt(N)
3950 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
3951 case 'B':
3952 case 'U': {
3953 bool Signed = look(1) == 'B';
3954 First += 2;
3955 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())
3956 : getDerived().parseExpr();
3957 if (!Size)
3958 return nullptr;
3959 if (!consumeIf('_'))
3960 return nullptr;
3961 return make<BitIntType>(Size, Signed);
3962 }
Richard Smithc20d1442018-08-20 20:14:49 +00003963 // ::= Di # char32_t
3964 case 'i':
3965 First += 2;
3966 return make<NameType>("char32_t");
3967 // ::= Ds # char16_t
3968 case 's':
3969 First += 2;
3970 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003971 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3972 case 'u':
3973 First += 2;
3974 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003975 // ::= Da # auto (in dependent new-expressions)
3976 case 'a':
3977 First += 2;
3978 return make<NameType>("auto");
3979 // ::= Dc # decltype(auto)
3980 case 'c':
3981 First += 2;
3982 return make<NameType>("decltype(auto)");
3983 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3984 case 'n':
3985 First += 2;
3986 return make<NameType>("std::nullptr_t");
3987
3988 // ::= <decltype>
3989 case 't':
3990 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003991 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003992 break;
3993 }
3994 // extension ::= <vector-type> # <vector-type> starts with Dv
3995 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003996 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003997 break;
3998 }
3999 // ::= Dp <type> # pack expansion (C++0x)
4000 case 'p': {
4001 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004002 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004003 if (!Child)
4004 return nullptr;
4005 Result = make<ParameterPackExpansion>(Child);
4006 break;
4007 }
4008 // Exception specifier on a function type.
4009 case 'o':
4010 case 'O':
4011 case 'w':
4012 // Transaction safe function type.
4013 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00004014 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00004015 break;
4016 }
4017 break;
4018 // ::= <function-type>
4019 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00004020 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00004021 break;
4022 }
4023 // ::= <array-type>
4024 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00004025 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00004026 break;
4027 }
4028 // ::= <pointer-to-member-type>
4029 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00004030 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00004031 break;
4032 }
4033 // ::= <template-param>
4034 case 'T': {
4035 // This could be an elaborate type specifier on a <class-enum-type>.
4036 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00004037 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004038 break;
4039 }
4040
Pavel Labathba825192018-10-16 14:29:14 +00004041 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004042 if (Result == nullptr)
4043 return nullptr;
4044
4045 // Result could be either of:
4046 // <type> ::= <template-param>
4047 // <type> ::= <template-template-param> <template-args>
4048 //
4049 // <template-template-param> ::= <template-param>
4050 // ::= <substitution>
4051 //
4052 // If this is followed by some <template-args>, and we're permitted to
4053 // parse them, take the second production.
4054
4055 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004056 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004057 if (TA == nullptr)
4058 return nullptr;
4059 Result = make<NameWithTemplateArgs>(Result, TA);
4060 }
4061 break;
4062 }
4063 // ::= P <type> # pointer
4064 case 'P': {
4065 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004066 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004067 if (Ptr == nullptr)
4068 return nullptr;
4069 Result = make<PointerType>(Ptr);
4070 break;
4071 }
4072 // ::= R <type> # l-value reference
4073 case 'R': {
4074 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004075 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004076 if (Ref == nullptr)
4077 return nullptr;
4078 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4079 break;
4080 }
4081 // ::= O <type> # r-value reference (C++11)
4082 case 'O': {
4083 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004084 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004085 if (Ref == nullptr)
4086 return nullptr;
4087 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4088 break;
4089 }
4090 // ::= C <type> # complex pair (C99)
4091 case 'C': {
4092 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004093 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004094 if (P == nullptr)
4095 return nullptr;
4096 Result = make<PostfixQualifiedType>(P, " complex");
4097 break;
4098 }
4099 // ::= G <type> # imaginary (C99)
4100 case 'G': {
4101 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004102 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004103 if (P == nullptr)
4104 return P;
4105 Result = make<PostfixQualifiedType>(P, " imaginary");
4106 break;
4107 }
4108 // ::= <substitution> # See Compression below
4109 case 'S': {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004110 if (look(1) != 't') {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004111 bool IsSubst = false;
4112 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4113 if (!Result)
Richard Smithc20d1442018-08-20 20:14:49 +00004114 return nullptr;
4115
4116 // Sub could be either of:
4117 // <type> ::= <substitution>
4118 // <type> ::= <template-template-param> <template-args>
4119 //
4120 // <template-template-param> ::= <template-param>
4121 // ::= <substitution>
4122 //
4123 // If this is followed by some <template-args>, and we're permitted to
4124 // parse them, take the second production.
4125
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004126 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4127 if (!IsSubst)
4128 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00004129 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004130 if (TA == nullptr)
4131 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004132 Result = make<NameWithTemplateArgs>(Result, TA);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004133 } else if (IsSubst) {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004134 // If all we parsed was a substitution, don't re-insert into the
4135 // substitution table.
4136 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00004137 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004138 break;
Richard Smithc20d1442018-08-20 20:14:49 +00004139 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004140 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004141 }
4142 // ::= <class-enum-type>
4143 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004144 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004145 break;
4146 }
4147 }
4148
4149 // If we parsed a type, insert it into the substitution table. Note that all
4150 // <builtin-type>s and <substitution>s have already bailed out, because they
4151 // don't get substitutions.
4152 if (Result != nullptr)
4153 Subs.push_back(Result);
4154 return Result;
4155}
4156
Pavel Labathba825192018-10-16 14:29:14 +00004157template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004158Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4159 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004160 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004161 if (E == nullptr)
4162 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004163 return make<PrefixExpr>(Kind, E, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004164}
4165
Pavel Labathba825192018-10-16 14:29:14 +00004166template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004167Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4168 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004169 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004170 if (LHS == nullptr)
4171 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004172 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004173 if (RHS == nullptr)
4174 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004175 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004176}
4177
Pavel Labathba825192018-10-16 14:29:14 +00004178template <typename Derived, typename Alloc>
4179Node *
4180AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004181 StringView Tmp = parseNumber(true);
4182 if (!Tmp.empty() && consumeIf('E'))
4183 return make<IntegerLiteral>(Lit, Tmp);
4184 return nullptr;
4185}
4186
4187// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004188template <typename Alloc, typename Derived>
4189Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004190 Qualifiers CVR = QualNone;
4191 if (consumeIf('r'))
4192 CVR |= QualRestrict;
4193 if (consumeIf('V'))
4194 CVR |= QualVolatile;
4195 if (consumeIf('K'))
4196 CVR |= QualConst;
4197 return CVR;
4198}
4199
4200// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4201// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4202// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4203// ::= 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 -04004204// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004205template <typename Derived, typename Alloc>
4206Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004207 if (consumeIf("fpT"))
4208 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004209 if (consumeIf("fp")) {
4210 parseCVQualifiers();
4211 StringView Num = parseNumber();
4212 if (!consumeIf('_'))
4213 return nullptr;
4214 return make<FunctionParam>(Num);
4215 }
4216 if (consumeIf("fL")) {
4217 if (parseNumber().empty())
4218 return nullptr;
4219 if (!consumeIf('p'))
4220 return nullptr;
4221 parseCVQualifiers();
4222 StringView Num = parseNumber();
4223 if (!consumeIf('_'))
4224 return nullptr;
4225 return make<FunctionParam>(Num);
4226 }
4227 return nullptr;
4228}
4229
Richard Smithc20d1442018-08-20 20:14:49 +00004230// cv <type> <expression> # conversion with one argument
4231// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004232template <typename Derived, typename Alloc>
4233Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004234 if (!consumeIf("cv"))
4235 return nullptr;
4236 Node *Ty;
4237 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004238 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004239 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004240 }
4241
4242 if (Ty == nullptr)
4243 return nullptr;
4244
4245 if (consumeIf('_')) {
4246 size_t ExprsBegin = Names.size();
4247 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004248 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004249 if (E == nullptr)
4250 return E;
4251 Names.push_back(E);
4252 }
4253 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4254 return make<ConversionExpr>(Ty, Exprs);
4255 }
4256
Pavel Labathba825192018-10-16 14:29:14 +00004257 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004258 if (E[0] == nullptr)
4259 return nullptr;
4260 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4261}
4262
4263// <expr-primary> ::= L <type> <value number> E # integer literal
4264// ::= L <type> <value float> E # floating literal
4265// ::= L <string type> E # string literal
4266// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004267// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004268// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4269// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004270template <typename Derived, typename Alloc>
4271Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004272 if (!consumeIf('L'))
4273 return nullptr;
4274 switch (look()) {
4275 case 'w':
4276 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004277 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004278 case 'b':
4279 if (consumeIf("b0E"))
4280 return make<BoolExpr>(0);
4281 if (consumeIf("b1E"))
4282 return make<BoolExpr>(1);
4283 return nullptr;
4284 case 'c':
4285 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004286 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004287 case 'a':
4288 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004289 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004290 case 'h':
4291 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004292 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004293 case 's':
4294 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004295 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004296 case 't':
4297 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004298 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004299 case 'i':
4300 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004301 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004302 case 'j':
4303 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004304 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004305 case 'l':
4306 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004307 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004308 case 'm':
4309 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004310 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004311 case 'x':
4312 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004313 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004314 case 'y':
4315 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004316 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004317 case 'n':
4318 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004319 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004320 case 'o':
4321 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004322 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004323 case 'f':
4324 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004325 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004326 case 'd':
4327 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004328 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004329 case 'e':
4330 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004331#if defined(__powerpc__) || defined(__s390__)
4332 // Handle cases where long doubles encoded with e have the same size
4333 // and representation as doubles.
4334 return getDerived().template parseFloatingLiteral<double>();
4335#else
Pavel Labathba825192018-10-16 14:29:14 +00004336 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004337#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004338 case '_':
4339 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004340 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004341 if (R != nullptr && consumeIf('E'))
4342 return R;
4343 }
4344 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004345 case 'A': {
4346 Node *T = getDerived().parseType();
4347 if (T == nullptr)
4348 return nullptr;
4349 // FIXME: We need to include the string contents in the mangling.
4350 if (consumeIf('E'))
4351 return make<StringLiteral>(T);
4352 return nullptr;
4353 }
4354 case 'D':
4355 if (consumeIf("DnE"))
4356 return make<NameType>("nullptr");
4357 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004358 case 'T':
4359 // Invalid mangled name per
4360 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4361 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004362 case 'U': {
4363 // FIXME: Should we support LUb... for block literals?
4364 if (look(1) != 'l')
4365 return nullptr;
4366 Node *T = parseUnnamedTypeName(nullptr);
4367 if (!T || !consumeIf('E'))
4368 return nullptr;
4369 return make<LambdaExpr>(T);
4370 }
Richard Smithc20d1442018-08-20 20:14:49 +00004371 default: {
4372 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004373 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004374 if (T == nullptr)
4375 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004376 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004377 if (N.empty())
4378 return nullptr;
4379 if (!consumeIf('E'))
4380 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004381 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004382 }
4383 }
4384}
4385
4386// <braced-expression> ::= <expression>
4387// ::= di <field source-name> <braced-expression> # .name = expr
4388// ::= dx <index expression> <braced-expression> # [expr] = expr
4389// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004390template <typename Derived, typename Alloc>
4391Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004392 if (look() == 'd') {
4393 switch (look(1)) {
4394 case 'i': {
4395 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004396 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004397 if (Field == nullptr)
4398 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004399 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004400 if (Init == nullptr)
4401 return nullptr;
4402 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4403 }
4404 case 'x': {
4405 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004406 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004407 if (Index == nullptr)
4408 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004409 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004410 if (Init == nullptr)
4411 return nullptr;
4412 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4413 }
4414 case 'X': {
4415 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004416 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004417 if (RangeBegin == nullptr)
4418 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004419 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004420 if (RangeEnd == nullptr)
4421 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004422 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004423 if (Init == nullptr)
4424 return nullptr;
4425 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4426 }
4427 }
4428 }
Pavel Labathba825192018-10-16 14:29:14 +00004429 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004430}
4431
4432// (not yet in the spec)
4433// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4434// ::= fR <binary-operator-name> <expression> <expression>
4435// ::= fl <binary-operator-name> <expression>
4436// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004437template <typename Derived, typename Alloc>
4438Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004439 if (!consumeIf('f'))
4440 return nullptr;
4441
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004442 bool IsLeftFold = false, HasInitializer = false;
4443 switch (look()) {
4444 default:
Richard Smithc20d1442018-08-20 20:14:49 +00004445 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004446 case 'L':
4447 IsLeftFold = true;
4448 HasInitializer = true;
4449 break;
4450 case 'R':
4451 HasInitializer = true;
4452 break;
4453 case 'l':
4454 IsLeftFold = true;
4455 break;
4456 case 'r':
4457 break;
4458 }
Richard Smithc20d1442018-08-20 20:14:49 +00004459 ++First;
4460
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004461 const auto *Op = parseOperatorEncoding();
4462 if (!Op || Op->getKind() != OperatorInfo::Binary)
4463 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004464
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004465 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004466 if (Pack == nullptr)
4467 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004468
4469 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004470 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004471 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004472 if (Init == nullptr)
4473 return nullptr;
4474 }
4475
4476 if (IsLeftFold && Init)
4477 std::swap(Pack, Init);
4478
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004479 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004480}
4481
Richard Smith1865d2f2020-10-22 19:29:36 -07004482// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4483//
4484// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4485template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004486Node *
4487AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4488 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004489 Node *Ty = getDerived().parseType();
4490 if (!Ty)
4491 return nullptr;
4492 Node *Expr = getDerived().parseExpr();
4493 if (!Expr)
4494 return nullptr;
4495 StringView Offset = getDerived().parseNumber(true);
4496 if (!consumeIf('E'))
4497 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004498 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004499}
4500
4501// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4502// <union-selector> ::= _ [<number>]
4503//
4504// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4505template <typename Derived, typename Alloc>
4506Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4507 Node *Ty = getDerived().parseType();
4508 if (!Ty)
4509 return nullptr;
4510 Node *Expr = getDerived().parseExpr();
4511 if (!Expr)
4512 return nullptr;
4513 StringView Offset = getDerived().parseNumber(true);
4514 size_t SelectorsBegin = Names.size();
4515 while (consumeIf('_')) {
4516 Node *Selector = make<NameType>(parseNumber());
4517 if (!Selector)
4518 return nullptr;
4519 Names.push_back(Selector);
4520 }
4521 bool OnePastTheEnd = consumeIf('p');
4522 if (!consumeIf('E'))
4523 return nullptr;
4524 return make<SubobjectExpr>(
4525 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4526}
4527
Richard Smithc20d1442018-08-20 20:14:49 +00004528// <expression> ::= <unary operator-name> <expression>
4529// ::= <binary operator-name> <expression> <expression>
4530// ::= <ternary operator-name> <expression> <expression> <expression>
4531// ::= cl <expression>+ E # call
4532// ::= cv <type> <expression> # conversion with one argument
4533// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4534// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4535// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4536// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4537// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4538// ::= [gs] dl <expression> # delete expression
4539// ::= [gs] da <expression> # delete[] expression
4540// ::= pp_ <expression> # prefix ++
4541// ::= mm_ <expression> # prefix --
4542// ::= ti <type> # typeid (type)
4543// ::= te <expression> # typeid (expression)
4544// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4545// ::= sc <type> <expression> # static_cast<type> (expression)
4546// ::= cc <type> <expression> # const_cast<type> (expression)
4547// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4548// ::= st <type> # sizeof (a type)
4549// ::= sz <expression> # sizeof (an expression)
4550// ::= at <type> # alignof (a type)
4551// ::= az <expression> # alignof (an expression)
4552// ::= nx <expression> # noexcept (expression)
4553// ::= <template-param>
4554// ::= <function-param>
4555// ::= dt <expression> <unresolved-name> # expr.name
4556// ::= pt <expression> <unresolved-name> # expr->name
4557// ::= ds <expression> <expression> # expr.*expr
4558// ::= sZ <template-param> # size of a parameter pack
4559// ::= sZ <function-param> # size of a function parameter pack
4560// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4561// ::= sp <expression> # pack expansion
4562// ::= tw <expression> # throw expression
4563// ::= tr # throw with no operand (rethrow)
4564// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4565// # freestanding dependent name (e.g., T::x),
4566// # objectless nonstatic member reference
4567// ::= fL <binary-operator-name> <expression> <expression>
4568// ::= fR <binary-operator-name> <expression> <expression>
4569// ::= fl <binary-operator-name> <expression>
4570// ::= fr <binary-operator-name> <expression>
4571// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004572template <typename Derived, typename Alloc>
4573Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004574 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004575
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004576 const auto *Op = parseOperatorEncoding();
4577 if (Op) {
4578 auto Sym = Op->getSymbol();
4579 switch (Op->getKind()) {
4580 case OperatorInfo::Binary:
4581 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004582 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004583 case OperatorInfo::Prefix:
4584 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004585 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004586 case OperatorInfo::Postfix: {
4587 // Postfix unary operator: expr @
4588 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004589 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004590 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004591 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004592 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004593 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004594 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004595 case OperatorInfo::Array: {
4596 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004597 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004598 if (Base == nullptr)
4599 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004600 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004601 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004602 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004603 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004604 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004605 case OperatorInfo::Member: {
4606 // Member access lhs @ rhs
4607 Node *LHS = getDerived().parseExpr();
4608 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004609 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004610 Node *RHS = getDerived().parseExpr();
4611 if (RHS == nullptr)
4612 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004613 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004614 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004615 case OperatorInfo::New: {
4616 // New
4617 // # new (expr-list) type [(init)]
4618 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4619 // # new[] (expr-list) type [(init)]
4620 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004621 size_t Exprs = Names.size();
4622 while (!consumeIf('_')) {
4623 Node *Ex = getDerived().parseExpr();
4624 if (Ex == nullptr)
4625 return nullptr;
4626 Names.push_back(Ex);
4627 }
4628 NodeArray ExprList = popTrailingNodeArray(Exprs);
4629 Node *Ty = getDerived().parseType();
4630 if (Ty == nullptr)
4631 return nullptr;
4632 bool HaveInits = consumeIf("pi");
4633 size_t InitsBegin = Names.size();
4634 while (!consumeIf('E')) {
4635 if (!HaveInits)
4636 return nullptr;
4637 Node *Init = getDerived().parseExpr();
4638 if (Init == nullptr)
4639 return Init;
4640 Names.push_back(Init);
4641 }
4642 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004643 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004644 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004645 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004646 case OperatorInfo::Del: {
4647 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004648 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004649 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004650 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004651 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4652 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004653 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004654 case OperatorInfo::Call: {
4655 // Function Call
4656 Node *Callee = getDerived().parseExpr();
4657 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004658 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004659 size_t ExprsBegin = Names.size();
4660 while (!consumeIf('E')) {
4661 Node *E = getDerived().parseExpr();
4662 if (E == nullptr)
4663 return nullptr;
4664 Names.push_back(E);
4665 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004666 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4667 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004668 }
4669 case OperatorInfo::CCast: {
4670 // C Cast: (type)expr
4671 Node *Ty;
4672 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004673 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004674 Ty = getDerived().parseType();
4675 }
4676 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004677 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004678
4679 size_t ExprsBegin = Names.size();
4680 bool IsMany = consumeIf('_');
4681 while (!consumeIf('E')) {
4682 Node *E = getDerived().parseExpr();
4683 if (E == nullptr)
4684 return E;
4685 Names.push_back(E);
4686 if (!IsMany)
4687 break;
4688 }
4689 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4690 if (!IsMany && Exprs.size() != 1)
4691 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004692 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004693 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004694 case OperatorInfo::Conditional: {
4695 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004696 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004697 if (Cond == nullptr)
4698 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004699 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004700 if (LHS == nullptr)
4701 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004702 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004703 if (RHS == nullptr)
4704 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004705 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004706 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004707 case OperatorInfo::NamedCast: {
4708 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004709 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004710 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004711 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004712 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004713 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004714 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004715 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004716 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004717 case OperatorInfo::OfIdOp: {
4718 // [sizeof/alignof/typeid] ( <type>|<expr> )
4719 Node *Arg =
4720 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4721 if (!Arg)
4722 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004723 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004724 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004725 case OperatorInfo::NameOnly: {
4726 // Not valid as an expression operand.
4727 return nullptr;
4728 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004729 }
4730 DEMANGLE_UNREACHABLE;
4731 }
4732
4733 if (numLeft() < 2)
4734 return nullptr;
4735
4736 if (look() == 'L')
4737 return getDerived().parseExprPrimary();
4738 if (look() == 'T')
4739 return getDerived().parseTemplateParam();
4740 if (look() == 'f') {
4741 // Disambiguate a fold expression from a <function-param>.
4742 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4743 return getDerived().parseFunctionParam();
4744 return getDerived().parseFoldExpr();
4745 }
4746 if (consumeIf("il")) {
4747 size_t InitsBegin = Names.size();
4748 while (!consumeIf('E')) {
4749 Node *E = getDerived().parseBracedExpr();
4750 if (E == nullptr)
4751 return nullptr;
4752 Names.push_back(E);
4753 }
4754 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4755 }
4756 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004757 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004758 if (consumeIf("nx")) {
4759 Node *Ex = getDerived().parseExpr();
4760 if (Ex == nullptr)
4761 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004762 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004763 }
4764 if (consumeIf("so"))
4765 return parseSubobjectExpr();
4766 if (consumeIf("sp")) {
4767 Node *Child = getDerived().parseExpr();
4768 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004769 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004770 return make<ParameterPackExpansion>(Child);
4771 }
4772 if (consumeIf("sZ")) {
4773 if (look() == 'T') {
4774 Node *R = getDerived().parseTemplateParam();
4775 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004776 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004777 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004778 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004779 Node *FP = getDerived().parseFunctionParam();
4780 if (FP == nullptr)
4781 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004782 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004783 }
4784 if (consumeIf("sP")) {
4785 size_t ArgsBegin = Names.size();
4786 while (!consumeIf('E')) {
4787 Node *Arg = getDerived().parseTemplateArg();
4788 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004789 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004790 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004791 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004792 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4793 if (!Pack)
4794 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004795 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004796 }
4797 if (consumeIf("tl")) {
4798 Node *Ty = getDerived().parseType();
4799 if (Ty == nullptr)
4800 return nullptr;
4801 size_t InitsBegin = Names.size();
4802 while (!consumeIf('E')) {
4803 Node *E = getDerived().parseBracedExpr();
4804 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004805 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004806 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004807 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004808 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4809 }
4810 if (consumeIf("tr"))
4811 return make<NameType>("throw");
4812 if (consumeIf("tw")) {
4813 Node *Ex = getDerived().parseExpr();
4814 if (Ex == nullptr)
4815 return nullptr;
4816 return make<ThrowExpr>(Ex);
4817 }
4818 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004819 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4820 if (!Name)
4821 return nullptr;
4822 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4823 // standard encoding expects a <template-arg>, and would be otherwise be
4824 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4825 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4826 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004827 bool IsUUID = false;
4828 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004829 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004830 if (consumeIf('t')) {
4831 UUID = getDerived().parseType();
4832 IsUUID = true;
4833 } else if (consumeIf('z')) {
4834 UUID = getDerived().parseExpr();
4835 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004836 }
4837 }
4838 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004839 if (IsUUID) {
4840 if (UUID == nullptr)
4841 return nullptr;
4842 Names.push_back(UUID);
4843 } else {
4844 while (!consumeIf('E')) {
4845 Node *E = getDerived().parseTemplateArg();
4846 if (E == nullptr)
4847 return E;
4848 Names.push_back(E);
4849 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004850 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004851 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4852 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004853 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004854
4855 // Only unresolved names remain.
4856 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004857}
4858
4859// <call-offset> ::= h <nv-offset> _
4860// ::= v <v-offset> _
4861//
4862// <nv-offset> ::= <offset number>
4863// # non-virtual base override
4864//
4865// <v-offset> ::= <offset number> _ <virtual offset number>
4866// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004867template <typename Alloc, typename Derived>
4868bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004869 // Just scan through the call offset, we never add this information into the
4870 // output.
4871 if (consumeIf('h'))
4872 return parseNumber(true).empty() || !consumeIf('_');
4873 if (consumeIf('v'))
4874 return parseNumber(true).empty() || !consumeIf('_') ||
4875 parseNumber(true).empty() || !consumeIf('_');
4876 return true;
4877}
4878
4879// <special-name> ::= TV <type> # virtual table
4880// ::= TT <type> # VTT structure (construction vtable index)
4881// ::= TI <type> # typeinfo structure
4882// ::= TS <type> # typeinfo name (null-terminated byte string)
4883// ::= Tc <call-offset> <call-offset> <base encoding>
4884// # base is the nominal target function of thunk
4885// # first call-offset is 'this' adjustment
4886// # second call-offset is result adjustment
4887// ::= T <call-offset> <base encoding>
4888// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004889// # Guard variable for one-time initialization
4890// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004891// # No <type>
4892// ::= TW <object name> # Thread-local wrapper
4893// ::= TH <object name> # Thread-local initialization
4894// ::= GR <object name> _ # First temporary
4895// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004896// # construction vtable for second-in-first
4897// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004898// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004899// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004900template <typename Derived, typename Alloc>
4901Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004902 switch (look()) {
4903 case 'T':
4904 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004905 // TA <template-arg> # template parameter object
4906 //
4907 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4908 case 'A': {
4909 First += 2;
4910 Node *Arg = getDerived().parseTemplateArg();
4911 if (Arg == nullptr)
4912 return nullptr;
4913 return make<SpecialName>("template parameter object for ", Arg);
4914 }
Richard Smithc20d1442018-08-20 20:14:49 +00004915 // TV <type> # virtual table
4916 case 'V': {
4917 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004918 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004919 if (Ty == nullptr)
4920 return nullptr;
4921 return make<SpecialName>("vtable for ", Ty);
4922 }
4923 // TT <type> # VTT structure (construction vtable index)
4924 case 'T': {
4925 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004926 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004927 if (Ty == nullptr)
4928 return nullptr;
4929 return make<SpecialName>("VTT for ", Ty);
4930 }
4931 // TI <type> # typeinfo structure
4932 case 'I': {
4933 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004934 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004935 if (Ty == nullptr)
4936 return nullptr;
4937 return make<SpecialName>("typeinfo for ", Ty);
4938 }
4939 // TS <type> # typeinfo name (null-terminated byte string)
4940 case 'S': {
4941 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004942 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004943 if (Ty == nullptr)
4944 return nullptr;
4945 return make<SpecialName>("typeinfo name for ", Ty);
4946 }
4947 // Tc <call-offset> <call-offset> <base encoding>
4948 case 'c': {
4949 First += 2;
4950 if (parseCallOffset() || parseCallOffset())
4951 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004952 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004953 if (Encoding == nullptr)
4954 return nullptr;
4955 return make<SpecialName>("covariant return thunk to ", Encoding);
4956 }
4957 // extension ::= TC <first type> <number> _ <second type>
4958 // # construction vtable for second-in-first
4959 case 'C': {
4960 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004961 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004962 if (FirstType == nullptr)
4963 return nullptr;
4964 if (parseNumber(true).empty() || !consumeIf('_'))
4965 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004966 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004967 if (SecondType == nullptr)
4968 return nullptr;
4969 return make<CtorVtableSpecialName>(SecondType, FirstType);
4970 }
4971 // TW <object name> # Thread-local wrapper
4972 case 'W': {
4973 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004974 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004975 if (Name == nullptr)
4976 return nullptr;
4977 return make<SpecialName>("thread-local wrapper routine for ", Name);
4978 }
4979 // TH <object name> # Thread-local initialization
4980 case 'H': {
4981 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004982 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004983 if (Name == nullptr)
4984 return nullptr;
4985 return make<SpecialName>("thread-local initialization routine for ", Name);
4986 }
4987 // T <call-offset> <base encoding>
4988 default: {
4989 ++First;
4990 bool IsVirt = look() == 'v';
4991 if (parseCallOffset())
4992 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004993 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004994 if (BaseEncoding == nullptr)
4995 return nullptr;
4996 if (IsVirt)
4997 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4998 else
4999 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
5000 }
5001 }
5002 case 'G':
5003 switch (look(1)) {
5004 // GV <object name> # Guard variable for one-time initialization
5005 case 'V': {
5006 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005007 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005008 if (Name == nullptr)
5009 return nullptr;
5010 return make<SpecialName>("guard variable for ", Name);
5011 }
5012 // GR <object name> # reference temporary for object
5013 // GR <object name> _ # First temporary
5014 // GR <object name> <seq-id> _ # Subsequent temporaries
5015 case 'R': {
5016 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005017 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00005018 if (Name == nullptr)
5019 return nullptr;
5020 size_t Count;
5021 bool ParsedSeqId = !parseSeqId(&Count);
5022 if (!consumeIf('_') && ParsedSeqId)
5023 return nullptr;
5024 return make<SpecialName>("reference temporary for ", Name);
5025 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08005026 // GI <module-name> v
5027 case 'I': {
5028 First += 2;
5029 ModuleName *Module = nullptr;
5030 if (getDerived().parseModuleNameOpt(Module))
5031 return nullptr;
5032 if (Module == nullptr)
5033 return nullptr;
5034 return make<SpecialName>("initializer for module ", Module);
5035 }
Richard Smithc20d1442018-08-20 20:14:49 +00005036 }
5037 }
5038 return nullptr;
5039}
5040
5041// <encoding> ::= <function name> <bare-function-type>
5042// ::= <data name>
5043// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005044template <typename Derived, typename Alloc>
5045Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005046 // The template parameters of an encoding are unrelated to those of the
5047 // enclosing context.
5048 class SaveTemplateParams {
5049 AbstractManglingParser *Parser;
5050 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005051 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005052
5053 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005054 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005055 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005056 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005057 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005058 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005059 }
5060 ~SaveTemplateParams() {
5061 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005062 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005063 }
5064 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005065
Richard Smithc20d1442018-08-20 20:14:49 +00005066 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005067 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005068
5069 auto IsEndOfEncoding = [&] {
5070 // The set of chars that can potentially follow an <encoding> (none of which
5071 // can start a <type>). Enumerating these allows us to avoid speculative
5072 // parsing.
5073 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5074 };
5075
5076 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005077 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005078 if (Name == nullptr)
5079 return nullptr;
5080
5081 if (resolveForwardTemplateRefs(NameInfo))
5082 return nullptr;
5083
5084 if (IsEndOfEncoding())
5085 return Name;
5086
5087 Node *Attrs = nullptr;
5088 if (consumeIf("Ua9enable_ifI")) {
5089 size_t BeforeArgs = Names.size();
5090 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005091 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005092 if (Arg == nullptr)
5093 return nullptr;
5094 Names.push_back(Arg);
5095 }
5096 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005097 if (!Attrs)
5098 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005099 }
5100
5101 Node *ReturnType = nullptr;
5102 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005103 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005104 if (ReturnType == nullptr)
5105 return nullptr;
5106 }
5107
5108 if (consumeIf('v'))
5109 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5110 Attrs, NameInfo.CVQualifiers,
5111 NameInfo.ReferenceQualifier);
5112
5113 size_t ParamsBegin = Names.size();
5114 do {
Pavel Labathba825192018-10-16 14:29:14 +00005115 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005116 if (Ty == nullptr)
5117 return nullptr;
5118 Names.push_back(Ty);
5119 } while (!IsEndOfEncoding());
5120
5121 return make<FunctionEncoding>(ReturnType, Name,
5122 popTrailingNodeArray(ParamsBegin),
5123 Attrs, NameInfo.CVQualifiers,
5124 NameInfo.ReferenceQualifier);
5125}
5126
5127template <class Float>
5128struct FloatData;
5129
5130template <>
5131struct FloatData<float>
5132{
5133 static const size_t mangled_size = 8;
5134 static const size_t max_demangled_size = 24;
5135 static constexpr const char* spec = "%af";
5136};
5137
5138template <>
5139struct FloatData<double>
5140{
5141 static const size_t mangled_size = 16;
5142 static const size_t max_demangled_size = 32;
5143 static constexpr const char* spec = "%a";
5144};
5145
5146template <>
5147struct FloatData<long double>
5148{
5149#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5150 defined(__wasm__)
5151 static const size_t mangled_size = 32;
5152#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5153 static const size_t mangled_size = 16;
5154#else
5155 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5156#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005157 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5158 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5159 // Negatives are one character longer than positives.
5160 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5161 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5162 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005163 static constexpr const char *spec = "%LaL";
5164};
5165
Pavel Labathba825192018-10-16 14:29:14 +00005166template <typename Alloc, typename Derived>
5167template <class Float>
5168Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005169 const size_t N = FloatData<Float>::mangled_size;
5170 if (numLeft() <= N)
5171 return nullptr;
5172 StringView Data(First, First + N);
5173 for (char C : Data)
5174 if (!std::isxdigit(C))
5175 return nullptr;
5176 First += N;
5177 if (!consumeIf('E'))
5178 return nullptr;
5179 return make<FloatLiteralImpl<Float>>(Data);
5180}
5181
5182// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005183template <typename Alloc, typename Derived>
5184bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005185 if (!(look() >= '0' && look() <= '9') &&
5186 !(look() >= 'A' && look() <= 'Z'))
5187 return true;
5188
5189 size_t Id = 0;
5190 while (true) {
5191 if (look() >= '0' && look() <= '9') {
5192 Id *= 36;
5193 Id += static_cast<size_t>(look() - '0');
5194 } else if (look() >= 'A' && look() <= 'Z') {
5195 Id *= 36;
5196 Id += static_cast<size_t>(look() - 'A') + 10;
5197 } else {
5198 *Out = Id;
5199 return false;
5200 }
5201 ++First;
5202 }
5203}
5204
5205// <substitution> ::= S <seq-id> _
5206// ::= S_
5207// <substitution> ::= Sa # ::std::allocator
5208// <substitution> ::= Sb # ::std::basic_string
5209// <substitution> ::= Ss # ::std::basic_string < char,
5210// ::std::char_traits<char>,
5211// ::std::allocator<char> >
5212// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5213// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5214// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005215// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005216template <typename Derived, typename Alloc>
5217Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005218 if (!consumeIf('S'))
5219 return nullptr;
5220
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005221 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005222 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005223 switch (look()) {
5224 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005225 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005226 break;
5227 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005228 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005229 break;
5230 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005231 Kind = SpecialSubKind::iostream;
5232 break;
5233 case 'i':
5234 Kind = SpecialSubKind::istream;
5235 break;
5236 case 'o':
5237 Kind = SpecialSubKind::ostream;
5238 break;
5239 case 's':
5240 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005241 break;
5242 default:
5243 return nullptr;
5244 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005245 ++First;
5246 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005247 if (!SpecialSub)
5248 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005249
Richard Smithc20d1442018-08-20 20:14:49 +00005250 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5251 // has ABI tags, the tags are appended to the substitution; the result is a
5252 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005253 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005254 if (WithTags != SpecialSub) {
5255 Subs.push_back(WithTags);
5256 SpecialSub = WithTags;
5257 }
5258 return SpecialSub;
5259 }
5260
5261 // ::= S_
5262 if (consumeIf('_')) {
5263 if (Subs.empty())
5264 return nullptr;
5265 return Subs[0];
5266 }
5267
5268 // ::= S <seq-id> _
5269 size_t Index = 0;
5270 if (parseSeqId(&Index))
5271 return nullptr;
5272 ++Index;
5273 if (!consumeIf('_') || Index >= Subs.size())
5274 return nullptr;
5275 return Subs[Index];
5276}
5277
5278// <template-param> ::= T_ # first template parameter
5279// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005280// ::= TL <level-1> __
5281// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005282template <typename Derived, typename Alloc>
5283Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005284 if (!consumeIf('T'))
5285 return nullptr;
5286
Richard Smithdf1c14c2019-09-06 23:53:21 +00005287 size_t Level = 0;
5288 if (consumeIf('L')) {
5289 if (parsePositiveInteger(&Level))
5290 return nullptr;
5291 ++Level;
5292 if (!consumeIf('_'))
5293 return nullptr;
5294 }
5295
Richard Smithc20d1442018-08-20 20:14:49 +00005296 size_t Index = 0;
5297 if (!consumeIf('_')) {
5298 if (parsePositiveInteger(&Index))
5299 return nullptr;
5300 ++Index;
5301 if (!consumeIf('_'))
5302 return nullptr;
5303 }
5304
Richard Smithc20d1442018-08-20 20:14:49 +00005305 // If we're in a context where this <template-param> refers to a
5306 // <template-arg> further ahead in the mangled name (currently just conversion
5307 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005308 // This can only happen at the outermost level.
5309 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005310 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5311 if (!ForwardRef)
5312 return nullptr;
5313 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5314 ForwardTemplateRefs.push_back(
5315 static_cast<ForwardTemplateReference *>(ForwardRef));
5316 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005317 }
5318
Richard Smithdf1c14c2019-09-06 23:53:21 +00005319 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5320 Index >= TemplateParams[Level]->size()) {
5321 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5322 // list are mangled as the corresponding artificial template type parameter.
5323 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5324 // This will be popped by the ScopedTemplateParamList in
5325 // parseUnnamedTypeName.
5326 if (Level == TemplateParams.size())
5327 TemplateParams.push_back(nullptr);
5328 return make<NameType>("auto");
5329 }
5330
Richard Smithc20d1442018-08-20 20:14:49 +00005331 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005332 }
5333
5334 return (*TemplateParams[Level])[Index];
5335}
5336
5337// <template-param-decl> ::= Ty # type parameter
5338// ::= Tn <type> # non-type parameter
5339// ::= Tt <template-param-decl>* E # template parameter
5340// ::= Tp <template-param-decl> # parameter pack
5341template <typename Derived, typename Alloc>
5342Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5343 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5344 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5345 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5346 if (N) TemplateParams.back()->push_back(N);
5347 return N;
5348 };
5349
5350 if (consumeIf("Ty")) {
5351 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5352 if (!Name)
5353 return nullptr;
5354 return make<TypeTemplateParamDecl>(Name);
5355 }
5356
5357 if (consumeIf("Tn")) {
5358 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5359 if (!Name)
5360 return nullptr;
5361 Node *Type = parseType();
5362 if (!Type)
5363 return nullptr;
5364 return make<NonTypeTemplateParamDecl>(Name, Type);
5365 }
5366
5367 if (consumeIf("Tt")) {
5368 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5369 if (!Name)
5370 return nullptr;
5371 size_t ParamsBegin = Names.size();
5372 ScopedTemplateParamList TemplateTemplateParamParams(this);
5373 while (!consumeIf("E")) {
5374 Node *P = parseTemplateParamDecl();
5375 if (!P)
5376 return nullptr;
5377 Names.push_back(P);
5378 }
5379 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5380 return make<TemplateTemplateParamDecl>(Name, Params);
5381 }
5382
5383 if (consumeIf("Tp")) {
5384 Node *P = parseTemplateParamDecl();
5385 if (!P)
5386 return nullptr;
5387 return make<TemplateParamPackDecl>(P);
5388 }
5389
5390 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005391}
5392
5393// <template-arg> ::= <type> # type or template
5394// ::= X <expression> E # expression
5395// ::= <expr-primary> # simple expressions
5396// ::= J <template-arg>* E # argument pack
5397// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005398template <typename Derived, typename Alloc>
5399Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005400 switch (look()) {
5401 case 'X': {
5402 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005403 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005404 if (Arg == nullptr || !consumeIf('E'))
5405 return nullptr;
5406 return Arg;
5407 }
5408 case 'J': {
5409 ++First;
5410 size_t ArgsBegin = Names.size();
5411 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005412 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005413 if (Arg == nullptr)
5414 return nullptr;
5415 Names.push_back(Arg);
5416 }
5417 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5418 return make<TemplateArgumentPack>(Args);
5419 }
5420 case 'L': {
5421 // ::= LZ <encoding> E # extension
5422 if (look(1) == 'Z') {
5423 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005424 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005425 if (Arg == nullptr || !consumeIf('E'))
5426 return nullptr;
5427 return Arg;
5428 }
5429 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005430 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005431 }
5432 default:
Pavel Labathba825192018-10-16 14:29:14 +00005433 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005434 }
5435}
5436
5437// <template-args> ::= I <template-arg>* E
5438// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005439template <typename Derived, typename Alloc>
5440Node *
5441AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005442 if (!consumeIf('I'))
5443 return nullptr;
5444
5445 // <template-params> refer to the innermost <template-args>. Clear out any
5446 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005447 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005448 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005449 TemplateParams.push_back(&OuterTemplateParams);
5450 OuterTemplateParams.clear();
5451 }
Richard Smithc20d1442018-08-20 20:14:49 +00005452
5453 size_t ArgsBegin = Names.size();
5454 while (!consumeIf('E')) {
5455 if (TagTemplates) {
5456 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005457 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005458 TemplateParams = std::move(OldParams);
5459 if (Arg == nullptr)
5460 return nullptr;
5461 Names.push_back(Arg);
5462 Node *TableEntry = Arg;
5463 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5464 TableEntry = make<ParameterPack>(
5465 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005466 if (!TableEntry)
5467 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005468 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005469 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005470 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005471 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005472 if (Arg == nullptr)
5473 return nullptr;
5474 Names.push_back(Arg);
5475 }
5476 }
5477 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5478}
5479
5480// <mangled-name> ::= _Z <encoding>
5481// ::= <type>
5482// extension ::= ___Z <encoding> _block_invoke
5483// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5484// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005485template <typename Derived, typename Alloc>
5486Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005487 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005488 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005489 if (Encoding == nullptr)
5490 return nullptr;
5491 if (look() == '.') {
5492 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5493 First = Last;
5494 }
5495 if (numLeft() != 0)
5496 return nullptr;
5497 return Encoding;
5498 }
5499
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005500 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005501 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005502 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5503 return nullptr;
5504 bool RequireNumber = consumeIf('_');
5505 if (parseNumber().empty() && RequireNumber)
5506 return nullptr;
5507 if (look() == '.')
5508 First = Last;
5509 if (numLeft() != 0)
5510 return nullptr;
5511 return make<SpecialName>("invocation function for block in ", Encoding);
5512 }
5513
Pavel Labathba825192018-10-16 14:29:14 +00005514 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005515 if (numLeft() != 0)
5516 return nullptr;
5517 return Ty;
5518}
5519
Pavel Labathba825192018-10-16 14:29:14 +00005520template <typename Alloc>
5521struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5522 using AbstractManglingParser<ManglingParser<Alloc>,
5523 Alloc>::AbstractManglingParser;
5524};
5525
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005526DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005527
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005528#endif // DEMANGLE_ITANIUMDEMANGLE_H