blob: 339982584f5f92c8c82fb51420da86fa6049521c [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>
Nikolas Klauser62855772022-09-05 00:01:15 +020029#include <new>
Richard Smithc20d1442018-08-20 20:14:49 +000030#include <utility>
31
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000032DEMANGLE_NAMESPACE_BEGIN
33
Mikhail Borisov8452f062021-08-17 18:06:53 -040034template <class T, size_t N> class PODSmallVector {
35 static_assert(std::is_pod<T>::value,
36 "T is required to be a plain old data type");
37
38 T *First = nullptr;
39 T *Last = nullptr;
40 T *Cap = nullptr;
41 T Inline[N] = {0};
42
43 bool isInline() const { return First == Inline; }
44
45 void clearInline() {
46 First = Inline;
47 Last = Inline;
48 Cap = Inline + N;
49 }
50
51 void reserve(size_t NewCap) {
52 size_t S = size();
53 if (isInline()) {
54 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
55 if (Tmp == nullptr)
56 std::terminate();
57 std::copy(First, Last, Tmp);
58 First = Tmp;
59 } else {
60 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
61 if (First == nullptr)
62 std::terminate();
63 }
64 Last = First + S;
65 Cap = First + NewCap;
66 }
67
68public:
69 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
70
71 PODSmallVector(const PODSmallVector &) = delete;
72 PODSmallVector &operator=(const PODSmallVector &) = delete;
73
74 PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {
75 if (Other.isInline()) {
76 std::copy(Other.begin(), Other.end(), First);
77 Last = First + Other.size();
78 Other.clear();
79 return;
80 }
81
82 First = Other.First;
83 Last = Other.Last;
84 Cap = Other.Cap;
85 Other.clearInline();
86 }
87
88 PODSmallVector &operator=(PODSmallVector &&Other) {
89 if (Other.isInline()) {
90 if (!isInline()) {
91 std::free(First);
92 clearInline();
93 }
94 std::copy(Other.begin(), Other.end(), First);
95 Last = First + Other.size();
96 Other.clear();
97 return *this;
98 }
99
100 if (isInline()) {
101 First = Other.First;
102 Last = Other.Last;
103 Cap = Other.Cap;
104 Other.clearInline();
105 return *this;
106 }
107
108 std::swap(First, Other.First);
109 std::swap(Last, Other.Last);
110 std::swap(Cap, Other.Cap);
111 Other.clear();
112 return *this;
113 }
114
115 // NOLINTNEXTLINE(readability-identifier-naming)
116 void push_back(const T &Elem) {
117 if (Last == Cap)
118 reserve(size() * 2);
119 *Last++ = Elem;
120 }
121
122 // NOLINTNEXTLINE(readability-identifier-naming)
123 void pop_back() {
124 assert(Last != First && "Popping empty vector!");
125 --Last;
126 }
127
128 void dropBack(size_t Index) {
129 assert(Index <= size() && "dropBack() can't expand!");
130 Last = First + Index;
131 }
132
133 T *begin() { return First; }
134 T *end() { return Last; }
135
136 bool empty() const { return First == Last; }
137 size_t size() const { return static_cast<size_t>(Last - First); }
138 T &back() {
139 assert(Last != First && "Calling back() on empty vector!");
140 return *(Last - 1);
141 }
142 T &operator[](size_t Index) {
143 assert(Index < size() && "Invalid access!");
144 return *(begin() + Index);
145 }
146 void clear() { Last = First; }
147
148 ~PODSmallVector() {
149 if (!isInline())
150 std::free(First);
151 }
152};
153
Richard Smithc20d1442018-08-20 20:14:49 +0000154// Base class of all AST nodes. The AST is built by the parser, then is
155// traversed by the printLeft/Right functions to produce a demangled string.
156class Node {
157public:
158 enum Kind : unsigned char {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -0700159#define NODE(NodeKind) K##NodeKind,
160#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +0000161 };
162
163 /// Three-way bool to track a cached value. Unknown is possible if this node
164 /// has an unexpanded parameter pack below it that may affect this cache.
165 enum class Cache : unsigned char { Yes, No, Unknown, };
166
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800167 /// Operator precedence for expression nodes. Used to determine required
168 /// parens in expression emission.
169 enum class Prec {
170 Primary,
171 Postfix,
172 Unary,
173 Cast,
174 PtrMem,
175 Multiplicative,
176 Additive,
177 Shift,
178 Spaceship,
179 Relational,
180 Equality,
181 And,
182 Xor,
183 Ior,
184 AndIf,
185 OrIf,
186 Conditional,
187 Assign,
188 Comma,
189 Default,
190 };
191
Richard Smithc20d1442018-08-20 20:14:49 +0000192private:
193 Kind K;
194
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800195 Prec Precedence : 6;
196
Richard Smithc20d1442018-08-20 20:14:49 +0000197 // FIXME: Make these protected.
198public:
199 /// Tracks if this node has a component on its right side, in which case we
200 /// need to call printRight.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800201 Cache RHSComponentCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000202
203 /// Track if this node is a (possibly qualified) array type. This can affect
204 /// how we format the output string.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800205 Cache ArrayCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000206
207 /// Track if this node is a (possibly qualified) function type. This can
208 /// affect how we format the output string.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800209 Cache FunctionCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000210
211public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800212 Node(Kind K_, Prec Precedence_ = Prec::Primary,
213 Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,
214 Cache FunctionCache_ = Cache::No)
215 : K(K_), Precedence(Precedence_), RHSComponentCache(RHSComponentCache_),
216 ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {}
217 Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_ = Cache::No,
218 Cache FunctionCache_ = Cache::No)
219 : Node(K_, Prec::Primary, RHSComponentCache_, ArrayCache_,
220 FunctionCache_) {}
Richard Smithc20d1442018-08-20 20:14:49 +0000221
222 /// Visit the most-derived object corresponding to this object.
223 template<typename Fn> void visit(Fn F) const;
224
225 // The following function is provided by all derived classes:
226 //
227 // Call F with arguments that, when passed to the constructor of this node,
228 // would construct an equivalent node.
229 //template<typename Fn> void match(Fn F) const;
230
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700231 bool hasRHSComponent(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000232 if (RHSComponentCache != Cache::Unknown)
233 return RHSComponentCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700234 return hasRHSComponentSlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000235 }
236
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700237 bool hasArray(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000238 if (ArrayCache != Cache::Unknown)
239 return ArrayCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700240 return hasArraySlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000241 }
242
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700243 bool hasFunction(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000244 if (FunctionCache != Cache::Unknown)
245 return FunctionCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700246 return hasFunctionSlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000247 }
248
249 Kind getKind() const { return K; }
250
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800251 Prec getPrecedence() const { return Precedence; }
252
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700253 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
254 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
255 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
Richard Smithc20d1442018-08-20 20:14:49 +0000256
257 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
258 // get at a node that actually represents some concrete syntax.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700259 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }
Richard Smithc20d1442018-08-20 20:14:49 +0000260
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800261 // Print this node as an expression operand, surrounding it in parentheses if
262 // its precedence is [Strictly] weaker than P.
263 void printAsOperand(OutputBuffer &OB, Prec P = Prec::Default,
264 bool StrictlyWorse = false) const {
265 bool Paren =
266 unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse);
267 if (Paren)
268 OB.printOpen();
269 print(OB);
270 if (Paren)
271 OB.printClose();
272 }
273
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700274 void print(OutputBuffer &OB) const {
275 printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000276 if (RHSComponentCache != Cache::No)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700277 printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000278 }
279
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -0800280 // Print the "left" side of this Node into OutputBuffer.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700281 virtual void printLeft(OutputBuffer &) const = 0;
Richard Smithc20d1442018-08-20 20:14:49 +0000282
283 // Print the "right". This distinction is necessary to represent C++ types
284 // that appear on the RHS of their subtype, such as arrays or functions.
285 // Since most types don't have such a component, provide a default
286 // implementation.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700287 virtual void printRight(OutputBuffer &) const {}
Richard Smithc20d1442018-08-20 20:14:49 +0000288
289 virtual StringView getBaseName() const { return StringView(); }
290
291 // Silence compiler warnings, this dtor will never be called.
292 virtual ~Node() = default;
293
294#ifndef NDEBUG
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000295 DEMANGLE_DUMP_METHOD void dump() const;
Richard Smithc20d1442018-08-20 20:14:49 +0000296#endif
297};
298
299class NodeArray {
300 Node **Elements;
301 size_t NumElements;
302
303public:
304 NodeArray() : Elements(nullptr), NumElements(0) {}
305 NodeArray(Node **Elements_, size_t NumElements_)
306 : Elements(Elements_), NumElements(NumElements_) {}
307
308 bool empty() const { return NumElements == 0; }
309 size_t size() const { return NumElements; }
310
311 Node **begin() const { return Elements; }
312 Node **end() const { return Elements + NumElements; }
313
314 Node *operator[](size_t Idx) const { return Elements[Idx]; }
315
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700316 void printWithComma(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000317 bool FirstElement = true;
318 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700319 size_t BeforeComma = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +0000320 if (!FirstElement)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700321 OB += ", ";
322 size_t AfterComma = OB.getCurrentPosition();
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800323 Elements[Idx]->printAsOperand(OB, Node::Prec::Comma);
Richard Smithc20d1442018-08-20 20:14:49 +0000324
325 // Elements[Idx] is an empty parameter pack expansion, we should erase the
326 // comma we just printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700327 if (AfterComma == OB.getCurrentPosition()) {
328 OB.setCurrentPosition(BeforeComma);
Richard Smithc20d1442018-08-20 20:14:49 +0000329 continue;
330 }
331
332 FirstElement = false;
333 }
334 }
335};
336
337struct NodeArrayNode : Node {
338 NodeArray Array;
339 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
340
341 template<typename Fn> void match(Fn F) const { F(Array); }
342
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700343 void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000344};
345
346class DotSuffix final : public Node {
347 const Node *Prefix;
348 const StringView Suffix;
349
350public:
351 DotSuffix(const Node *Prefix_, StringView Suffix_)
352 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
353
354 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
355
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700356 void printLeft(OutputBuffer &OB) const override {
357 Prefix->print(OB);
358 OB += " (";
359 OB += Suffix;
360 OB += ")";
Richard Smithc20d1442018-08-20 20:14:49 +0000361 }
362};
363
364class VendorExtQualType final : public Node {
365 const Node *Ty;
366 StringView Ext;
Alex Orlovf50df922021-03-24 10:21:32 +0400367 const Node *TA;
Richard Smithc20d1442018-08-20 20:14:49 +0000368
369public:
Alex Orlovf50df922021-03-24 10:21:32 +0400370 VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)
371 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
Richard Smithc20d1442018-08-20 20:14:49 +0000372
Nathan Sidwelleb9fece2022-10-07 07:03:32 -0700373 const Node *getTy() const { return Ty; }
374 StringView getExt() const { return Ext; }
375 const Node *getTA() const { return TA; }
376
Alex Orlovf50df922021-03-24 10:21:32 +0400377 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
Richard Smithc20d1442018-08-20 20:14:49 +0000378
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700379 void printLeft(OutputBuffer &OB) const override {
380 Ty->print(OB);
381 OB += " ";
382 OB += Ext;
Alex Orlovf50df922021-03-24 10:21:32 +0400383 if (TA != nullptr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700384 TA->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000385 }
386};
387
388enum FunctionRefQual : unsigned char {
389 FrefQualNone,
390 FrefQualLValue,
391 FrefQualRValue,
392};
393
394enum Qualifiers {
395 QualNone = 0,
396 QualConst = 0x1,
397 QualVolatile = 0x2,
398 QualRestrict = 0x4,
399};
400
401inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
402 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
403}
404
Richard Smithdf1c14c2019-09-06 23:53:21 +0000405class QualType final : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +0000406protected:
407 const Qualifiers Quals;
408 const Node *Child;
409
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700410 void printQuals(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000411 if (Quals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700412 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000413 if (Quals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700414 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000415 if (Quals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700416 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000417 }
418
419public:
420 QualType(const Node *Child_, Qualifiers Quals_)
421 : Node(KQualType, Child_->RHSComponentCache,
422 Child_->ArrayCache, Child_->FunctionCache),
423 Quals(Quals_), Child(Child_) {}
424
Nathan Sidwelleb9fece2022-10-07 07:03:32 -0700425 Qualifiers getQuals() const { return Quals; }
426 const Node *getChild() const { return Child; }
427
Richard Smithc20d1442018-08-20 20:14:49 +0000428 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
429
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700430 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
431 return Child->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000432 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700433 bool hasArraySlow(OutputBuffer &OB) const override {
434 return Child->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000435 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700436 bool hasFunctionSlow(OutputBuffer &OB) const override {
437 return Child->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000438 }
439
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700440 void printLeft(OutputBuffer &OB) const override {
441 Child->printLeft(OB);
442 printQuals(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000443 }
444
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700445 void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000446};
447
448class ConversionOperatorType final : public Node {
449 const Node *Ty;
450
451public:
452 ConversionOperatorType(const Node *Ty_)
453 : Node(KConversionOperatorType), Ty(Ty_) {}
454
455 template<typename Fn> void match(Fn F) const { F(Ty); }
456
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700457 void printLeft(OutputBuffer &OB) const override {
458 OB += "operator ";
459 Ty->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000460 }
461};
462
463class PostfixQualifiedType final : public Node {
464 const Node *Ty;
465 const StringView Postfix;
466
467public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -0700468 PostfixQualifiedType(const Node *Ty_, StringView Postfix_)
Richard Smithc20d1442018-08-20 20:14:49 +0000469 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
470
471 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
472
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700473 void printLeft(OutputBuffer &OB) const override {
474 Ty->printLeft(OB);
475 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +0000476 }
477};
478
479class NameType final : public Node {
480 const StringView Name;
481
482public:
483 NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
484
485 template<typename Fn> void match(Fn F) const { F(Name); }
486
487 StringView getName() const { return Name; }
488 StringView getBaseName() const override { return Name; }
489
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700490 void printLeft(OutputBuffer &OB) const override { OB += Name; }
Richard Smithc20d1442018-08-20 20:14:49 +0000491};
492
Senran Zhange025ba52022-03-27 00:04:23 +0800493class BitIntType final : public Node {
494 const Node *Size;
495 bool Signed;
496
497public:
498 BitIntType(const Node *Size_, bool Signed_)
499 : Node(KBitIntType), Size(Size_), Signed(Signed_) {}
500
501 template <typename Fn> void match(Fn F) const { F(Size, Signed); }
502
503 void printLeft(OutputBuffer &OB) const override {
504 if (!Signed)
505 OB += "unsigned ";
506 OB += "_BitInt";
507 OB.printOpen();
508 Size->printAsOperand(OB);
509 OB.printClose();
510 }
511};
512
Richard Smithc20d1442018-08-20 20:14:49 +0000513class ElaboratedTypeSpefType : public Node {
514 StringView Kind;
515 Node *Child;
516public:
517 ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
518 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
519
520 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
521
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700522 void printLeft(OutputBuffer &OB) const override {
523 OB += Kind;
524 OB += ' ';
525 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000526 }
527};
528
529struct AbiTagAttr : Node {
530 Node *Base;
531 StringView Tag;
532
533 AbiTagAttr(Node* Base_, StringView Tag_)
534 : Node(KAbiTagAttr, Base_->RHSComponentCache,
535 Base_->ArrayCache, Base_->FunctionCache),
536 Base(Base_), Tag(Tag_) {}
537
538 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
539
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700540 void printLeft(OutputBuffer &OB) const override {
541 Base->printLeft(OB);
542 OB += "[abi:";
543 OB += Tag;
544 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +0000545 }
546};
547
548class EnableIfAttr : public Node {
549 NodeArray Conditions;
550public:
551 EnableIfAttr(NodeArray Conditions_)
552 : Node(KEnableIfAttr), Conditions(Conditions_) {}
553
554 template<typename Fn> void match(Fn F) const { F(Conditions); }
555
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700556 void printLeft(OutputBuffer &OB) const override {
557 OB += " [enable_if:";
558 Conditions.printWithComma(OB);
559 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +0000560 }
561};
562
563class ObjCProtoName : public Node {
564 const Node *Ty;
565 StringView Protocol;
566
567 friend class PointerType;
568
569public:
570 ObjCProtoName(const Node *Ty_, StringView Protocol_)
571 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
572
573 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
574
575 bool isObjCObject() const {
576 return Ty->getKind() == KNameType &&
577 static_cast<const NameType *>(Ty)->getName() == "objc_object";
578 }
579
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700580 void printLeft(OutputBuffer &OB) const override {
581 Ty->print(OB);
582 OB += "<";
583 OB += Protocol;
584 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +0000585 }
586};
587
588class PointerType final : public Node {
589 const Node *Pointee;
590
591public:
592 PointerType(const Node *Pointee_)
593 : Node(KPointerType, Pointee_->RHSComponentCache),
594 Pointee(Pointee_) {}
595
Nathan Sidwelleb9fece2022-10-07 07:03:32 -0700596 const Node *getPointee() const { return Pointee; }
597
Richard Smithc20d1442018-08-20 20:14:49 +0000598 template<typename Fn> void match(Fn F) const { F(Pointee); }
599
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700600 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
601 return Pointee->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000602 }
603
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700604 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000605 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
606 if (Pointee->getKind() != KObjCProtoName ||
607 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700608 Pointee->printLeft(OB);
609 if (Pointee->hasArray(OB))
610 OB += " ";
611 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
612 OB += "(";
613 OB += "*";
Richard Smithc20d1442018-08-20 20:14:49 +0000614 } else {
615 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700616 OB += "id<";
617 OB += objcProto->Protocol;
618 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +0000619 }
620 }
621
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700622 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000623 if (Pointee->getKind() != KObjCProtoName ||
624 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700625 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
626 OB += ")";
627 Pointee->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000628 }
629 }
630};
631
632enum class ReferenceKind {
633 LValue,
634 RValue,
635};
636
637// Represents either a LValue or an RValue reference type.
638class ReferenceType : public Node {
639 const Node *Pointee;
640 ReferenceKind RK;
641
642 mutable bool Printing = false;
643
644 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
645 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
646 // other combination collapses to a lvalue ref.
Mikhail Borisov05f77222021-08-17 18:10:57 -0400647 //
648 // A combination of a TemplateForwardReference and a back-ref Substitution
649 // from an ill-formed string may have created a cycle; use cycle detection to
650 // avoid looping forever.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700651 std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000652 auto SoFar = std::make_pair(RK, Pointee);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400653 // Track the chain of nodes for the Floyd's 'tortoise and hare'
654 // cycle-detection algorithm, since getSyntaxNode(S) is impure
655 PODSmallVector<const Node *, 8> Prev;
Richard Smithc20d1442018-08-20 20:14:49 +0000656 for (;;) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700657 const Node *SN = SoFar.second->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000658 if (SN->getKind() != KReferenceType)
659 break;
660 auto *RT = static_cast<const ReferenceType *>(SN);
661 SoFar.second = RT->Pointee;
662 SoFar.first = std::min(SoFar.first, RT->RK);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400663
664 // The middle of Prev is the 'slow' pointer moving at half speed
665 Prev.push_back(SoFar.second);
666 if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {
667 // Cycle detected
668 SoFar.second = nullptr;
669 break;
670 }
Richard Smithc20d1442018-08-20 20:14:49 +0000671 }
672 return SoFar;
673 }
674
675public:
676 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
677 : Node(KReferenceType, Pointee_->RHSComponentCache),
678 Pointee(Pointee_), RK(RK_) {}
679
680 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
681
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700682 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
683 return Pointee->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000684 }
685
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700686 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000687 if (Printing)
688 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -0800689 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700690 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400691 if (!Collapsed.second)
692 return;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700693 Collapsed.second->printLeft(OB);
694 if (Collapsed.second->hasArray(OB))
695 OB += " ";
696 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
697 OB += "(";
Richard Smithc20d1442018-08-20 20:14:49 +0000698
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700699 OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
Richard Smithc20d1442018-08-20 20:14:49 +0000700 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700701 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000702 if (Printing)
703 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -0800704 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700705 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400706 if (!Collapsed.second)
707 return;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700708 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
709 OB += ")";
710 Collapsed.second->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000711 }
712};
713
714class PointerToMemberType final : public Node {
715 const Node *ClassType;
716 const Node *MemberType;
717
718public:
719 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
720 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
721 ClassType(ClassType_), MemberType(MemberType_) {}
722
723 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
724
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700725 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
726 return MemberType->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000727 }
728
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700729 void printLeft(OutputBuffer &OB) const override {
730 MemberType->printLeft(OB);
731 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
732 OB += "(";
Richard Smithc20d1442018-08-20 20:14:49 +0000733 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700734 OB += " ";
735 ClassType->print(OB);
736 OB += "::*";
Richard Smithc20d1442018-08-20 20:14:49 +0000737 }
738
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700739 void printRight(OutputBuffer &OB) const override {
740 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
741 OB += ")";
742 MemberType->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000743 }
744};
745
Richard Smithc20d1442018-08-20 20:14:49 +0000746class ArrayType final : public Node {
747 const Node *Base;
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800748 Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000749
750public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800751 ArrayType(const Node *Base_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000752 : Node(KArrayType,
753 /*RHSComponentCache=*/Cache::Yes,
754 /*ArrayCache=*/Cache::Yes),
755 Base(Base_), Dimension(Dimension_) {}
756
757 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
758
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700759 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
760 bool hasArraySlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000761
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700762 void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000763
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700764 void printRight(OutputBuffer &OB) const override {
765 if (OB.back() != ']')
766 OB += " ";
767 OB += "[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800768 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700769 Dimension->print(OB);
770 OB += "]";
771 Base->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000772 }
773};
774
775class FunctionType final : public Node {
776 const Node *Ret;
777 NodeArray Params;
778 Qualifiers CVQuals;
779 FunctionRefQual RefQual;
780 const Node *ExceptionSpec;
781
782public:
783 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
784 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
785 : Node(KFunctionType,
786 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
787 /*FunctionCache=*/Cache::Yes),
788 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
789 ExceptionSpec(ExceptionSpec_) {}
790
791 template<typename Fn> void match(Fn F) const {
792 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
793 }
794
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700795 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
796 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000797
798 // Handle C++'s ... quirky decl grammar by using the left & right
799 // distinction. Consider:
800 // int (*f(float))(char) {}
801 // f is a function that takes a float and returns a pointer to a function
802 // that takes a char and returns an int. If we're trying to print f, start
803 // by printing out the return types's left, then print our parameters, then
804 // finally print right of the return type.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700805 void printLeft(OutputBuffer &OB) const override {
806 Ret->printLeft(OB);
807 OB += " ";
Richard Smithc20d1442018-08-20 20:14:49 +0000808 }
809
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700810 void printRight(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800811 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700812 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800813 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700814 Ret->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000815
816 if (CVQuals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700817 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000818 if (CVQuals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700819 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000820 if (CVQuals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700821 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000822
823 if (RefQual == FrefQualLValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700824 OB += " &";
Richard Smithc20d1442018-08-20 20:14:49 +0000825 else if (RefQual == FrefQualRValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700826 OB += " &&";
Richard Smithc20d1442018-08-20 20:14:49 +0000827
828 if (ExceptionSpec != nullptr) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700829 OB += ' ';
830 ExceptionSpec->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000831 }
832 }
833};
834
835class NoexceptSpec : public Node {
836 const Node *E;
837public:
838 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
839
840 template<typename Fn> void match(Fn F) const { F(E); }
841
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700842 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800843 OB += "noexcept";
844 OB.printOpen();
845 E->printAsOperand(OB);
846 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000847 }
848};
849
850class DynamicExceptionSpec : public Node {
851 NodeArray Types;
852public:
853 DynamicExceptionSpec(NodeArray Types_)
854 : Node(KDynamicExceptionSpec), Types(Types_) {}
855
856 template<typename Fn> void match(Fn F) const { F(Types); }
857
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700858 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800859 OB += "throw";
860 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700861 Types.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800862 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000863 }
864};
865
866class FunctionEncoding final : public Node {
867 const Node *Ret;
868 const Node *Name;
869 NodeArray Params;
870 const Node *Attrs;
871 Qualifiers CVQuals;
872 FunctionRefQual RefQual;
873
874public:
875 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
876 const Node *Attrs_, Qualifiers CVQuals_,
877 FunctionRefQual RefQual_)
878 : Node(KFunctionEncoding,
879 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
880 /*FunctionCache=*/Cache::Yes),
881 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
882 CVQuals(CVQuals_), RefQual(RefQual_) {}
883
884 template<typename Fn> void match(Fn F) const {
885 F(Ret, Name, Params, Attrs, CVQuals, RefQual);
886 }
887
888 Qualifiers getCVQuals() const { return CVQuals; }
889 FunctionRefQual getRefQual() const { return RefQual; }
890 NodeArray getParams() const { return Params; }
891 const Node *getReturnType() const { return Ret; }
892
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700893 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
894 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000895
896 const Node *getName() const { return Name; }
897
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700898 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000899 if (Ret) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700900 Ret->printLeft(OB);
901 if (!Ret->hasRHSComponent(OB))
902 OB += " ";
Richard Smithc20d1442018-08-20 20:14:49 +0000903 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700904 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000905 }
906
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700907 void printRight(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800908 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700909 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800910 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000911 if (Ret)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700912 Ret->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000913
914 if (CVQuals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700915 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000916 if (CVQuals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700917 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000918 if (CVQuals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700919 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000920
921 if (RefQual == FrefQualLValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700922 OB += " &";
Richard Smithc20d1442018-08-20 20:14:49 +0000923 else if (RefQual == FrefQualRValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700924 OB += " &&";
Richard Smithc20d1442018-08-20 20:14:49 +0000925
926 if (Attrs != nullptr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700927 Attrs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000928 }
929};
930
931class LiteralOperator : public Node {
932 const Node *OpName;
933
934public:
935 LiteralOperator(const Node *OpName_)
936 : Node(KLiteralOperator), OpName(OpName_) {}
937
938 template<typename Fn> void match(Fn F) const { F(OpName); }
939
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700940 void printLeft(OutputBuffer &OB) const override {
941 OB += "operator\"\" ";
942 OpName->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000943 }
944};
945
946class SpecialName final : public Node {
947 const StringView Special;
948 const Node *Child;
949
950public:
951 SpecialName(StringView Special_, const Node *Child_)
952 : Node(KSpecialName), Special(Special_), Child(Child_) {}
953
954 template<typename Fn> void match(Fn F) const { F(Special, Child); }
955
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700956 void printLeft(OutputBuffer &OB) const override {
957 OB += Special;
958 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000959 }
960};
961
962class CtorVtableSpecialName final : public Node {
963 const Node *FirstType;
964 const Node *SecondType;
965
966public:
967 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
968 : Node(KCtorVtableSpecialName),
969 FirstType(FirstType_), SecondType(SecondType_) {}
970
971 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
972
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700973 void printLeft(OutputBuffer &OB) const override {
974 OB += "construction vtable for ";
975 FirstType->print(OB);
976 OB += "-in-";
977 SecondType->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000978 }
979};
980
981struct NestedName : Node {
982 Node *Qual;
983 Node *Name;
984
985 NestedName(Node *Qual_, Node *Name_)
986 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
987
988 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
989
990 StringView getBaseName() const override { return Name->getBaseName(); }
991
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700992 void printLeft(OutputBuffer &OB) const override {
993 Qual->print(OB);
994 OB += "::";
995 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000996 }
997};
998
Nathan Sidwelledde7bb2022-01-26 07:22:04 -0800999struct ModuleName : Node {
1000 ModuleName *Parent;
1001 Node *Name;
1002 bool IsPartition;
1003
1004 ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false)
1005 : Node(KModuleName), Parent(Parent_), Name(Name_),
1006 IsPartition(IsPartition_) {}
1007
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001008 template <typename Fn> void match(Fn F) const {
1009 F(Parent, Name, IsPartition);
1010 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08001011
1012 void printLeft(OutputBuffer &OB) const override {
1013 if (Parent)
1014 Parent->print(OB);
1015 if (Parent || IsPartition)
1016 OB += IsPartition ? ':' : '.';
1017 Name->print(OB);
1018 }
1019};
1020
1021struct ModuleEntity : Node {
1022 ModuleName *Module;
1023 Node *Name;
1024
1025 ModuleEntity(ModuleName *Module_, Node *Name_)
1026 : Node(KModuleEntity), Module(Module_), Name(Name_) {}
1027
1028 template <typename Fn> void match(Fn F) const { F(Module, Name); }
1029
1030 StringView getBaseName() const override { return Name->getBaseName(); }
1031
1032 void printLeft(OutputBuffer &OB) const override {
1033 Name->print(OB);
1034 OB += '@';
1035 Module->print(OB);
1036 }
1037};
1038
Richard Smithc20d1442018-08-20 20:14:49 +00001039struct LocalName : Node {
1040 Node *Encoding;
1041 Node *Entity;
1042
1043 LocalName(Node *Encoding_, Node *Entity_)
1044 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
1045
1046 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
1047
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001048 void printLeft(OutputBuffer &OB) const override {
1049 Encoding->print(OB);
1050 OB += "::";
1051 Entity->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001052 }
1053};
1054
1055class QualifiedName final : public Node {
1056 // qualifier::name
1057 const Node *Qualifier;
1058 const Node *Name;
1059
1060public:
1061 QualifiedName(const Node *Qualifier_, const Node *Name_)
1062 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
1063
1064 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
1065
1066 StringView getBaseName() const override { return Name->getBaseName(); }
1067
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001068 void printLeft(OutputBuffer &OB) const override {
1069 Qualifier->print(OB);
1070 OB += "::";
1071 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001072 }
1073};
1074
1075class VectorType final : public Node {
1076 const Node *BaseType;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001077 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001078
1079public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001080 VectorType(const Node *BaseType_, const Node *Dimension_)
1081 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001082
Nathan Sidwelleb9fece2022-10-07 07:03:32 -07001083 const Node *getBaseType() const { return BaseType; }
1084 const Node *getDimension() const { return Dimension; }
1085
Richard Smithc20d1442018-08-20 20:14:49 +00001086 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
1087
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001088 void printLeft(OutputBuffer &OB) const override {
1089 BaseType->print(OB);
1090 OB += " vector[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001091 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001092 Dimension->print(OB);
1093 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001094 }
1095};
1096
1097class PixelVectorType final : public Node {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001098 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001099
1100public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001101 PixelVectorType(const Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +00001102 : Node(KPixelVectorType), Dimension(Dimension_) {}
1103
1104 template<typename Fn> void match(Fn F) const { F(Dimension); }
1105
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001106 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001107 // FIXME: This should demangle as "vector pixel".
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001108 OB += "pixel vector[";
1109 Dimension->print(OB);
1110 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001111 }
1112};
1113
Pengfei Wang50e90b82021-09-23 11:02:25 +08001114class BinaryFPType final : public Node {
1115 const Node *Dimension;
1116
1117public:
1118 BinaryFPType(const Node *Dimension_)
1119 : Node(KBinaryFPType), Dimension(Dimension_) {}
1120
1121 template<typename Fn> void match(Fn F) const { F(Dimension); }
1122
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001123 void printLeft(OutputBuffer &OB) const override {
1124 OB += "_Float";
1125 Dimension->print(OB);
Pengfei Wang50e90b82021-09-23 11:02:25 +08001126 }
1127};
1128
Richard Smithdf1c14c2019-09-06 23:53:21 +00001129enum class TemplateParamKind { Type, NonType, Template };
1130
1131/// An invented name for a template parameter for which we don't have a
1132/// corresponding template argument.
1133///
1134/// This node is created when parsing the <lambda-sig> for a lambda with
1135/// explicit template arguments, which might be referenced in the parameter
1136/// types appearing later in the <lambda-sig>.
1137class SyntheticTemplateParamName final : public Node {
1138 TemplateParamKind Kind;
1139 unsigned Index;
1140
1141public:
1142 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
1143 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
1144
1145 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
1146
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001147 void printLeft(OutputBuffer &OB) const override {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001148 switch (Kind) {
1149 case TemplateParamKind::Type:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001150 OB += "$T";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001151 break;
1152 case TemplateParamKind::NonType:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001153 OB += "$N";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001154 break;
1155 case TemplateParamKind::Template:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001156 OB += "$TT";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001157 break;
1158 }
1159 if (Index > 0)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001160 OB << Index - 1;
Richard Smithdf1c14c2019-09-06 23:53:21 +00001161 }
1162};
1163
1164/// A template type parameter declaration, 'typename T'.
1165class TypeTemplateParamDecl final : public Node {
1166 Node *Name;
1167
1168public:
1169 TypeTemplateParamDecl(Node *Name_)
1170 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
1171
1172 template<typename Fn> void match(Fn F) const { F(Name); }
1173
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001174 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001175
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001176 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001177};
1178
1179/// A non-type template parameter declaration, 'int N'.
1180class NonTypeTemplateParamDecl final : public Node {
1181 Node *Name;
1182 Node *Type;
1183
1184public:
1185 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
1186 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
1187
1188 template<typename Fn> void match(Fn F) const { F(Name, Type); }
1189
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001190 void printLeft(OutputBuffer &OB) const override {
1191 Type->printLeft(OB);
1192 if (!Type->hasRHSComponent(OB))
1193 OB += " ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001194 }
1195
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001196 void printRight(OutputBuffer &OB) const override {
1197 Name->print(OB);
1198 Type->printRight(OB);
Richard Smithdf1c14c2019-09-06 23:53:21 +00001199 }
1200};
1201
1202/// A template template parameter declaration,
1203/// 'template<typename T> typename N'.
1204class TemplateTemplateParamDecl final : public Node {
1205 Node *Name;
1206 NodeArray Params;
1207
1208public:
1209 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
1210 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1211 Params(Params_) {}
1212
1213 template<typename Fn> void match(Fn F) const { F(Name, Params); }
1214
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001215 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001216 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001217 OB += "template<";
1218 Params.printWithComma(OB);
1219 OB += "> typename ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001220 }
1221
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001222 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001223};
1224
1225/// A template parameter pack declaration, 'typename ...T'.
1226class TemplateParamPackDecl final : public Node {
1227 Node *Param;
1228
1229public:
1230 TemplateParamPackDecl(Node *Param_)
1231 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1232
1233 template<typename Fn> void match(Fn F) const { F(Param); }
1234
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001235 void printLeft(OutputBuffer &OB) const override {
1236 Param->printLeft(OB);
1237 OB += "...";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001238 }
1239
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001240 void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001241};
1242
Richard Smithc20d1442018-08-20 20:14:49 +00001243/// An unexpanded parameter pack (either in the expression or type context). If
1244/// this AST is correct, this node will have a ParameterPackExpansion node above
1245/// it.
1246///
1247/// This node is created when some <template-args> are found that apply to an
1248/// <encoding>, and is stored in the TemplateParams table. In order for this to
1249/// appear in the final AST, it has to referenced via a <template-param> (ie,
1250/// T_).
1251class ParameterPack final : public Node {
1252 NodeArray Data;
1253
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08001254 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1255 // one.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001256 void initializePackExpansion(OutputBuffer &OB) const {
1257 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1258 OB.CurrentPackMax = static_cast<unsigned>(Data.size());
1259 OB.CurrentPackIndex = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00001260 }
1261 }
1262
1263public:
1264 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1265 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
1266 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1267 return P->ArrayCache == Cache::No;
1268 }))
1269 ArrayCache = Cache::No;
1270 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1271 return P->FunctionCache == Cache::No;
1272 }))
1273 FunctionCache = Cache::No;
1274 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1275 return P->RHSComponentCache == Cache::No;
1276 }))
1277 RHSComponentCache = Cache::No;
1278 }
1279
1280 template<typename Fn> void match(Fn F) const { F(Data); }
1281
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001282 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1283 initializePackExpansion(OB);
1284 size_t Idx = OB.CurrentPackIndex;
1285 return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001286 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001287 bool hasArraySlow(OutputBuffer &OB) const override {
1288 initializePackExpansion(OB);
1289 size_t Idx = OB.CurrentPackIndex;
1290 return Idx < Data.size() && Data[Idx]->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001291 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001292 bool hasFunctionSlow(OutputBuffer &OB) const override {
1293 initializePackExpansion(OB);
1294 size_t Idx = OB.CurrentPackIndex;
1295 return Idx < Data.size() && Data[Idx]->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001296 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001297 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1298 initializePackExpansion(OB);
1299 size_t Idx = OB.CurrentPackIndex;
1300 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;
Richard Smithc20d1442018-08-20 20:14:49 +00001301 }
1302
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001303 void printLeft(OutputBuffer &OB) const override {
1304 initializePackExpansion(OB);
1305 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001306 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001307 Data[Idx]->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001308 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001309 void printRight(OutputBuffer &OB) const override {
1310 initializePackExpansion(OB);
1311 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001312 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001313 Data[Idx]->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001314 }
1315};
1316
1317/// A variadic template argument. This node represents an occurrence of
1318/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1319/// one of it's Elements is. The parser inserts a ParameterPack into the
1320/// TemplateParams table if the <template-args> this pack belongs to apply to an
1321/// <encoding>.
1322class TemplateArgumentPack final : public Node {
1323 NodeArray Elements;
1324public:
1325 TemplateArgumentPack(NodeArray Elements_)
1326 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1327
1328 template<typename Fn> void match(Fn F) const { F(Elements); }
1329
1330 NodeArray getElements() const { return Elements; }
1331
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001332 void printLeft(OutputBuffer &OB) const override {
1333 Elements.printWithComma(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001334 }
1335};
1336
1337/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1338/// which each have Child->ParameterPackSize elements.
1339class ParameterPackExpansion final : public Node {
1340 const Node *Child;
1341
1342public:
1343 ParameterPackExpansion(const Node *Child_)
1344 : Node(KParameterPackExpansion), Child(Child_) {}
1345
1346 template<typename Fn> void match(Fn F) const { F(Child); }
1347
1348 const Node *getChild() const { return Child; }
1349
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001350 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001351 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001352 ScopedOverride<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1353 ScopedOverride<unsigned> SavePackMax(OB.CurrentPackMax, Max);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001354 size_t StreamPos = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +00001355
1356 // Print the first element in the pack. If Child contains a ParameterPack,
1357 // it will set up S.CurrentPackMax and print the first element.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001358 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001359
1360 // No ParameterPack was found in Child. This can occur if we've found a pack
1361 // expansion on a <function-param>.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001362 if (OB.CurrentPackMax == Max) {
1363 OB += "...";
Richard Smithc20d1442018-08-20 20:14:49 +00001364 return;
1365 }
1366
1367 // We found a ParameterPack, but it has no elements. Erase whatever we may
1368 // of printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001369 if (OB.CurrentPackMax == 0) {
1370 OB.setCurrentPosition(StreamPos);
Richard Smithc20d1442018-08-20 20:14:49 +00001371 return;
1372 }
1373
1374 // Else, iterate through the rest of the elements in the pack.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001375 for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {
1376 OB += ", ";
1377 OB.CurrentPackIndex = I;
1378 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001379 }
1380 }
1381};
1382
1383class TemplateArgs final : public Node {
1384 NodeArray Params;
1385
1386public:
1387 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1388
1389 template<typename Fn> void match(Fn F) const { F(Params); }
1390
1391 NodeArray getParams() { return Params; }
1392
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001393 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001394 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001395 OB += "<";
1396 Params.printWithComma(OB);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001397 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +00001398 }
1399};
1400
Richard Smithb485b352018-08-24 23:30:26 +00001401/// A forward-reference to a template argument that was not known at the point
1402/// where the template parameter name was parsed in a mangling.
1403///
1404/// This is created when demangling the name of a specialization of a
1405/// conversion function template:
1406///
1407/// \code
1408/// struct A {
1409/// template<typename T> operator T*();
1410/// };
1411/// \endcode
1412///
1413/// When demangling a specialization of the conversion function template, we
1414/// encounter the name of the template (including the \c T) before we reach
1415/// the template argument list, so we cannot substitute the parameter name
1416/// for the corresponding argument while parsing. Instead, we create a
1417/// \c ForwardTemplateReference node that is resolved after we parse the
1418/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001419struct ForwardTemplateReference : Node {
1420 size_t Index;
1421 Node *Ref = nullptr;
1422
1423 // If we're currently printing this node. It is possible (though invalid) for
1424 // a forward template reference to refer to itself via a substitution. This
1425 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1426 // out if more than one print* function is active.
1427 mutable bool Printing = false;
1428
1429 ForwardTemplateReference(size_t Index_)
1430 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1431 Cache::Unknown),
1432 Index(Index_) {}
1433
1434 // We don't provide a matcher for these, because the value of the node is
1435 // not determined by its construction parameters, and it generally needs
1436 // special handling.
1437 template<typename Fn> void match(Fn F) const = delete;
1438
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001439 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001440 if (Printing)
1441 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001442 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001443 return Ref->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001444 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001445 bool hasArraySlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001446 if (Printing)
1447 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001448 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001449 return Ref->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001450 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001451 bool hasFunctionSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001452 if (Printing)
1453 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001454 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001455 return Ref->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001456 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001457 const Node *getSyntaxNode(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001458 if (Printing)
1459 return this;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001460 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001461 return Ref->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001462 }
1463
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001464 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001465 if (Printing)
1466 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001467 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001468 Ref->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001469 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001470 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001471 if (Printing)
1472 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001473 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001474 Ref->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001475 }
1476};
1477
1478struct NameWithTemplateArgs : Node {
1479 // name<template_args>
1480 Node *Name;
1481 Node *TemplateArgs;
1482
1483 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1484 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1485
1486 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1487
1488 StringView getBaseName() const override { return Name->getBaseName(); }
1489
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001490 void printLeft(OutputBuffer &OB) const override {
1491 Name->print(OB);
1492 TemplateArgs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001493 }
1494};
1495
1496class GlobalQualifiedName final : public Node {
1497 Node *Child;
1498
1499public:
1500 GlobalQualifiedName(Node* Child_)
1501 : Node(KGlobalQualifiedName), Child(Child_) {}
1502
1503 template<typename Fn> void match(Fn F) const { F(Child); }
1504
1505 StringView getBaseName() const override { return Child->getBaseName(); }
1506
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001507 void printLeft(OutputBuffer &OB) const override {
1508 OB += "::";
1509 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001510 }
1511};
1512
Richard Smithc20d1442018-08-20 20:14:49 +00001513enum class SpecialSubKind {
1514 allocator,
1515 basic_string,
1516 string,
1517 istream,
1518 ostream,
1519 iostream,
1520};
1521
Nathan Sidwell28201492022-03-28 12:55:45 -07001522class SpecialSubstitution;
1523class ExpandedSpecialSubstitution : public Node {
1524protected:
Richard Smithc20d1442018-08-20 20:14:49 +00001525 SpecialSubKind SSK;
1526
Nathan Sidwell28201492022-03-28 12:55:45 -07001527 ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)
1528 : Node(K_), SSK(SSK_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001529public:
1530 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
Nathan Sidwell28201492022-03-28 12:55:45 -07001531 : ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}
1532 inline ExpandedSpecialSubstitution(SpecialSubstitution const *);
Richard Smithc20d1442018-08-20 20:14:49 +00001533
1534 template<typename Fn> void match(Fn F) const { F(SSK); }
1535
Nathan Sidwell28201492022-03-28 12:55:45 -07001536protected:
1537 bool isInstantiation() const {
1538 return unsigned(SSK) >= unsigned(SpecialSubKind::string);
1539 }
1540
Richard Smithc20d1442018-08-20 20:14:49 +00001541 StringView getBaseName() const override {
1542 switch (SSK) {
1543 case SpecialSubKind::allocator:
1544 return StringView("allocator");
1545 case SpecialSubKind::basic_string:
1546 return StringView("basic_string");
1547 case SpecialSubKind::string:
1548 return StringView("basic_string");
1549 case SpecialSubKind::istream:
1550 return StringView("basic_istream");
1551 case SpecialSubKind::ostream:
1552 return StringView("basic_ostream");
1553 case SpecialSubKind::iostream:
1554 return StringView("basic_iostream");
1555 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001556 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001557 }
1558
Nathan Sidwell28201492022-03-28 12:55:45 -07001559private:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001560 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell28201492022-03-28 12:55:45 -07001561 OB << "std::" << getBaseName();
1562 if (isInstantiation()) {
1563 OB << "<char, std::char_traits<char>";
1564 if (SSK == SpecialSubKind::string)
1565 OB << ", std::allocator<char>";
1566 OB << ">";
Richard Smithc20d1442018-08-20 20:14:49 +00001567 }
1568 }
1569};
1570
Nathan Sidwell28201492022-03-28 12:55:45 -07001571class SpecialSubstitution final : public ExpandedSpecialSubstitution {
Richard Smithc20d1442018-08-20 20:14:49 +00001572public:
Richard Smithc20d1442018-08-20 20:14:49 +00001573 SpecialSubstitution(SpecialSubKind SSK_)
Nathan Sidwell28201492022-03-28 12:55:45 -07001574 : ExpandedSpecialSubstitution(SSK_, KSpecialSubstitution) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001575
1576 template<typename Fn> void match(Fn F) const { F(SSK); }
1577
1578 StringView getBaseName() const override {
Nathan Sidwell28201492022-03-28 12:55:45 -07001579 auto SV = ExpandedSpecialSubstitution::getBaseName ();
1580 if (isInstantiation()) {
1581 // The instantiations are typedefs that drop the "basic_" prefix.
1582 assert(SV.startsWith("basic_"));
1583 SV = SV.dropFront(sizeof("basic_") - 1);
Richard Smithc20d1442018-08-20 20:14:49 +00001584 }
Nathan Sidwell28201492022-03-28 12:55:45 -07001585 return SV;
Richard Smithc20d1442018-08-20 20:14:49 +00001586 }
1587
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001588 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell28201492022-03-28 12:55:45 -07001589 OB << "std::" << getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001590 }
1591};
1592
Nathan Sidwell28201492022-03-28 12:55:45 -07001593inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(
1594 SpecialSubstitution const *SS)
1595 : ExpandedSpecialSubstitution(SS->SSK) {}
1596
Richard Smithc20d1442018-08-20 20:14:49 +00001597class CtorDtorName final : public Node {
1598 const Node *Basename;
1599 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001600 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001601
1602public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001603 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1604 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1605 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001606
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001607 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001608
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001609 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001610 if (IsDtor)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001611 OB += "~";
1612 OB += Basename->getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001613 }
1614};
1615
1616class DtorName : public Node {
1617 const Node *Base;
1618
1619public:
1620 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1621
1622 template<typename Fn> void match(Fn F) const { F(Base); }
1623
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001624 void printLeft(OutputBuffer &OB) const override {
1625 OB += "~";
1626 Base->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001627 }
1628};
1629
1630class UnnamedTypeName : public Node {
1631 const StringView Count;
1632
1633public:
1634 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1635
1636 template<typename Fn> void match(Fn F) const { F(Count); }
1637
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001638 void printLeft(OutputBuffer &OB) const override {
1639 OB += "'unnamed";
1640 OB += Count;
1641 OB += "\'";
Richard Smithc20d1442018-08-20 20:14:49 +00001642 }
1643};
1644
1645class ClosureTypeName : public Node {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001646 NodeArray TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00001647 NodeArray Params;
1648 StringView Count;
1649
1650public:
Richard Smithdf1c14c2019-09-06 23:53:21 +00001651 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1652 StringView Count_)
1653 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1654 Params(Params_), Count(Count_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001655
Richard Smithdf1c14c2019-09-06 23:53:21 +00001656 template<typename Fn> void match(Fn F) const {
1657 F(TemplateParams, Params, Count);
1658 }
1659
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001660 void printDeclarator(OutputBuffer &OB) const {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001661 if (!TemplateParams.empty()) {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001662 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001663 OB += "<";
1664 TemplateParams.printWithComma(OB);
1665 OB += ">";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001666 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001667 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001668 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001669 OB.printClose();
Richard Smithdf1c14c2019-09-06 23:53:21 +00001670 }
Richard Smithc20d1442018-08-20 20:14:49 +00001671
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001672 void printLeft(OutputBuffer &OB) const override {
1673 OB += "\'lambda";
1674 OB += Count;
1675 OB += "\'";
1676 printDeclarator(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001677 }
1678};
1679
1680class StructuredBindingName : public Node {
1681 NodeArray Bindings;
1682public:
1683 StructuredBindingName(NodeArray Bindings_)
1684 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1685
1686 template<typename Fn> void match(Fn F) const { F(Bindings); }
1687
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001688 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001689 OB.printOpen('[');
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001690 Bindings.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001691 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001692 }
1693};
1694
1695// -- Expression Nodes --
1696
1697class BinaryExpr : public Node {
1698 const Node *LHS;
1699 const StringView InfixOperator;
1700 const Node *RHS;
1701
1702public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001703 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
1704 Prec Prec_)
1705 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
1706 RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001707
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001708 template <typename Fn> void match(Fn F) const {
1709 F(LHS, InfixOperator, RHS, getPrecedence());
1710 }
Richard Smithc20d1442018-08-20 20:14:49 +00001711
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001712 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell18505102022-03-25 04:34:19 -07001713 bool ParenAll = OB.isGtInsideTemplateArgs() &&
1714 (InfixOperator == ">" || InfixOperator == ">>");
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001715 if (ParenAll)
1716 OB.printOpen();
1717 // Assignment is right associative, with special LHS precedence.
1718 bool IsAssign = getPrecedence() == Prec::Assign;
1719 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1720 // No space before comma operator
1721 if (!(InfixOperator == ","))
1722 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001723 OB += InfixOperator;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001724 OB += " ";
1725 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1726 if (ParenAll)
1727 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001728 }
1729};
1730
1731class ArraySubscriptExpr : public Node {
1732 const Node *Op1;
1733 const Node *Op2;
1734
1735public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001736 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1737 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001738
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001739 template <typename Fn> void match(Fn F) const {
1740 F(Op1, Op2, getPrecedence());
1741 }
Richard Smithc20d1442018-08-20 20:14:49 +00001742
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001743 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001744 Op1->printAsOperand(OB, getPrecedence());
1745 OB.printOpen('[');
1746 Op2->printAsOperand(OB);
1747 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001748 }
1749};
1750
1751class PostfixExpr : public Node {
1752 const Node *Child;
1753 const StringView Operator;
1754
1755public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001756 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
1757 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001758
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001759 template <typename Fn> void match(Fn F) const {
1760 F(Child, Operator, getPrecedence());
1761 }
Richard Smithc20d1442018-08-20 20:14:49 +00001762
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001763 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001764 Child->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001765 OB += Operator;
Richard Smithc20d1442018-08-20 20:14:49 +00001766 }
1767};
1768
1769class ConditionalExpr : public Node {
1770 const Node *Cond;
1771 const Node *Then;
1772 const Node *Else;
1773
1774public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001775 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1776 Prec Prec_)
1777 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001778
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001779 template <typename Fn> void match(Fn F) const {
1780 F(Cond, Then, Else, getPrecedence());
1781 }
Richard Smithc20d1442018-08-20 20:14:49 +00001782
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001783 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001784 Cond->printAsOperand(OB, getPrecedence());
1785 OB += " ? ";
1786 Then->printAsOperand(OB);
1787 OB += " : ";
1788 Else->printAsOperand(OB, Prec::Assign, true);
Richard Smithc20d1442018-08-20 20:14:49 +00001789 }
1790};
1791
1792class MemberExpr : public Node {
1793 const Node *LHS;
1794 const StringView Kind;
1795 const Node *RHS;
1796
1797public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001798 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
1799 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001800
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001801 template <typename Fn> void match(Fn F) const {
1802 F(LHS, Kind, RHS, getPrecedence());
1803 }
Richard Smithc20d1442018-08-20 20:14:49 +00001804
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001805 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001806 LHS->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001807 OB += Kind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001808 RHS->printAsOperand(OB, getPrecedence(), false);
Richard Smithc20d1442018-08-20 20:14:49 +00001809 }
1810};
1811
Richard Smith1865d2f2020-10-22 19:29:36 -07001812class SubobjectExpr : public Node {
1813 const Node *Type;
1814 const Node *SubExpr;
1815 StringView Offset;
1816 NodeArray UnionSelectors;
1817 bool OnePastTheEnd;
1818
1819public:
1820 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1821 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1822 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1823 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1824
1825 template<typename Fn> void match(Fn F) const {
1826 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1827 }
1828
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001829 void printLeft(OutputBuffer &OB) const override {
1830 SubExpr->print(OB);
1831 OB += ".<";
1832 Type->print(OB);
1833 OB += " at offset ";
Richard Smith1865d2f2020-10-22 19:29:36 -07001834 if (Offset.empty()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001835 OB += "0";
Richard Smith1865d2f2020-10-22 19:29:36 -07001836 } else if (Offset[0] == 'n') {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001837 OB += "-";
1838 OB += Offset.dropFront();
Richard Smith1865d2f2020-10-22 19:29:36 -07001839 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001840 OB += Offset;
Richard Smith1865d2f2020-10-22 19:29:36 -07001841 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001842 OB += ">";
Richard Smith1865d2f2020-10-22 19:29:36 -07001843 }
1844};
1845
Richard Smithc20d1442018-08-20 20:14:49 +00001846class EnclosingExpr : public Node {
1847 const StringView Prefix;
1848 const Node *Infix;
1849 const StringView Postfix;
1850
1851public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001852 EnclosingExpr(StringView Prefix_, const Node *Infix_,
1853 Prec Prec_ = Prec::Primary)
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001854 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001855
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001856 template <typename Fn> void match(Fn F) const {
1857 F(Prefix, Infix, getPrecedence());
1858 }
Richard Smithc20d1442018-08-20 20:14:49 +00001859
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001860 void printLeft(OutputBuffer &OB) const override {
1861 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001862 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001863 Infix->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001864 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001865 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +00001866 }
1867};
1868
1869class CastExpr : public Node {
1870 // cast_kind<to>(from)
1871 const StringView CastKind;
1872 const Node *To;
1873 const Node *From;
1874
1875public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001876 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
1877 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001878
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001879 template <typename Fn> void match(Fn F) const {
1880 F(CastKind, To, From, getPrecedence());
1881 }
Richard Smithc20d1442018-08-20 20:14:49 +00001882
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001883 void printLeft(OutputBuffer &OB) const override {
1884 OB += CastKind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001885 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001886 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001887 OB += "<";
1888 To->printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001889 OB += ">";
1890 }
1891 OB.printOpen();
1892 From->printAsOperand(OB);
1893 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001894 }
1895};
1896
1897class SizeofParamPackExpr : public Node {
1898 const Node *Pack;
1899
1900public:
1901 SizeofParamPackExpr(const Node *Pack_)
1902 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1903
1904 template<typename Fn> void match(Fn F) const { F(Pack); }
1905
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001906 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001907 OB += "sizeof...";
1908 OB.printOpen();
Richard Smithc20d1442018-08-20 20:14:49 +00001909 ParameterPackExpansion PPE(Pack);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001910 PPE.printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001911 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001912 }
1913};
1914
1915class CallExpr : public Node {
1916 const Node *Callee;
1917 NodeArray Args;
1918
1919public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001920 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
1921 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001922
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001923 template <typename Fn> void match(Fn F) const {
1924 F(Callee, Args, getPrecedence());
1925 }
Richard Smithc20d1442018-08-20 20:14:49 +00001926
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001927 void printLeft(OutputBuffer &OB) const override {
1928 Callee->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001929 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001930 Args.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001931 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001932 }
1933};
1934
1935class NewExpr : public Node {
1936 // new (expr_list) type(init_list)
1937 NodeArray ExprList;
1938 Node *Type;
1939 NodeArray InitList;
1940 bool IsGlobal; // ::operator new ?
1941 bool IsArray; // new[] ?
1942public:
1943 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001944 bool IsArray_, Prec Prec_)
1945 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
1946 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001947
1948 template<typename Fn> void match(Fn F) const {
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001949 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00001950 }
1951
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001952 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001953 if (IsGlobal)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001954 OB += "::";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001955 OB += "new";
Richard Smithc20d1442018-08-20 20:14:49 +00001956 if (IsArray)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001957 OB += "[]";
Richard Smithc20d1442018-08-20 20:14:49 +00001958 if (!ExprList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001959 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001960 ExprList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001961 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001962 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001963 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001964 Type->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001965 if (!InitList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001966 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001967 InitList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001968 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001969 }
Richard Smithc20d1442018-08-20 20:14:49 +00001970 }
1971};
1972
1973class DeleteExpr : public Node {
1974 Node *Op;
1975 bool IsGlobal;
1976 bool IsArray;
1977
1978public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001979 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
1980 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
1981 IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001982
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001983 template <typename Fn> void match(Fn F) const {
1984 F(Op, IsGlobal, IsArray, getPrecedence());
1985 }
Richard Smithc20d1442018-08-20 20:14:49 +00001986
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001987 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001988 if (IsGlobal)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001989 OB += "::";
1990 OB += "delete";
Richard Smithc20d1442018-08-20 20:14:49 +00001991 if (IsArray)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001992 OB += "[]";
1993 OB += ' ';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001994 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001995 }
1996};
1997
1998class PrefixExpr : public Node {
1999 StringView Prefix;
2000 Node *Child;
2001
2002public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002003 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
2004 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002005
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002006 template <typename Fn> void match(Fn F) const {
2007 F(Prefix, Child, getPrecedence());
2008 }
Richard Smithc20d1442018-08-20 20:14:49 +00002009
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002010 void printLeft(OutputBuffer &OB) const override {
2011 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002012 Child->printAsOperand(OB, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00002013 }
2014};
2015
2016class FunctionParam : public Node {
2017 StringView Number;
2018
2019public:
2020 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
2021
2022 template<typename Fn> void match(Fn F) const { F(Number); }
2023
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002024 void printLeft(OutputBuffer &OB) const override {
2025 OB += "fp";
2026 OB += Number;
Richard Smithc20d1442018-08-20 20:14:49 +00002027 }
2028};
2029
2030class ConversionExpr : public Node {
2031 const Node *Type;
2032 NodeArray Expressions;
2033
2034public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002035 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2036 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002037
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002038 template <typename Fn> void match(Fn F) const {
2039 F(Type, Expressions, getPrecedence());
2040 }
Richard Smithc20d1442018-08-20 20:14:49 +00002041
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002042 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002043 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002044 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002045 OB.printClose();
2046 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002047 Expressions.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002048 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002049 }
2050};
2051
Richard Smith1865d2f2020-10-22 19:29:36 -07002052class PointerToMemberConversionExpr : public Node {
2053 const Node *Type;
2054 const Node *SubExpr;
2055 StringView Offset;
2056
2057public:
2058 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002059 StringView Offset_, Prec Prec_)
2060 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2061 SubExpr(SubExpr_), Offset(Offset_) {}
Richard Smith1865d2f2020-10-22 19:29:36 -07002062
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002063 template <typename Fn> void match(Fn F) const {
2064 F(Type, SubExpr, Offset, getPrecedence());
2065 }
Richard Smith1865d2f2020-10-22 19:29:36 -07002066
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002067 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002068 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002069 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002070 OB.printClose();
2071 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002072 SubExpr->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002073 OB.printClose();
Richard Smith1865d2f2020-10-22 19:29:36 -07002074 }
2075};
2076
Richard Smithc20d1442018-08-20 20:14:49 +00002077class InitListExpr : public Node {
2078 const Node *Ty;
2079 NodeArray Inits;
2080public:
2081 InitListExpr(const Node *Ty_, NodeArray Inits_)
2082 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2083
2084 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2085
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002086 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002087 if (Ty)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002088 Ty->print(OB);
2089 OB += '{';
2090 Inits.printWithComma(OB);
2091 OB += '}';
Richard Smithc20d1442018-08-20 20:14:49 +00002092 }
2093};
2094
2095class BracedExpr : public Node {
2096 const Node *Elem;
2097 const Node *Init;
2098 bool IsArray;
2099public:
2100 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2101 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2102
2103 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
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 (IsArray) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002107 OB += '[';
2108 Elem->print(OB);
2109 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002110 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002111 OB += '.';
2112 Elem->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002113 }
2114 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002115 OB += " = ";
2116 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002117 }
2118};
2119
2120class BracedRangeExpr : public Node {
2121 const Node *First;
2122 const Node *Last;
2123 const Node *Init;
2124public:
2125 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2126 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2127
2128 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2129
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002130 void printLeft(OutputBuffer &OB) const override {
2131 OB += '[';
2132 First->print(OB);
2133 OB += " ... ";
2134 Last->print(OB);
2135 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002136 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002137 OB += " = ";
2138 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002139 }
2140};
2141
2142class FoldExpr : public Node {
2143 const Node *Pack, *Init;
2144 StringView OperatorName;
2145 bool IsLeftFold;
2146
2147public:
2148 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
2149 const Node *Init_)
2150 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2151 IsLeftFold(IsLeftFold_) {}
2152
2153 template<typename Fn> void match(Fn F) const {
2154 F(IsLeftFold, OperatorName, Pack, Init);
2155 }
2156
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002157 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002158 auto PrintPack = [&] {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002159 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002160 ParameterPackExpansion(Pack).print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002161 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002162 };
2163
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002164 OB.printOpen();
2165 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2166 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2167 // Fold expr operands are cast-expressions
2168 if (!IsLeftFold || Init != nullptr) {
2169 // '(init|pack) op '
2170 if (IsLeftFold)
2171 Init->printAsOperand(OB, Prec::Cast, true);
2172 else
2173 PrintPack();
2174 OB << " " << OperatorName << " ";
Richard Smithc20d1442018-08-20 20:14:49 +00002175 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002176 OB << "...";
2177 if (IsLeftFold || Init != nullptr) {
2178 // ' op (init|pack)'
2179 OB << " " << OperatorName << " ";
2180 if (IsLeftFold)
2181 PrintPack();
2182 else
2183 Init->printAsOperand(OB, Prec::Cast, true);
2184 }
2185 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002186 }
2187};
2188
2189class ThrowExpr : public Node {
2190 const Node *Op;
2191
2192public:
2193 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2194
2195 template<typename Fn> void match(Fn F) const { F(Op); }
2196
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002197 void printLeft(OutputBuffer &OB) const override {
2198 OB += "throw ";
2199 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002200 }
2201};
2202
2203class BoolExpr : public Node {
2204 bool Value;
2205
2206public:
2207 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2208
2209 template<typename Fn> void match(Fn F) const { F(Value); }
2210
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002211 void printLeft(OutputBuffer &OB) const override {
2212 OB += Value ? StringView("true") : StringView("false");
Richard Smithc20d1442018-08-20 20:14:49 +00002213 }
2214};
2215
Richard Smithdf1c14c2019-09-06 23:53:21 +00002216class StringLiteral : public Node {
2217 const Node *Type;
2218
2219public:
2220 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2221
2222 template<typename Fn> void match(Fn F) const { F(Type); }
2223
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002224 void printLeft(OutputBuffer &OB) const override {
2225 OB += "\"<";
2226 Type->print(OB);
2227 OB += ">\"";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002228 }
2229};
2230
2231class LambdaExpr : public Node {
2232 const Node *Type;
2233
Richard Smithdf1c14c2019-09-06 23:53:21 +00002234public:
2235 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2236
2237 template<typename Fn> void match(Fn F) const { F(Type); }
2238
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002239 void printLeft(OutputBuffer &OB) const override {
2240 OB += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002241 if (Type->getKind() == KClosureTypeName)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002242 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2243 OB += "{...}";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002244 }
2245};
2246
Erik Pilkington0a170f12020-05-13 14:13:37 -04002247class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002248 // ty(integer)
2249 const Node *Ty;
2250 StringView Integer;
2251
2252public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002253 EnumLiteral(const Node *Ty_, StringView Integer_)
2254 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002255
2256 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2257
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002258 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002259 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002260 Ty->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002261 OB.printClose();
Erik Pilkington0a170f12020-05-13 14:13:37 -04002262
2263 if (Integer[0] == 'n')
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002264 OB << "-" << Integer.dropFront(1);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002265 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002266 OB << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002267 }
2268};
2269
2270class IntegerLiteral : public Node {
2271 StringView Type;
2272 StringView Value;
2273
2274public:
2275 IntegerLiteral(StringView Type_, StringView Value_)
2276 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2277
2278 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2279
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002280 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002281 if (Type.size() > 3) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002282 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002283 OB += Type;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002284 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002285 }
2286
2287 if (Value[0] == 'n') {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002288 OB += '-';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002289 OB += Value.dropFront(1);
Richard Smithc20d1442018-08-20 20:14:49 +00002290 } else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002291 OB += Value;
Richard Smithc20d1442018-08-20 20:14:49 +00002292
2293 if (Type.size() <= 3)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002294 OB += Type;
Richard Smithc20d1442018-08-20 20:14:49 +00002295 }
2296};
2297
2298template <class Float> struct FloatData;
2299
2300namespace float_literal_impl {
2301constexpr Node::Kind getFloatLiteralKind(float *) {
2302 return Node::KFloatLiteral;
2303}
2304constexpr Node::Kind getFloatLiteralKind(double *) {
2305 return Node::KDoubleLiteral;
2306}
2307constexpr Node::Kind getFloatLiteralKind(long double *) {
2308 return Node::KLongDoubleLiteral;
2309}
2310}
2311
2312template <class Float> class FloatLiteralImpl : public Node {
2313 const StringView Contents;
2314
2315 static constexpr Kind KindForClass =
2316 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2317
2318public:
2319 FloatLiteralImpl(StringView Contents_)
2320 : Node(KindForClass), Contents(Contents_) {}
2321
2322 template<typename Fn> void match(Fn F) const { F(Contents); }
2323
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002324 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002325 const char *first = Contents.begin();
2326 const char *last = Contents.end() + 1;
2327
2328 const size_t N = FloatData<Float>::mangled_size;
2329 if (static_cast<std::size_t>(last - first) > N) {
2330 last = first + N;
2331 union {
2332 Float value;
2333 char buf[sizeof(Float)];
2334 };
2335 const char *t = first;
2336 char *e = buf;
2337 for (; t != last; ++t, ++e) {
2338 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2339 : static_cast<unsigned>(*t - 'a' + 10);
2340 ++t;
2341 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2342 : static_cast<unsigned>(*t - 'a' + 10);
2343 *e = static_cast<char>((d1 << 4) + d0);
2344 }
2345#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2346 std::reverse(buf, e);
2347#endif
2348 char num[FloatData<Float>::max_demangled_size] = {0};
2349 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002350 OB += StringView(num, num + n);
Richard Smithc20d1442018-08-20 20:14:49 +00002351 }
2352 }
2353};
2354
2355using FloatLiteral = FloatLiteralImpl<float>;
2356using DoubleLiteral = FloatLiteralImpl<double>;
2357using LongDoubleLiteral = FloatLiteralImpl<long double>;
2358
2359/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2360/// appropriate derived class.
2361template<typename Fn>
2362void Node::visit(Fn F) const {
2363 switch (K) {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002364#define NODE(X) \
2365 case K##X: \
2366 return F(static_cast<const X *>(this));
2367#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002368 }
2369 assert(0 && "unknown mangling node kind");
2370}
2371
2372/// Determine the kind of a node from its type.
2373template<typename NodeT> struct NodeKind;
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002374#define NODE(X) \
2375 template <> struct NodeKind<X> { \
2376 static constexpr Node::Kind Kind = Node::K##X; \
2377 static constexpr const char *name() { return #X; } \
Richard Smithc20d1442018-08-20 20:14:49 +00002378 };
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002379#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002380
Pavel Labathba825192018-10-16 14:29:14 +00002381template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002382 const char *First;
2383 const char *Last;
2384
2385 // Name stack, this is used by the parser to hold temporary names that were
2386 // parsed. The parser collapses multiple names into new nodes to construct
2387 // the AST. Once the parser is finished, names.size() == 1.
2388 PODSmallVector<Node *, 32> Names;
2389
2390 // Substitution table. Itanium supports name substitutions as a means of
2391 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2392 // table.
2393 PODSmallVector<Node *, 32> Subs;
2394
Richard Smithdf1c14c2019-09-06 23:53:21 +00002395 using TemplateParamList = PODSmallVector<Node *, 8>;
2396
2397 class ScopedTemplateParamList {
2398 AbstractManglingParser *Parser;
2399 size_t OldNumTemplateParamLists;
2400 TemplateParamList Params;
2401
2402 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002403 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2404 : Parser(TheParser),
2405 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002406 Parser->TemplateParams.push_back(&Params);
2407 }
2408 ~ScopedTemplateParamList() {
2409 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2410 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2411 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002412 };
2413
Richard Smithc20d1442018-08-20 20:14:49 +00002414 // Template parameter table. Like the above, but referenced like "T42_".
2415 // This has a smaller size compared to Subs and Names because it can be
2416 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002417 TemplateParamList OuterTemplateParams;
2418
2419 // Lists of template parameters indexed by template parameter depth,
2420 // referenced like "TL2_4_". If nonempty, element 0 is always
2421 // OuterTemplateParams; inner elements are always template parameter lists of
2422 // lambda expressions. For a generic lambda with no explicit template
2423 // parameter list, the corresponding parameter list pointer will be null.
2424 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002425
2426 // Set of unresolved forward <template-param> references. These can occur in a
2427 // conversion operator's type, and are resolved in the enclosing <encoding>.
2428 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2429
Richard Smithc20d1442018-08-20 20:14:49 +00002430 bool TryToParseTemplateArgs = true;
2431 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002432 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2433
2434 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002435
2436 Alloc ASTAllocator;
2437
Pavel Labathba825192018-10-16 14:29:14 +00002438 AbstractManglingParser(const char *First_, const char *Last_)
2439 : First(First_), Last(Last_) {}
2440
2441 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002442
2443 void reset(const char *First_, const char *Last_) {
2444 First = First_;
2445 Last = Last_;
2446 Names.clear();
2447 Subs.clear();
2448 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002449 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002450 TryToParseTemplateArgs = true;
2451 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002452 for (int I = 0; I != 3; ++I)
2453 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002454 ASTAllocator.reset();
2455 }
2456
Richard Smithb485b352018-08-24 23:30:26 +00002457 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002458 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2459 }
2460
2461 template <class It> NodeArray makeNodeArray(It begin, It end) {
2462 size_t sz = static_cast<size_t>(end - begin);
2463 void *mem = ASTAllocator.allocateNodeArray(sz);
2464 Node **data = new (mem) Node *[sz];
2465 std::copy(begin, end, data);
2466 return NodeArray(data, sz);
2467 }
2468
2469 NodeArray popTrailingNodeArray(size_t FromPosition) {
2470 assert(FromPosition <= Names.size());
2471 NodeArray res =
2472 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2473 Names.dropBack(FromPosition);
2474 return res;
2475 }
2476
2477 bool consumeIf(StringView S) {
2478 if (StringView(First, Last).startsWith(S)) {
2479 First += S.size();
2480 return true;
2481 }
2482 return false;
2483 }
2484
2485 bool consumeIf(char C) {
2486 if (First != Last && *First == C) {
2487 ++First;
2488 return true;
2489 }
2490 return false;
2491 }
2492
2493 char consume() { return First != Last ? *First++ : '\0'; }
2494
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08002495 char look(unsigned Lookahead = 0) const {
Richard Smithc20d1442018-08-20 20:14:49 +00002496 if (static_cast<size_t>(Last - First) <= Lookahead)
2497 return '\0';
2498 return First[Lookahead];
2499 }
2500
2501 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2502
2503 StringView parseNumber(bool AllowNegative = false);
2504 Qualifiers parseCVQualifiers();
2505 bool parsePositiveInteger(size_t *Out);
2506 StringView parseBareSourceName();
2507
2508 bool parseSeqId(size_t *Out);
2509 Node *parseSubstitution();
2510 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002511 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002512 Node *parseTemplateArgs(bool TagTemplates = false);
2513 Node *parseTemplateArg();
2514
2515 /// Parse the <expr> production.
2516 Node *parseExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002517 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2518 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00002519 Node *parseIntegerLiteral(StringView Lit);
2520 Node *parseExprPrimary();
2521 template <class Float> Node *parseFloatingLiteral();
2522 Node *parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00002523 Node *parseConversionExpr();
2524 Node *parseBracedExpr();
2525 Node *parseFoldExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002526 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07002527 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002528
2529 /// Parse the <type> production.
2530 Node *parseType();
2531 Node *parseFunctionType();
2532 Node *parseVectorType();
2533 Node *parseDecltype();
2534 Node *parseArrayType();
2535 Node *parsePointerToMemberType();
2536 Node *parseClassEnumType();
2537 Node *parseQualifiedType();
2538
2539 Node *parseEncoding();
2540 bool parseCallOffset();
2541 Node *parseSpecialName();
2542
2543 /// Holds some extra information about a <name> that is being parsed. This
2544 /// information is only pertinent if the <name> refers to an <encoding>.
2545 struct NameState {
2546 bool CtorDtorConversion = false;
2547 bool EndsWithTemplateArgs = false;
2548 Qualifiers CVQualifiers = QualNone;
2549 FunctionRefQual ReferenceQualifier = FrefQualNone;
2550 size_t ForwardTemplateRefsBegin;
2551
Pavel Labathba825192018-10-16 14:29:14 +00002552 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002553 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2554 };
2555
2556 bool resolveForwardTemplateRefs(NameState &State) {
2557 size_t I = State.ForwardTemplateRefsBegin;
2558 size_t E = ForwardTemplateRefs.size();
2559 for (; I < E; ++I) {
2560 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002561 if (TemplateParams.empty() || !TemplateParams[0] ||
2562 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002563 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002564 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002565 }
2566 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2567 return false;
2568 }
2569
2570 /// Parse the <name> production>
2571 Node *parseName(NameState *State = nullptr);
2572 Node *parseLocalName(NameState *State);
2573 Node *parseOperatorName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002574 bool parseModuleNameOpt(ModuleName *&Module);
2575 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
Richard Smithc20d1442018-08-20 20:14:49 +00002576 Node *parseUnnamedTypeName(NameState *State);
2577 Node *parseSourceName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002578 Node *parseUnscopedName(NameState *State, bool *isSubstName);
Richard Smithc20d1442018-08-20 20:14:49 +00002579 Node *parseNestedName(NameState *State);
2580 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2581
2582 Node *parseAbiTags(Node *N);
2583
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002584 struct OperatorInfo {
2585 enum OIKind : unsigned char {
2586 Prefix, // Prefix unary: @ expr
2587 Postfix, // Postfix unary: expr @
2588 Binary, // Binary: lhs @ rhs
2589 Array, // Array index: lhs [ rhs ]
2590 Member, // Member access: lhs @ rhs
2591 New, // New
2592 Del, // Delete
2593 Call, // Function call: expr (expr*)
2594 CCast, // C cast: (type)expr
2595 Conditional, // Conditional: expr ? expr : expr
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08002596 NameOnly, // Overload only, not allowed in expression.
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002597 // Below do not have operator names
2598 NamedCast, // Named cast, @<type>(expr)
2599 OfIdOp, // alignof, sizeof, typeid
2600
2601 Unnameable = NamedCast,
2602 };
2603 char Enc[2]; // Encoding
2604 OIKind Kind; // Kind of operator
2605 bool Flag : 1; // Entry-specific flag
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002606 Node::Prec Prec : 7; // Precedence
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002607 const char *Name; // Spelling
2608
2609 public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002610 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2611 const char *N)
2612 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002613
2614 public:
2615 bool operator<(const OperatorInfo &Other) const {
2616 return *this < Other.Enc;
2617 }
2618 bool operator<(const char *Peek) const {
2619 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2620 }
2621 bool operator==(const char *Peek) const {
2622 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2623 }
2624 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2625
2626 public:
2627 StringView getSymbol() const {
2628 StringView Res = Name;
2629 if (Kind < Unnameable) {
2630 assert(Res.startsWith("operator") &&
2631 "operator name does not start with 'operator'");
2632 Res = Res.dropFront(sizeof("operator") - 1);
2633 Res.consumeFront(' ');
2634 }
2635 return Res;
2636 }
2637 StringView getName() const { return Name; }
2638 OIKind getKind() const { return Kind; }
2639 bool getFlag() const { return Flag; }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002640 Node::Prec getPrecedence() const { return Prec; }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002641 };
Nathan Sidwell7d9bbeb2022-04-08 06:55:31 -07002642 static const OperatorInfo Ops[];
2643 static const size_t NumOps;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002644 const OperatorInfo *parseOperatorEncoding();
2645
Richard Smithc20d1442018-08-20 20:14:49 +00002646 /// Parse the <unresolved-name> production.
Nathan Sidwell77c52e22022-01-28 11:59:03 -08002647 Node *parseUnresolvedName(bool Global);
Richard Smithc20d1442018-08-20 20:14:49 +00002648 Node *parseSimpleId();
2649 Node *parseBaseUnresolvedName();
2650 Node *parseUnresolvedType();
2651 Node *parseDestructorName();
2652
2653 /// Top-level entry point into the parser.
2654 Node *parse();
2655};
2656
2657const char* parse_discriminator(const char* first, const char* last);
2658
2659// <name> ::= <nested-name> // N
2660// ::= <local-name> # See Scope Encoding below // Z
2661// ::= <unscoped-template-name> <template-args>
2662// ::= <unscoped-name>
2663//
2664// <unscoped-template-name> ::= <unscoped-name>
2665// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002666template <typename Derived, typename Alloc>
2667Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002668 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002669 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002670 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002671 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002672
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002673 Node *Result = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002674 bool IsSubst = false;
2675
2676 Result = getDerived().parseUnscopedName(State, &IsSubst);
2677 if (!Result)
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002678 return nullptr;
2679
2680 if (look() == 'I') {
2681 // ::= <unscoped-template-name> <template-args>
2682 if (!IsSubst)
2683 // An unscoped-template-name is substitutable.
2684 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00002685 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002686 if (TA == nullptr)
2687 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002688 if (State)
2689 State->EndsWithTemplateArgs = true;
2690 Result = make<NameWithTemplateArgs>(Result, TA);
2691 } else if (IsSubst) {
2692 // The substitution case must be followed by <template-args>.
2693 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002694 }
2695
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002696 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00002697}
2698
2699// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2700// := Z <function encoding> E s [<discriminator>]
2701// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002702template <typename Derived, typename Alloc>
2703Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002704 if (!consumeIf('Z'))
2705 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002706 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002707 if (Encoding == nullptr || !consumeIf('E'))
2708 return nullptr;
2709
2710 if (consumeIf('s')) {
2711 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002712 auto *StringLitName = make<NameType>("string literal");
2713 if (!StringLitName)
2714 return nullptr;
2715 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002716 }
2717
2718 if (consumeIf('d')) {
2719 parseNumber(true);
2720 if (!consumeIf('_'))
2721 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002722 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002723 if (N == nullptr)
2724 return nullptr;
2725 return make<LocalName>(Encoding, N);
2726 }
2727
Pavel Labathba825192018-10-16 14:29:14 +00002728 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002729 if (Entity == nullptr)
2730 return nullptr;
2731 First = parse_discriminator(First, Last);
2732 return make<LocalName>(Encoding, Entity);
2733}
2734
Nathan Sidwellac492da2022-04-05 09:25:47 -07002735// <unscoped-name> ::= <unqualified-name>
2736// ::= St <unqualified-name> # ::std::
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08002737// [*] extension
Pavel Labathba825192018-10-16 14:29:14 +00002738template <typename Derived, typename Alloc>
2739Node *
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002740AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2741 bool *IsSubst) {
2742
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002743 Node *Std = nullptr;
2744 if (consumeIf("St")) {
2745 Std = make<NameType>("std");
2746 if (Std == nullptr)
Nathan Sidwell200e97c2022-01-21 11:37:01 -08002747 return nullptr;
2748 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002749
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002750 Node *Res = nullptr;
2751 ModuleName *Module = nullptr;
2752 if (look() == 'S') {
2753 Node *S = getDerived().parseSubstitution();
2754 if (!S)
2755 return nullptr;
2756 if (S->getKind() == Node::KModuleName)
2757 Module = static_cast<ModuleName *>(S);
2758 else if (IsSubst && Std == nullptr) {
2759 Res = S;
2760 *IsSubst = true;
2761 } else {
2762 return nullptr;
2763 }
2764 }
2765
Nathan Sidwellac492da2022-04-05 09:25:47 -07002766 if (Res == nullptr || Std != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002767 Res = getDerived().parseUnqualifiedName(State, Std, Module);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002768 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002769
2770 return Res;
Richard Smithc20d1442018-08-20 20:14:49 +00002771}
2772
Nathan Sidwellac492da2022-04-05 09:25:47 -07002773// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002774// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
Nathan Sidwellac492da2022-04-05 09:25:47 -07002775// ::= [<module-name>] L? <source-name> [<abi-tags>]
2776// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002777// # structured binding declaration
Nathan Sidwellac492da2022-04-05 09:25:47 -07002778// ::= [<module-name>] L? DC <source-name>+ E
Pavel Labathba825192018-10-16 14:29:14 +00002779template <typename Derived, typename Alloc>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002780Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2781 NameState *State, Node *Scope, ModuleName *Module) {
2782 if (getDerived().parseModuleNameOpt(Module))
2783 return nullptr;
2784
Nathan Sidwellac492da2022-04-05 09:25:47 -07002785 consumeIf('L');
2786
Richard Smithc20d1442018-08-20 20:14:49 +00002787 Node *Result;
Nathan Sidwellac492da2022-04-05 09:25:47 -07002788 if (look() >= '1' && look() <= '9') {
Pavel Labathba825192018-10-16 14:29:14 +00002789 Result = getDerived().parseSourceName(State);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002790 } else if (look() == 'U') {
2791 Result = getDerived().parseUnnamedTypeName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002792 } else if (consumeIf("DC")) {
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002793 // Structured binding
Richard Smithc20d1442018-08-20 20:14:49 +00002794 size_t BindingsBegin = Names.size();
2795 do {
Pavel Labathba825192018-10-16 14:29:14 +00002796 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002797 if (Binding == nullptr)
2798 return nullptr;
2799 Names.push_back(Binding);
2800 } while (!consumeIf('E'));
2801 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002802 } else if (look() == 'C' || look() == 'D') {
2803 // A <ctor-dtor-name>.
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002804 if (Scope == nullptr || Module != nullptr)
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002805 return nullptr;
2806 Result = getDerived().parseCtorDtorName(Scope, State);
2807 } else {
Pavel Labathba825192018-10-16 14:29:14 +00002808 Result = getDerived().parseOperatorName(State);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002809 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002810
David Blaikie019fb1b2022-03-30 20:18:40 +00002811 if (Result != nullptr && Module != nullptr)
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002812 Result = make<ModuleEntity>(Module, Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002813 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002814 Result = getDerived().parseAbiTags(Result);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002815 if (Result != nullptr && Scope != nullptr)
2816 Result = make<NestedName>(Scope, Result);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002817
Richard Smithc20d1442018-08-20 20:14:49 +00002818 return Result;
2819}
2820
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002821// <module-name> ::= <module-subname>
2822// ::= <module-name> <module-subname>
2823// ::= <substitution> # passed in by caller
2824// <module-subname> ::= W <source-name>
2825// ::= W P <source-name>
2826template <typename Derived, typename Alloc>
2827bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2828 ModuleName *&Module) {
2829 while (consumeIf('W')) {
2830 bool IsPartition = consumeIf('P');
2831 Node *Sub = getDerived().parseSourceName(nullptr);
2832 if (!Sub)
2833 return true;
2834 Module =
2835 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2836 Subs.push_back(Module);
2837 }
2838
2839 return false;
2840}
2841
Richard Smithc20d1442018-08-20 20:14:49 +00002842// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2843// ::= <closure-type-name>
2844//
2845// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2846//
2847// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002848template <typename Derived, typename Alloc>
2849Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002850AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2851 // <template-params> refer to the innermost <template-args>. Clear out any
2852 // outer args that we may have inserted into TemplateParams.
2853 if (State != nullptr)
2854 TemplateParams.clear();
2855
Richard Smithc20d1442018-08-20 20:14:49 +00002856 if (consumeIf("Ut")) {
2857 StringView Count = parseNumber();
2858 if (!consumeIf('_'))
2859 return nullptr;
2860 return make<UnnamedTypeName>(Count);
2861 }
2862 if (consumeIf("Ul")) {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08002863 ScopedOverride<size_t> SwapParams(ParsingLambdaParamsAtLevel,
Richard Smithdf1c14c2019-09-06 23:53:21 +00002864 TemplateParams.size());
2865 ScopedTemplateParamList LambdaTemplateParams(this);
2866
2867 size_t ParamsBegin = Names.size();
2868 while (look() == 'T' &&
2869 StringView("yptn").find(look(1)) != StringView::npos) {
2870 Node *T = parseTemplateParamDecl();
2871 if (!T)
2872 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002873 Names.push_back(T);
2874 }
2875 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2876
2877 // FIXME: If TempParams is empty and none of the function parameters
2878 // includes 'auto', we should remove LambdaTemplateParams from the
2879 // TemplateParams list. Unfortunately, we don't find out whether there are
2880 // any 'auto' parameters until too late in an example such as:
2881 //
2882 // template<typename T> void f(
2883 // decltype([](decltype([]<typename T>(T v) {}),
2884 // auto) {})) {}
2885 // template<typename T> void f(
2886 // decltype([](decltype([]<typename T>(T w) {}),
2887 // int) {})) {}
2888 //
2889 // Here, the type of v is at level 2 but the type of w is at level 1. We
2890 // don't find this out until we encounter the type of the next parameter.
2891 //
2892 // However, compilers can't actually cope with the former example in
2893 // practice, and it's likely to be made ill-formed in future, so we don't
2894 // need to support it here.
2895 //
2896 // If we encounter an 'auto' in the function parameter types, we will
2897 // recreate a template parameter scope for it, but any intervening lambdas
2898 // will be parsed in the 'wrong' template parameter depth.
2899 if (TempParams.empty())
2900 TemplateParams.pop_back();
2901
Richard Smithc20d1442018-08-20 20:14:49 +00002902 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002903 do {
Pavel Labathba825192018-10-16 14:29:14 +00002904 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002905 if (P == nullptr)
2906 return nullptr;
2907 Names.push_back(P);
2908 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002909 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002910 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2911
Richard Smithc20d1442018-08-20 20:14:49 +00002912 StringView Count = parseNumber();
2913 if (!consumeIf('_'))
2914 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002915 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002916 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002917 if (consumeIf("Ub")) {
2918 (void)parseNumber();
2919 if (!consumeIf('_'))
2920 return nullptr;
2921 return make<NameType>("'block-literal'");
2922 }
Richard Smithc20d1442018-08-20 20:14:49 +00002923 return nullptr;
2924}
2925
2926// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002927template <typename Derived, typename Alloc>
2928Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002929 size_t Length = 0;
2930 if (parsePositiveInteger(&Length))
2931 return nullptr;
2932 if (numLeft() < Length || Length == 0)
2933 return nullptr;
2934 StringView Name(First, First + Length);
2935 First += Length;
2936 if (Name.startsWith("_GLOBAL__N"))
2937 return make<NameType>("(anonymous namespace)");
2938 return make<NameType>(Name);
2939}
2940
Nathan Sidwell7d9bbeb2022-04-08 06:55:31 -07002941// Operator encodings
2942template <typename Derived, typename Alloc>
2943const typename AbstractManglingParser<
2944 Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,
2945 Alloc>::Ops[] = {
2946 // Keep ordered by encoding
2947 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
2948 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
2949 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
2950 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
2951 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
2952 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},
2953 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
2954 "operator co_await"},
2955 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},
2956 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
2957 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
2958 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
2959 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
2960 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast
2961 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
2962 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
2963 "operator delete[]"},
2964 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},
2965 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
2966 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
2967 "operator delete"},
2968 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2969 "operator.*"},
2970 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
2971 "operator."},
2972 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
2973 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
2974 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
2975 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
2976 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
2977 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
2978 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
2979 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
2980 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
2981 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
2982 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
2983 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
2984 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
2985 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
2986 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
2987 "operator*"},
2988 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
2989 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
2990 "operator new[]"},
2991 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
2992 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
2993 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
2994 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},
2995 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
2996 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
2997 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
2998 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
2999 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
3000 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3001 "operator->*"},
3002 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
3003 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
3004 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
3005 "operator->"},
3006 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
3007 "operator?"},
3008 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
3009 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
3010 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3011 "reinterpret_cast"},
3012 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3013 "operator%"},
3014 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3015 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},
3016 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3017 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3018 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},
3019 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3020 "typeid "},
3021 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
3022};
3023template <typename Derived, typename Alloc>
3024const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /
3025 sizeof(Ops[0]);
3026
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003027// If the next 2 chars are an operator encoding, consume them and return their
3028// OperatorInfo. Otherwise return nullptr.
3029template <typename Derived, typename Alloc>
3030const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
3031AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003032 if (numLeft() < 2)
3033 return nullptr;
3034
Nathan Sidwell519e9ef2022-10-20 07:10:47 -04003035 // We can't use lower_bound as that can link to symbols in the C++ library,
3036 // and this must remain independant of that.
3037 size_t lower = 0u, upper = NumOps - 1; // Inclusive bounds.
3038 while (upper != lower) {
3039 size_t middle = (upper + lower) / 2;
3040 if (Ops[middle] < First)
3041 lower = middle + 1;
3042 else
3043 upper = middle;
3044 }
3045 if (Ops[lower] != First)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003046 return nullptr;
3047
3048 First += 2;
Nathan Sidwell519e9ef2022-10-20 07:10:47 -04003049 return &Ops[lower];
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003050}
3051
3052// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003053// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003054// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003055template <typename Derived, typename Alloc>
3056Node *
3057AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003058 if (const auto *Op = parseOperatorEncoding()) {
3059 if (Op->getKind() == OperatorInfo::CCast) {
3060 // ::= cv <type> # (cast)
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003061 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);
Richard Smithc20d1442018-08-20 20:14:49 +00003062 // If we're parsing an encoding, State != nullptr and the conversion
3063 // operators' <type> could have a <template-param> that refers to some
3064 // <template-arg>s further ahead in the mangled name.
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003065 ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,
Richard Smithc20d1442018-08-20 20:14:49 +00003066 PermitForwardTemplateReferences ||
3067 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003068 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003069 if (Ty == nullptr)
3070 return nullptr;
3071 if (State) State->CtorDtorConversion = true;
3072 return make<ConversionOperatorType>(Ty);
3073 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003074
3075 if (Op->getKind() >= OperatorInfo::Unnameable)
3076 /* Not a nameable operator. */
3077 return nullptr;
3078 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3079 /* Not a nameable MemberExpr */
3080 return nullptr;
3081
3082 return make<NameType>(Op->getName());
3083 }
3084
3085 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003086 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003087 Node *SN = getDerived().parseSourceName(State);
3088 if (SN == nullptr)
3089 return nullptr;
3090 return make<LiteralOperator>(SN);
3091 }
3092
3093 if (consumeIf('v')) {
3094 // ::= v <digit> <source-name> # vendor extended operator
3095 if (look() >= '0' && look() <= '9') {
3096 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003097 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003098 if (SN == nullptr)
3099 return nullptr;
3100 return make<ConversionOperatorType>(SN);
3101 }
3102 return nullptr;
3103 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003104
Richard Smithc20d1442018-08-20 20:14:49 +00003105 return nullptr;
3106}
3107
3108// <ctor-dtor-name> ::= C1 # complete object constructor
3109// ::= C2 # base object constructor
3110// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003111// extension ::= C4 # gcc old-style "[unified]" constructor
3112// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003113// ::= D0 # deleting destructor
3114// ::= D1 # complete object destructor
3115// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003116// extension ::= D4 # gcc old-style "[unified]" destructor
3117// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003118template <typename Derived, typename Alloc>
3119Node *
3120AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3121 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003122 if (SoFar->getKind() == Node::KSpecialSubstitution) {
Nathan Sidwell28201492022-03-28 12:55:45 -07003123 // Expand the special substitution.
3124 SoFar = make<ExpandedSpecialSubstitution>(
3125 static_cast<SpecialSubstitution *>(SoFar));
3126 if (!SoFar)
3127 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003128 }
3129
3130 if (consumeIf('C')) {
3131 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003132 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3133 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003134 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003135 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003136 ++First;
3137 if (State) State->CtorDtorConversion = true;
3138 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003139 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003140 return nullptr;
3141 }
Nico Weber29294792019-04-03 23:14:33 +00003142 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003143 }
3144
Nico Weber29294792019-04-03 23:14:33 +00003145 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3146 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003147 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003148 First += 2;
3149 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003150 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003151 }
3152
3153 return nullptr;
3154}
3155
Nathan Sidwellac492da2022-04-05 09:25:47 -07003156// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3157// <unqualified-name> E
3158// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3159// <template-args> E
Richard Smithc20d1442018-08-20 20:14:49 +00003160//
Nathan Sidwellac492da2022-04-05 09:25:47 -07003161// <prefix> ::= <prefix> <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003162// ::= <template-prefix> <template-args>
3163// ::= <template-param>
3164// ::= <decltype>
3165// ::= # empty
3166// ::= <substitution>
3167// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003168// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003169//
3170// <data-member-prefix> := <member source-name> [<template-args>] M
3171//
3172// <template-prefix> ::= <prefix> <template unqualified-name>
3173// ::= <template-param>
3174// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003175template <typename Derived, typename Alloc>
3176Node *
3177AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003178 if (!consumeIf('N'))
3179 return nullptr;
3180
3181 Qualifiers CVTmp = parseCVQualifiers();
3182 if (State) State->CVQualifiers = CVTmp;
3183
3184 if (consumeIf('O')) {
3185 if (State) State->ReferenceQualifier = FrefQualRValue;
3186 } else if (consumeIf('R')) {
3187 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003188 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003189 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003190 }
Richard Smithc20d1442018-08-20 20:14:49 +00003191
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003192 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003193 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003194 if (State)
3195 // Only set end-with-template on the case that does that.
3196 State->EndsWithTemplateArgs = false;
3197
Richard Smithc20d1442018-08-20 20:14:49 +00003198 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003199 // ::= <template-param>
3200 if (SoFar != nullptr)
3201 return nullptr; // Cannot have a prefix.
3202 SoFar = getDerived().parseTemplateParam();
3203 } else if (look() == 'I') {
3204 // ::= <template-prefix> <template-args>
3205 if (SoFar == nullptr)
3206 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003207 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003208 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003209 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003210 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3211 // Semantically <template-args> <template-args> cannot be generated by a
3212 // C++ entity. There will always be [something like] a name between
3213 // them.
3214 return nullptr;
3215 if (State)
3216 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003217 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003218 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3219 // ::= <decltype>
3220 if (SoFar != nullptr)
3221 return nullptr; // Cannot have a prefix.
3222 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003223 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003224 ModuleName *Module = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003225
3226 if (look() == 'S') {
3227 // ::= <substitution>
3228 Node *S = nullptr;
3229 if (look(1) == 't') {
3230 First += 2;
3231 S = make<NameType>("std");
3232 } else {
3233 S = getDerived().parseSubstitution();
3234 }
3235 if (!S)
3236 return nullptr;
3237 if (S->getKind() == Node::KModuleName) {
3238 Module = static_cast<ModuleName *>(S);
Nathan Sidwellac492da2022-04-05 09:25:47 -07003239 } else if (SoFar != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003240 return nullptr; // Cannot have a prefix.
3241 } else {
3242 SoFar = S;
3243 continue; // Do not push a new substitution.
3244 }
3245 }
3246
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003247 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003248 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003249 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003250
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003251 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003252 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003253 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003254
3255 // No longer used.
3256 // <data-member-prefix> := <member source-name> [<template-args>] M
3257 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003258 }
3259
3260 if (SoFar == nullptr || Subs.empty())
3261 return nullptr;
3262
3263 Subs.pop_back();
3264 return SoFar;
3265}
3266
3267// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003268template <typename Derived, typename Alloc>
3269Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3270 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003271 if (SN == nullptr)
3272 return nullptr;
3273 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003274 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003275 if (TA == nullptr)
3276 return nullptr;
3277 return make<NameWithTemplateArgs>(SN, TA);
3278 }
3279 return SN;
3280}
3281
3282// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3283// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003284template <typename Derived, typename Alloc>
3285Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003286 Node *Result;
3287 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003288 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003289 else
Pavel Labathba825192018-10-16 14:29:14 +00003290 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003291 if (Result == nullptr)
3292 return nullptr;
3293 return make<DtorName>(Result);
3294}
3295
3296// <unresolved-type> ::= <template-param>
3297// ::= <decltype>
3298// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003299template <typename Derived, typename Alloc>
3300Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003301 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003302 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003303 if (TP == nullptr)
3304 return nullptr;
3305 Subs.push_back(TP);
3306 return TP;
3307 }
3308 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003309 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003310 if (DT == nullptr)
3311 return nullptr;
3312 Subs.push_back(DT);
3313 return DT;
3314 }
Pavel Labathba825192018-10-16 14:29:14 +00003315 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003316}
3317
3318// <base-unresolved-name> ::= <simple-id> # unresolved name
3319// extension ::= <operator-name> # unresolved operator-function-id
3320// extension ::= <operator-name> <template-args> # unresolved operator template-id
3321// ::= on <operator-name> # unresolved operator-function-id
3322// ::= on <operator-name> <template-args> # unresolved operator template-id
3323// ::= dn <destructor-name> # destructor or pseudo-destructor;
3324// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003325template <typename Derived, typename Alloc>
3326Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003327 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003328 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003329
3330 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003331 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003332
3333 consumeIf("on");
3334
Pavel Labathba825192018-10-16 14:29:14 +00003335 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003336 if (Oper == nullptr)
3337 return nullptr;
3338 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003339 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003340 if (TA == nullptr)
3341 return nullptr;
3342 return make<NameWithTemplateArgs>(Oper, TA);
3343 }
3344 return Oper;
3345}
3346
3347// <unresolved-name>
3348// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3349// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3350// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3351// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003352// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003353// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3354// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3355// # T::N::x /decltype(p)::N::x
3356// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3357//
3358// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003359template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003360Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003361 Node *SoFar = nullptr;
3362
3363 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3364 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3365 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003366 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003367 if (SoFar == nullptr)
3368 return nullptr;
3369
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 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003375 if (!SoFar)
3376 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003377 }
3378
3379 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003380 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003381 if (Qual == nullptr)
3382 return nullptr;
3383 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003384 if (!SoFar)
3385 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003386 }
3387
Pavel Labathba825192018-10-16 14:29:14 +00003388 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003389 if (Base == nullptr)
3390 return nullptr;
3391 return make<QualifiedName>(SoFar, Base);
3392 }
3393
Richard Smithc20d1442018-08-20 20:14:49 +00003394 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3395 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003396 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003397 if (SoFar == nullptr)
3398 return nullptr;
3399 if (Global)
3400 SoFar = make<GlobalQualifiedName>(SoFar);
3401 return SoFar;
3402 }
3403
3404 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3405 if (std::isdigit(look())) {
3406 do {
Pavel Labathba825192018-10-16 14:29:14 +00003407 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003408 if (Qual == nullptr)
3409 return nullptr;
3410 if (SoFar)
3411 SoFar = make<QualifiedName>(SoFar, Qual);
3412 else if (Global)
3413 SoFar = make<GlobalQualifiedName>(Qual);
3414 else
3415 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003416 if (!SoFar)
3417 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003418 } while (!consumeIf('E'));
3419 }
3420 // sr <unresolved-type> <base-unresolved-name>
3421 // sr <unresolved-type> <template-args> <base-unresolved-name>
3422 else {
Pavel Labathba825192018-10-16 14:29:14 +00003423 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003424 if (SoFar == nullptr)
3425 return nullptr;
3426
3427 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003428 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003429 if (TA == nullptr)
3430 return nullptr;
3431 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003432 if (!SoFar)
3433 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003434 }
3435 }
3436
3437 assert(SoFar != nullptr);
3438
Pavel Labathba825192018-10-16 14:29:14 +00003439 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003440 if (Base == nullptr)
3441 return nullptr;
3442 return make<QualifiedName>(SoFar, Base);
3443}
3444
3445// <abi-tags> ::= <abi-tag> [<abi-tags>]
3446// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003447template <typename Derived, typename Alloc>
3448Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003449 while (consumeIf('B')) {
3450 StringView SN = parseBareSourceName();
3451 if (SN.empty())
3452 return nullptr;
3453 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003454 if (!N)
3455 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003456 }
3457 return N;
3458}
3459
3460// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003461template <typename Alloc, typename Derived>
3462StringView
3463AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003464 const char *Tmp = First;
3465 if (AllowNegative)
3466 consumeIf('n');
3467 if (numLeft() == 0 || !std::isdigit(*First))
3468 return StringView();
3469 while (numLeft() != 0 && std::isdigit(*First))
3470 ++First;
3471 return StringView(Tmp, First);
3472}
3473
3474// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003475template <typename Alloc, typename Derived>
3476bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003477 *Out = 0;
3478 if (look() < '0' || look() > '9')
3479 return true;
3480 while (look() >= '0' && look() <= '9') {
3481 *Out *= 10;
3482 *Out += static_cast<size_t>(consume() - '0');
3483 }
3484 return false;
3485}
3486
Pavel Labathba825192018-10-16 14:29:14 +00003487template <typename Alloc, typename Derived>
3488StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003489 size_t Int = 0;
3490 if (parsePositiveInteger(&Int) || numLeft() < Int)
3491 return StringView();
3492 StringView R(First, First + Int);
3493 First += Int;
3494 return R;
3495}
3496
3497// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3498//
3499// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3500// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3501// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3502//
3503// <ref-qualifier> ::= R # & ref-qualifier
3504// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003505template <typename Derived, typename Alloc>
3506Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003507 Qualifiers CVQuals = parseCVQualifiers();
3508
3509 Node *ExceptionSpec = nullptr;
3510 if (consumeIf("Do")) {
3511 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003512 if (!ExceptionSpec)
3513 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003514 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003515 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003516 if (E == nullptr || !consumeIf('E'))
3517 return nullptr;
3518 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003519 if (!ExceptionSpec)
3520 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003521 } else if (consumeIf("Dw")) {
3522 size_t SpecsBegin = Names.size();
3523 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003524 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003525 if (T == nullptr)
3526 return nullptr;
3527 Names.push_back(T);
3528 }
3529 ExceptionSpec =
3530 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003531 if (!ExceptionSpec)
3532 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003533 }
3534
3535 consumeIf("Dx"); // transaction safe
3536
3537 if (!consumeIf('F'))
3538 return nullptr;
3539 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003540 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003541 if (ReturnType == nullptr)
3542 return nullptr;
3543
3544 FunctionRefQual ReferenceQualifier = FrefQualNone;
3545 size_t ParamsBegin = Names.size();
3546 while (true) {
3547 if (consumeIf('E'))
3548 break;
3549 if (consumeIf('v'))
3550 continue;
3551 if (consumeIf("RE")) {
3552 ReferenceQualifier = FrefQualLValue;
3553 break;
3554 }
3555 if (consumeIf("OE")) {
3556 ReferenceQualifier = FrefQualRValue;
3557 break;
3558 }
Pavel Labathba825192018-10-16 14:29:14 +00003559 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003560 if (T == nullptr)
3561 return nullptr;
3562 Names.push_back(T);
3563 }
3564
3565 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3566 return make<FunctionType>(ReturnType, Params, CVQuals,
3567 ReferenceQualifier, ExceptionSpec);
3568}
3569
3570// extension:
3571// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3572// ::= Dv [<dimension expression>] _ <element type>
3573// <extended element type> ::= <element type>
3574// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003575template <typename Derived, typename Alloc>
3576Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003577 if (!consumeIf("Dv"))
3578 return nullptr;
3579 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003580 Node *DimensionNumber = make<NameType>(parseNumber());
3581 if (!DimensionNumber)
3582 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003583 if (!consumeIf('_'))
3584 return nullptr;
3585 if (consumeIf('p'))
3586 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003587 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003588 if (ElemType == nullptr)
3589 return nullptr;
3590 return make<VectorType>(ElemType, DimensionNumber);
3591 }
3592
3593 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003594 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003595 if (!DimExpr)
3596 return nullptr;
3597 if (!consumeIf('_'))
3598 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003599 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003600 if (!ElemType)
3601 return nullptr;
3602 return make<VectorType>(ElemType, DimExpr);
3603 }
Pavel Labathba825192018-10-16 14:29:14 +00003604 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003605 if (!ElemType)
3606 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003607 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003608}
3609
3610// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3611// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003612template <typename Derived, typename Alloc>
3613Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003614 if (!consumeIf('D'))
3615 return nullptr;
3616 if (!consumeIf('t') && !consumeIf('T'))
3617 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003618 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003619 if (E == nullptr)
3620 return nullptr;
3621 if (!consumeIf('E'))
3622 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003623 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003624}
3625
3626// <array-type> ::= A <positive dimension number> _ <element type>
3627// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003628template <typename Derived, typename Alloc>
3629Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003630 if (!consumeIf('A'))
3631 return nullptr;
3632
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003633 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003634
Richard Smithc20d1442018-08-20 20:14:49 +00003635 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003636 Dimension = make<NameType>(parseNumber());
3637 if (!Dimension)
3638 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003639 if (!consumeIf('_'))
3640 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003641 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003642 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003643 if (DimExpr == nullptr)
3644 return nullptr;
3645 if (!consumeIf('_'))
3646 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003647 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003648 }
3649
Pavel Labathba825192018-10-16 14:29:14 +00003650 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003651 if (Ty == nullptr)
3652 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003653 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003654}
3655
3656// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003657template <typename Derived, typename Alloc>
3658Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003659 if (!consumeIf('M'))
3660 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003661 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003662 if (ClassType == nullptr)
3663 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003664 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003665 if (MemberType == nullptr)
3666 return nullptr;
3667 return make<PointerToMemberType>(ClassType, MemberType);
3668}
3669
3670// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3671// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3672// ::= Tu <name> # dependent elaborated type specifier using 'union'
3673// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003674template <typename Derived, typename Alloc>
3675Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003676 StringView ElabSpef;
3677 if (consumeIf("Ts"))
3678 ElabSpef = "struct";
3679 else if (consumeIf("Tu"))
3680 ElabSpef = "union";
3681 else if (consumeIf("Te"))
3682 ElabSpef = "enum";
3683
Pavel Labathba825192018-10-16 14:29:14 +00003684 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003685 if (Name == nullptr)
3686 return nullptr;
3687
3688 if (!ElabSpef.empty())
3689 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3690
3691 return Name;
3692}
3693
3694// <qualified-type> ::= <qualifiers> <type>
3695// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3696// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003697template <typename Derived, typename Alloc>
3698Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003699 if (consumeIf('U')) {
3700 StringView Qual = parseBareSourceName();
3701 if (Qual.empty())
3702 return nullptr;
3703
Richard Smithc20d1442018-08-20 20:14:49 +00003704 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3705 if (Qual.startsWith("objcproto")) {
3706 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3707 StringView Proto;
3708 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003709 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()),
3710 SaveLast(Last, ProtoSourceName.end());
Richard Smithc20d1442018-08-20 20:14:49 +00003711 Proto = parseBareSourceName();
3712 }
3713 if (Proto.empty())
3714 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003715 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003716 if (Child == nullptr)
3717 return nullptr;
3718 return make<ObjCProtoName>(Child, Proto);
3719 }
3720
Alex Orlovf50df922021-03-24 10:21:32 +04003721 Node *TA = nullptr;
3722 if (look() == 'I') {
3723 TA = getDerived().parseTemplateArgs();
3724 if (TA == nullptr)
3725 return nullptr;
3726 }
3727
Pavel Labathba825192018-10-16 14:29:14 +00003728 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003729 if (Child == nullptr)
3730 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003731 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003732 }
3733
3734 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003735 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003736 if (Ty == nullptr)
3737 return nullptr;
3738 if (Quals != QualNone)
3739 Ty = make<QualType>(Ty, Quals);
3740 return Ty;
3741}
3742
3743// <type> ::= <builtin-type>
3744// ::= <qualified-type>
3745// ::= <function-type>
3746// ::= <class-enum-type>
3747// ::= <array-type>
3748// ::= <pointer-to-member-type>
3749// ::= <template-param>
3750// ::= <template-template-param> <template-args>
3751// ::= <decltype>
3752// ::= P <type> # pointer
3753// ::= R <type> # l-value reference
3754// ::= O <type> # r-value reference (C++11)
3755// ::= C <type> # complex pair (C99)
3756// ::= G <type> # imaginary (C99)
3757// ::= <substitution> # See Compression below
3758// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3759// extension ::= <vector-type> # <vector-type> starts with Dv
3760//
3761// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3762// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003763template <typename Derived, typename Alloc>
3764Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003765 Node *Result = nullptr;
3766
Richard Smithc20d1442018-08-20 20:14:49 +00003767 switch (look()) {
3768 // ::= <qualified-type>
3769 case 'r':
3770 case 'V':
3771 case 'K': {
3772 unsigned AfterQuals = 0;
3773 if (look(AfterQuals) == 'r') ++AfterQuals;
3774 if (look(AfterQuals) == 'V') ++AfterQuals;
3775 if (look(AfterQuals) == 'K') ++AfterQuals;
3776
3777 if (look(AfterQuals) == 'F' ||
3778 (look(AfterQuals) == 'D' &&
3779 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3780 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003781 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003782 break;
3783 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003784 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003785 }
3786 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003787 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003788 break;
3789 }
3790 // <builtin-type> ::= v # void
3791 case 'v':
3792 ++First;
3793 return make<NameType>("void");
3794 // ::= w # wchar_t
3795 case 'w':
3796 ++First;
3797 return make<NameType>("wchar_t");
3798 // ::= b # bool
3799 case 'b':
3800 ++First;
3801 return make<NameType>("bool");
3802 // ::= c # char
3803 case 'c':
3804 ++First;
3805 return make<NameType>("char");
3806 // ::= a # signed char
3807 case 'a':
3808 ++First;
3809 return make<NameType>("signed char");
3810 // ::= h # unsigned char
3811 case 'h':
3812 ++First;
3813 return make<NameType>("unsigned char");
3814 // ::= s # short
3815 case 's':
3816 ++First;
3817 return make<NameType>("short");
3818 // ::= t # unsigned short
3819 case 't':
3820 ++First;
3821 return make<NameType>("unsigned short");
3822 // ::= i # int
3823 case 'i':
3824 ++First;
3825 return make<NameType>("int");
3826 // ::= j # unsigned int
3827 case 'j':
3828 ++First;
3829 return make<NameType>("unsigned int");
3830 // ::= l # long
3831 case 'l':
3832 ++First;
3833 return make<NameType>("long");
3834 // ::= m # unsigned long
3835 case 'm':
3836 ++First;
3837 return make<NameType>("unsigned long");
3838 // ::= x # long long, __int64
3839 case 'x':
3840 ++First;
3841 return make<NameType>("long long");
3842 // ::= y # unsigned long long, __int64
3843 case 'y':
3844 ++First;
3845 return make<NameType>("unsigned long long");
3846 // ::= n # __int128
3847 case 'n':
3848 ++First;
3849 return make<NameType>("__int128");
3850 // ::= o # unsigned __int128
3851 case 'o':
3852 ++First;
3853 return make<NameType>("unsigned __int128");
3854 // ::= f # float
3855 case 'f':
3856 ++First;
3857 return make<NameType>("float");
3858 // ::= d # double
3859 case 'd':
3860 ++First;
3861 return make<NameType>("double");
3862 // ::= e # long double, __float80
3863 case 'e':
3864 ++First;
3865 return make<NameType>("long double");
3866 // ::= g # __float128
3867 case 'g':
3868 ++First;
3869 return make<NameType>("__float128");
3870 // ::= z # ellipsis
3871 case 'z':
3872 ++First;
3873 return make<NameType>("...");
3874
3875 // <builtin-type> ::= u <source-name> # vendor extended type
3876 case 'u': {
3877 ++First;
3878 StringView Res = parseBareSourceName();
3879 if (Res.empty())
3880 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003881 // Typically, <builtin-type>s are not considered substitution candidates,
3882 // but the exception to that exception is vendor extended types (Itanium C++
3883 // ABI 5.9.1).
3884 Result = make<NameType>(Res);
3885 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003886 }
3887 case 'D':
3888 switch (look(1)) {
3889 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3890 case 'd':
3891 First += 2;
3892 return make<NameType>("decimal64");
3893 // ::= De # IEEE 754r decimal floating point (128 bits)
3894 case 'e':
3895 First += 2;
3896 return make<NameType>("decimal128");
3897 // ::= Df # IEEE 754r decimal floating point (32 bits)
3898 case 'f':
3899 First += 2;
3900 return make<NameType>("decimal32");
3901 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3902 case 'h':
3903 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003904 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003905 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3906 case 'F': {
3907 First += 2;
3908 Node *DimensionNumber = make<NameType>(parseNumber());
3909 if (!DimensionNumber)
3910 return nullptr;
3911 if (!consumeIf('_'))
3912 return nullptr;
3913 return make<BinaryFPType>(DimensionNumber);
3914 }
Senran Zhange025ba52022-03-27 00:04:23 +08003915 // ::= DB <number> _ # C23 signed _BitInt(N)
3916 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
3917 // ::= DU <number> _ # C23 unsigned _BitInt(N)
3918 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
3919 case 'B':
3920 case 'U': {
3921 bool Signed = look(1) == 'B';
3922 First += 2;
3923 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())
3924 : getDerived().parseExpr();
3925 if (!Size)
3926 return nullptr;
3927 if (!consumeIf('_'))
3928 return nullptr;
3929 return make<BitIntType>(Size, Signed);
3930 }
Richard Smithc20d1442018-08-20 20:14:49 +00003931 // ::= Di # char32_t
3932 case 'i':
3933 First += 2;
3934 return make<NameType>("char32_t");
3935 // ::= Ds # char16_t
3936 case 's':
3937 First += 2;
3938 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003939 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3940 case 'u':
3941 First += 2;
3942 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003943 // ::= Da # auto (in dependent new-expressions)
3944 case 'a':
3945 First += 2;
3946 return make<NameType>("auto");
3947 // ::= Dc # decltype(auto)
3948 case 'c':
3949 First += 2;
3950 return make<NameType>("decltype(auto)");
3951 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3952 case 'n':
3953 First += 2;
3954 return make<NameType>("std::nullptr_t");
3955
3956 // ::= <decltype>
3957 case 't':
3958 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003959 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003960 break;
3961 }
3962 // extension ::= <vector-type> # <vector-type> starts with Dv
3963 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003964 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003965 break;
3966 }
3967 // ::= Dp <type> # pack expansion (C++0x)
3968 case 'p': {
3969 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003970 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003971 if (!Child)
3972 return nullptr;
3973 Result = make<ParameterPackExpansion>(Child);
3974 break;
3975 }
3976 // Exception specifier on a function type.
3977 case 'o':
3978 case 'O':
3979 case 'w':
3980 // Transaction safe function type.
3981 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003982 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003983 break;
3984 }
3985 break;
3986 // ::= <function-type>
3987 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003988 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003989 break;
3990 }
3991 // ::= <array-type>
3992 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003993 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003994 break;
3995 }
3996 // ::= <pointer-to-member-type>
3997 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003998 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003999 break;
4000 }
4001 // ::= <template-param>
4002 case 'T': {
4003 // This could be an elaborate type specifier on a <class-enum-type>.
4004 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00004005 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004006 break;
4007 }
4008
Pavel Labathba825192018-10-16 14:29:14 +00004009 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004010 if (Result == nullptr)
4011 return nullptr;
4012
4013 // Result could be either of:
4014 // <type> ::= <template-param>
4015 // <type> ::= <template-template-param> <template-args>
4016 //
4017 // <template-template-param> ::= <template-param>
4018 // ::= <substitution>
4019 //
4020 // If this is followed by some <template-args>, and we're permitted to
4021 // parse them, take the second production.
4022
4023 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004024 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004025 if (TA == nullptr)
4026 return nullptr;
4027 Result = make<NameWithTemplateArgs>(Result, TA);
4028 }
4029 break;
4030 }
4031 // ::= P <type> # pointer
4032 case 'P': {
4033 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004034 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004035 if (Ptr == nullptr)
4036 return nullptr;
4037 Result = make<PointerType>(Ptr);
4038 break;
4039 }
4040 // ::= R <type> # l-value reference
4041 case 'R': {
4042 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004043 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004044 if (Ref == nullptr)
4045 return nullptr;
4046 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4047 break;
4048 }
4049 // ::= O <type> # r-value reference (C++11)
4050 case 'O': {
4051 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004052 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004053 if (Ref == nullptr)
4054 return nullptr;
4055 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4056 break;
4057 }
4058 // ::= C <type> # complex pair (C99)
4059 case 'C': {
4060 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004061 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004062 if (P == nullptr)
4063 return nullptr;
4064 Result = make<PostfixQualifiedType>(P, " complex");
4065 break;
4066 }
4067 // ::= G <type> # imaginary (C99)
4068 case 'G': {
4069 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004070 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004071 if (P == nullptr)
4072 return P;
4073 Result = make<PostfixQualifiedType>(P, " imaginary");
4074 break;
4075 }
4076 // ::= <substitution> # See Compression below
4077 case 'S': {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004078 if (look(1) != 't') {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004079 bool IsSubst = false;
4080 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4081 if (!Result)
Richard Smithc20d1442018-08-20 20:14:49 +00004082 return nullptr;
4083
4084 // Sub could be either of:
4085 // <type> ::= <substitution>
4086 // <type> ::= <template-template-param> <template-args>
4087 //
4088 // <template-template-param> ::= <template-param>
4089 // ::= <substitution>
4090 //
4091 // If this is followed by some <template-args>, and we're permitted to
4092 // parse them, take the second production.
4093
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004094 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4095 if (!IsSubst)
4096 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00004097 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004098 if (TA == nullptr)
4099 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004100 Result = make<NameWithTemplateArgs>(Result, TA);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004101 } else if (IsSubst) {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004102 // If all we parsed was a substitution, don't re-insert into the
4103 // substitution table.
4104 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00004105 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004106 break;
Richard Smithc20d1442018-08-20 20:14:49 +00004107 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004108 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004109 }
4110 // ::= <class-enum-type>
4111 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004112 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004113 break;
4114 }
4115 }
4116
4117 // If we parsed a type, insert it into the substitution table. Note that all
4118 // <builtin-type>s and <substitution>s have already bailed out, because they
4119 // don't get substitutions.
4120 if (Result != nullptr)
4121 Subs.push_back(Result);
4122 return Result;
4123}
4124
Pavel Labathba825192018-10-16 14:29:14 +00004125template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004126Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4127 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004128 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004129 if (E == nullptr)
4130 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004131 return make<PrefixExpr>(Kind, E, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004132}
4133
Pavel Labathba825192018-10-16 14:29:14 +00004134template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004135Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4136 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004137 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004138 if (LHS == nullptr)
4139 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004140 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004141 if (RHS == nullptr)
4142 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004143 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004144}
4145
Pavel Labathba825192018-10-16 14:29:14 +00004146template <typename Derived, typename Alloc>
4147Node *
4148AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004149 StringView Tmp = parseNumber(true);
4150 if (!Tmp.empty() && consumeIf('E'))
4151 return make<IntegerLiteral>(Lit, Tmp);
4152 return nullptr;
4153}
4154
4155// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004156template <typename Alloc, typename Derived>
4157Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004158 Qualifiers CVR = QualNone;
4159 if (consumeIf('r'))
4160 CVR |= QualRestrict;
4161 if (consumeIf('V'))
4162 CVR |= QualVolatile;
4163 if (consumeIf('K'))
4164 CVR |= QualConst;
4165 return CVR;
4166}
4167
4168// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4169// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4170// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4171// ::= 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 -04004172// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004173template <typename Derived, typename Alloc>
4174Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004175 if (consumeIf("fpT"))
4176 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004177 if (consumeIf("fp")) {
4178 parseCVQualifiers();
4179 StringView Num = parseNumber();
4180 if (!consumeIf('_'))
4181 return nullptr;
4182 return make<FunctionParam>(Num);
4183 }
4184 if (consumeIf("fL")) {
4185 if (parseNumber().empty())
4186 return nullptr;
4187 if (!consumeIf('p'))
4188 return nullptr;
4189 parseCVQualifiers();
4190 StringView Num = parseNumber();
4191 if (!consumeIf('_'))
4192 return nullptr;
4193 return make<FunctionParam>(Num);
4194 }
4195 return nullptr;
4196}
4197
Richard Smithc20d1442018-08-20 20:14:49 +00004198// cv <type> <expression> # conversion with one argument
4199// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004200template <typename Derived, typename Alloc>
4201Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004202 if (!consumeIf("cv"))
4203 return nullptr;
4204 Node *Ty;
4205 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004206 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004207 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004208 }
4209
4210 if (Ty == nullptr)
4211 return nullptr;
4212
4213 if (consumeIf('_')) {
4214 size_t ExprsBegin = Names.size();
4215 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004216 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004217 if (E == nullptr)
4218 return E;
4219 Names.push_back(E);
4220 }
4221 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4222 return make<ConversionExpr>(Ty, Exprs);
4223 }
4224
Pavel Labathba825192018-10-16 14:29:14 +00004225 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004226 if (E[0] == nullptr)
4227 return nullptr;
4228 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4229}
4230
4231// <expr-primary> ::= L <type> <value number> E # integer literal
4232// ::= L <type> <value float> E # floating literal
4233// ::= L <string type> E # string literal
4234// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004235// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004236// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4237// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004238template <typename Derived, typename Alloc>
4239Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004240 if (!consumeIf('L'))
4241 return nullptr;
4242 switch (look()) {
4243 case 'w':
4244 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004245 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004246 case 'b':
4247 if (consumeIf("b0E"))
4248 return make<BoolExpr>(0);
4249 if (consumeIf("b1E"))
4250 return make<BoolExpr>(1);
4251 return nullptr;
4252 case 'c':
4253 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004254 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004255 case 'a':
4256 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004257 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004258 case 'h':
4259 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004260 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004261 case 's':
4262 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004263 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004264 case 't':
4265 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004266 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004267 case 'i':
4268 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004269 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004270 case 'j':
4271 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004272 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004273 case 'l':
4274 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004275 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004276 case 'm':
4277 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004278 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004279 case 'x':
4280 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004281 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004282 case 'y':
4283 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004284 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004285 case 'n':
4286 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004287 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004288 case 'o':
4289 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004290 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004291 case 'f':
4292 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004293 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004294 case 'd':
4295 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004296 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004297 case 'e':
4298 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004299#if defined(__powerpc__) || defined(__s390__)
4300 // Handle cases where long doubles encoded with e have the same size
4301 // and representation as doubles.
4302 return getDerived().template parseFloatingLiteral<double>();
4303#else
Pavel Labathba825192018-10-16 14:29:14 +00004304 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004305#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004306 case '_':
4307 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004308 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004309 if (R != nullptr && consumeIf('E'))
4310 return R;
4311 }
4312 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004313 case 'A': {
4314 Node *T = getDerived().parseType();
4315 if (T == nullptr)
4316 return nullptr;
4317 // FIXME: We need to include the string contents in the mangling.
4318 if (consumeIf('E'))
4319 return make<StringLiteral>(T);
4320 return nullptr;
4321 }
4322 case 'D':
gbreynooc0559322022-04-28 15:55:26 +01004323 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
Richard Smithdf1c14c2019-09-06 23:53:21 +00004324 return make<NameType>("nullptr");
4325 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004326 case 'T':
4327 // Invalid mangled name per
4328 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4329 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004330 case 'U': {
4331 // FIXME: Should we support LUb... for block literals?
4332 if (look(1) != 'l')
4333 return nullptr;
4334 Node *T = parseUnnamedTypeName(nullptr);
4335 if (!T || !consumeIf('E'))
4336 return nullptr;
4337 return make<LambdaExpr>(T);
4338 }
Richard Smithc20d1442018-08-20 20:14:49 +00004339 default: {
4340 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004341 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004342 if (T == nullptr)
4343 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004344 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004345 if (N.empty())
4346 return nullptr;
4347 if (!consumeIf('E'))
4348 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004349 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004350 }
4351 }
4352}
4353
4354// <braced-expression> ::= <expression>
4355// ::= di <field source-name> <braced-expression> # .name = expr
4356// ::= dx <index expression> <braced-expression> # [expr] = expr
4357// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004358template <typename Derived, typename Alloc>
4359Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004360 if (look() == 'd') {
4361 switch (look(1)) {
4362 case 'i': {
4363 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004364 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004365 if (Field == nullptr)
4366 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004367 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004368 if (Init == nullptr)
4369 return nullptr;
4370 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4371 }
4372 case 'x': {
4373 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004374 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004375 if (Index == nullptr)
4376 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004377 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004378 if (Init == nullptr)
4379 return nullptr;
4380 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4381 }
4382 case 'X': {
4383 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004384 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004385 if (RangeBegin == nullptr)
4386 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004387 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004388 if (RangeEnd == nullptr)
4389 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004390 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004391 if (Init == nullptr)
4392 return nullptr;
4393 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4394 }
4395 }
4396 }
Pavel Labathba825192018-10-16 14:29:14 +00004397 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004398}
4399
4400// (not yet in the spec)
4401// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4402// ::= fR <binary-operator-name> <expression> <expression>
4403// ::= fl <binary-operator-name> <expression>
4404// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004405template <typename Derived, typename Alloc>
4406Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004407 if (!consumeIf('f'))
4408 return nullptr;
4409
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004410 bool IsLeftFold = false, HasInitializer = false;
4411 switch (look()) {
4412 default:
Richard Smithc20d1442018-08-20 20:14:49 +00004413 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004414 case 'L':
4415 IsLeftFold = true;
4416 HasInitializer = true;
4417 break;
4418 case 'R':
4419 HasInitializer = true;
4420 break;
4421 case 'l':
4422 IsLeftFold = true;
4423 break;
4424 case 'r':
4425 break;
4426 }
Richard Smithc20d1442018-08-20 20:14:49 +00004427 ++First;
4428
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004429 const auto *Op = parseOperatorEncoding();
Nathan Sidwellce967252022-02-18 11:06:58 -08004430 if (!Op)
4431 return nullptr;
4432 if (!(Op->getKind() == OperatorInfo::Binary
4433 || (Op->getKind() == OperatorInfo::Member
4434 && Op->getName().back() == '*')))
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004435 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004436
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004437 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004438 if (Pack == nullptr)
4439 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004440
4441 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004442 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004443 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004444 if (Init == nullptr)
4445 return nullptr;
4446 }
4447
4448 if (IsLeftFold && Init)
4449 std::swap(Pack, Init);
4450
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004451 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004452}
4453
Richard Smith1865d2f2020-10-22 19:29:36 -07004454// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4455//
4456// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4457template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004458Node *
4459AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4460 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004461 Node *Ty = getDerived().parseType();
4462 if (!Ty)
4463 return nullptr;
4464 Node *Expr = getDerived().parseExpr();
4465 if (!Expr)
4466 return nullptr;
4467 StringView Offset = getDerived().parseNumber(true);
4468 if (!consumeIf('E'))
4469 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004470 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004471}
4472
4473// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4474// <union-selector> ::= _ [<number>]
4475//
4476// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4477template <typename Derived, typename Alloc>
4478Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4479 Node *Ty = getDerived().parseType();
4480 if (!Ty)
4481 return nullptr;
4482 Node *Expr = getDerived().parseExpr();
4483 if (!Expr)
4484 return nullptr;
4485 StringView Offset = getDerived().parseNumber(true);
4486 size_t SelectorsBegin = Names.size();
4487 while (consumeIf('_')) {
4488 Node *Selector = make<NameType>(parseNumber());
4489 if (!Selector)
4490 return nullptr;
4491 Names.push_back(Selector);
4492 }
4493 bool OnePastTheEnd = consumeIf('p');
4494 if (!consumeIf('E'))
4495 return nullptr;
4496 return make<SubobjectExpr>(
4497 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4498}
4499
Richard Smithc20d1442018-08-20 20:14:49 +00004500// <expression> ::= <unary operator-name> <expression>
4501// ::= <binary operator-name> <expression> <expression>
4502// ::= <ternary operator-name> <expression> <expression> <expression>
4503// ::= cl <expression>+ E # call
4504// ::= cv <type> <expression> # conversion with one argument
4505// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4506// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4507// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4508// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4509// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4510// ::= [gs] dl <expression> # delete expression
4511// ::= [gs] da <expression> # delete[] expression
4512// ::= pp_ <expression> # prefix ++
4513// ::= mm_ <expression> # prefix --
4514// ::= ti <type> # typeid (type)
4515// ::= te <expression> # typeid (expression)
4516// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4517// ::= sc <type> <expression> # static_cast<type> (expression)
4518// ::= cc <type> <expression> # const_cast<type> (expression)
4519// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4520// ::= st <type> # sizeof (a type)
4521// ::= sz <expression> # sizeof (an expression)
4522// ::= at <type> # alignof (a type)
4523// ::= az <expression> # alignof (an expression)
4524// ::= nx <expression> # noexcept (expression)
4525// ::= <template-param>
4526// ::= <function-param>
4527// ::= dt <expression> <unresolved-name> # expr.name
4528// ::= pt <expression> <unresolved-name> # expr->name
4529// ::= ds <expression> <expression> # expr.*expr
4530// ::= sZ <template-param> # size of a parameter pack
4531// ::= sZ <function-param> # size of a function parameter pack
4532// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4533// ::= sp <expression> # pack expansion
4534// ::= tw <expression> # throw expression
4535// ::= tr # throw with no operand (rethrow)
4536// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4537// # freestanding dependent name (e.g., T::x),
4538// # objectless nonstatic member reference
4539// ::= fL <binary-operator-name> <expression> <expression>
4540// ::= fR <binary-operator-name> <expression> <expression>
4541// ::= fl <binary-operator-name> <expression>
4542// ::= fr <binary-operator-name> <expression>
4543// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004544template <typename Derived, typename Alloc>
4545Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004546 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004547
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004548 const auto *Op = parseOperatorEncoding();
4549 if (Op) {
4550 auto Sym = Op->getSymbol();
4551 switch (Op->getKind()) {
4552 case OperatorInfo::Binary:
4553 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004554 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004555 case OperatorInfo::Prefix:
4556 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004557 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004558 case OperatorInfo::Postfix: {
4559 // Postfix unary operator: expr @
4560 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004561 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004562 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004563 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004564 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004565 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004566 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004567 case OperatorInfo::Array: {
4568 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004569 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004570 if (Base == nullptr)
4571 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004572 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004573 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004574 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004575 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004576 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004577 case OperatorInfo::Member: {
4578 // Member access lhs @ rhs
4579 Node *LHS = getDerived().parseExpr();
4580 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004581 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004582 Node *RHS = getDerived().parseExpr();
4583 if (RHS == nullptr)
4584 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004585 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004586 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004587 case OperatorInfo::New: {
4588 // New
4589 // # new (expr-list) type [(init)]
4590 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4591 // # new[] (expr-list) type [(init)]
4592 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004593 size_t Exprs = Names.size();
4594 while (!consumeIf('_')) {
4595 Node *Ex = getDerived().parseExpr();
4596 if (Ex == nullptr)
4597 return nullptr;
4598 Names.push_back(Ex);
4599 }
4600 NodeArray ExprList = popTrailingNodeArray(Exprs);
4601 Node *Ty = getDerived().parseType();
4602 if (Ty == nullptr)
4603 return nullptr;
4604 bool HaveInits = consumeIf("pi");
4605 size_t InitsBegin = Names.size();
4606 while (!consumeIf('E')) {
4607 if (!HaveInits)
4608 return nullptr;
4609 Node *Init = getDerived().parseExpr();
4610 if (Init == nullptr)
4611 return Init;
4612 Names.push_back(Init);
4613 }
4614 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004615 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004616 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004617 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004618 case OperatorInfo::Del: {
4619 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004620 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004621 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004622 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004623 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4624 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004625 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004626 case OperatorInfo::Call: {
4627 // Function Call
4628 Node *Callee = getDerived().parseExpr();
4629 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004630 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004631 size_t ExprsBegin = Names.size();
4632 while (!consumeIf('E')) {
4633 Node *E = getDerived().parseExpr();
4634 if (E == nullptr)
4635 return nullptr;
4636 Names.push_back(E);
4637 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004638 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4639 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004640 }
4641 case OperatorInfo::CCast: {
4642 // C Cast: (type)expr
4643 Node *Ty;
4644 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004645 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004646 Ty = getDerived().parseType();
4647 }
4648 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004649 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004650
4651 size_t ExprsBegin = Names.size();
4652 bool IsMany = consumeIf('_');
4653 while (!consumeIf('E')) {
4654 Node *E = getDerived().parseExpr();
4655 if (E == nullptr)
4656 return E;
4657 Names.push_back(E);
4658 if (!IsMany)
4659 break;
4660 }
4661 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4662 if (!IsMany && Exprs.size() != 1)
4663 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004664 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004665 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004666 case OperatorInfo::Conditional: {
4667 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004668 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004669 if (Cond == nullptr)
4670 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004671 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004672 if (LHS == nullptr)
4673 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004674 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004675 if (RHS == nullptr)
4676 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004677 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004678 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004679 case OperatorInfo::NamedCast: {
4680 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004681 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004682 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004683 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004684 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004685 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004686 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004687 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004688 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004689 case OperatorInfo::OfIdOp: {
4690 // [sizeof/alignof/typeid] ( <type>|<expr> )
4691 Node *Arg =
4692 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4693 if (!Arg)
4694 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004695 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004696 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004697 case OperatorInfo::NameOnly: {
4698 // Not valid as an expression operand.
4699 return nullptr;
4700 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004701 }
4702 DEMANGLE_UNREACHABLE;
4703 }
4704
4705 if (numLeft() < 2)
4706 return nullptr;
4707
4708 if (look() == 'L')
4709 return getDerived().parseExprPrimary();
4710 if (look() == 'T')
4711 return getDerived().parseTemplateParam();
4712 if (look() == 'f') {
4713 // Disambiguate a fold expression from a <function-param>.
4714 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4715 return getDerived().parseFunctionParam();
4716 return getDerived().parseFoldExpr();
4717 }
4718 if (consumeIf("il")) {
4719 size_t InitsBegin = Names.size();
4720 while (!consumeIf('E')) {
4721 Node *E = getDerived().parseBracedExpr();
4722 if (E == nullptr)
4723 return nullptr;
4724 Names.push_back(E);
4725 }
4726 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4727 }
4728 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004729 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004730 if (consumeIf("nx")) {
4731 Node *Ex = getDerived().parseExpr();
4732 if (Ex == nullptr)
4733 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004734 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004735 }
4736 if (consumeIf("so"))
4737 return parseSubobjectExpr();
4738 if (consumeIf("sp")) {
4739 Node *Child = getDerived().parseExpr();
4740 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004741 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004742 return make<ParameterPackExpansion>(Child);
4743 }
4744 if (consumeIf("sZ")) {
4745 if (look() == 'T') {
4746 Node *R = getDerived().parseTemplateParam();
4747 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004748 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004749 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004750 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004751 Node *FP = getDerived().parseFunctionParam();
4752 if (FP == nullptr)
4753 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004754 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004755 }
4756 if (consumeIf("sP")) {
4757 size_t ArgsBegin = Names.size();
4758 while (!consumeIf('E')) {
4759 Node *Arg = getDerived().parseTemplateArg();
4760 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004761 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004762 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004763 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004764 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4765 if (!Pack)
4766 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004767 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004768 }
4769 if (consumeIf("tl")) {
4770 Node *Ty = getDerived().parseType();
4771 if (Ty == nullptr)
4772 return nullptr;
4773 size_t InitsBegin = Names.size();
4774 while (!consumeIf('E')) {
4775 Node *E = getDerived().parseBracedExpr();
4776 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004777 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004778 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004779 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004780 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4781 }
4782 if (consumeIf("tr"))
4783 return make<NameType>("throw");
4784 if (consumeIf("tw")) {
4785 Node *Ex = getDerived().parseExpr();
4786 if (Ex == nullptr)
4787 return nullptr;
4788 return make<ThrowExpr>(Ex);
4789 }
4790 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004791 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4792 if (!Name)
4793 return nullptr;
4794 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4795 // standard encoding expects a <template-arg>, and would be otherwise be
4796 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4797 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4798 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004799 bool IsUUID = false;
4800 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004801 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004802 if (consumeIf('t')) {
4803 UUID = getDerived().parseType();
4804 IsUUID = true;
4805 } else if (consumeIf('z')) {
4806 UUID = getDerived().parseExpr();
4807 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004808 }
4809 }
4810 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004811 if (IsUUID) {
4812 if (UUID == nullptr)
4813 return nullptr;
4814 Names.push_back(UUID);
4815 } else {
4816 while (!consumeIf('E')) {
4817 Node *E = getDerived().parseTemplateArg();
4818 if (E == nullptr)
4819 return E;
4820 Names.push_back(E);
4821 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004822 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004823 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4824 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004825 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004826
4827 // Only unresolved names remain.
4828 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004829}
4830
4831// <call-offset> ::= h <nv-offset> _
4832// ::= v <v-offset> _
4833//
4834// <nv-offset> ::= <offset number>
4835// # non-virtual base override
4836//
4837// <v-offset> ::= <offset number> _ <virtual offset number>
4838// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004839template <typename Alloc, typename Derived>
4840bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004841 // Just scan through the call offset, we never add this information into the
4842 // output.
4843 if (consumeIf('h'))
4844 return parseNumber(true).empty() || !consumeIf('_');
4845 if (consumeIf('v'))
4846 return parseNumber(true).empty() || !consumeIf('_') ||
4847 parseNumber(true).empty() || !consumeIf('_');
4848 return true;
4849}
4850
4851// <special-name> ::= TV <type> # virtual table
4852// ::= TT <type> # VTT structure (construction vtable index)
4853// ::= TI <type> # typeinfo structure
4854// ::= TS <type> # typeinfo name (null-terminated byte string)
4855// ::= Tc <call-offset> <call-offset> <base encoding>
4856// # base is the nominal target function of thunk
4857// # first call-offset is 'this' adjustment
4858// # second call-offset is result adjustment
4859// ::= T <call-offset> <base encoding>
4860// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004861// # Guard variable for one-time initialization
4862// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004863// # No <type>
4864// ::= TW <object name> # Thread-local wrapper
4865// ::= TH <object name> # Thread-local initialization
4866// ::= GR <object name> _ # First temporary
4867// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004868// # construction vtable for second-in-first
4869// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004870// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004871// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004872template <typename Derived, typename Alloc>
4873Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004874 switch (look()) {
4875 case 'T':
4876 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004877 // TA <template-arg> # template parameter object
4878 //
4879 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4880 case 'A': {
4881 First += 2;
4882 Node *Arg = getDerived().parseTemplateArg();
4883 if (Arg == nullptr)
4884 return nullptr;
4885 return make<SpecialName>("template parameter object for ", Arg);
4886 }
Richard Smithc20d1442018-08-20 20:14:49 +00004887 // TV <type> # virtual table
4888 case 'V': {
4889 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004890 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004891 if (Ty == nullptr)
4892 return nullptr;
4893 return make<SpecialName>("vtable for ", Ty);
4894 }
4895 // TT <type> # VTT structure (construction vtable index)
4896 case 'T': {
4897 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004898 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004899 if (Ty == nullptr)
4900 return nullptr;
4901 return make<SpecialName>("VTT for ", Ty);
4902 }
4903 // TI <type> # typeinfo structure
4904 case 'I': {
4905 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004906 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004907 if (Ty == nullptr)
4908 return nullptr;
4909 return make<SpecialName>("typeinfo for ", Ty);
4910 }
4911 // TS <type> # typeinfo name (null-terminated byte string)
4912 case 'S': {
4913 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004914 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004915 if (Ty == nullptr)
4916 return nullptr;
4917 return make<SpecialName>("typeinfo name for ", Ty);
4918 }
4919 // Tc <call-offset> <call-offset> <base encoding>
4920 case 'c': {
4921 First += 2;
4922 if (parseCallOffset() || parseCallOffset())
4923 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004924 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004925 if (Encoding == nullptr)
4926 return nullptr;
4927 return make<SpecialName>("covariant return thunk to ", Encoding);
4928 }
4929 // extension ::= TC <first type> <number> _ <second type>
4930 // # construction vtable for second-in-first
4931 case 'C': {
4932 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004933 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004934 if (FirstType == nullptr)
4935 return nullptr;
4936 if (parseNumber(true).empty() || !consumeIf('_'))
4937 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004938 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004939 if (SecondType == nullptr)
4940 return nullptr;
4941 return make<CtorVtableSpecialName>(SecondType, FirstType);
4942 }
4943 // TW <object name> # Thread-local wrapper
4944 case 'W': {
4945 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004946 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004947 if (Name == nullptr)
4948 return nullptr;
4949 return make<SpecialName>("thread-local wrapper routine for ", Name);
4950 }
4951 // TH <object name> # Thread-local initialization
4952 case 'H': {
4953 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004954 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004955 if (Name == nullptr)
4956 return nullptr;
4957 return make<SpecialName>("thread-local initialization routine for ", Name);
4958 }
4959 // T <call-offset> <base encoding>
4960 default: {
4961 ++First;
4962 bool IsVirt = look() == 'v';
4963 if (parseCallOffset())
4964 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004965 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004966 if (BaseEncoding == nullptr)
4967 return nullptr;
4968 if (IsVirt)
4969 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4970 else
4971 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4972 }
4973 }
4974 case 'G':
4975 switch (look(1)) {
4976 // GV <object name> # Guard variable for one-time initialization
4977 case 'V': {
4978 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004979 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004980 if (Name == nullptr)
4981 return nullptr;
4982 return make<SpecialName>("guard variable for ", Name);
4983 }
4984 // GR <object name> # reference temporary for object
4985 // GR <object name> _ # First temporary
4986 // GR <object name> <seq-id> _ # Subsequent temporaries
4987 case 'R': {
4988 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004989 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004990 if (Name == nullptr)
4991 return nullptr;
4992 size_t Count;
4993 bool ParsedSeqId = !parseSeqId(&Count);
4994 if (!consumeIf('_') && ParsedSeqId)
4995 return nullptr;
4996 return make<SpecialName>("reference temporary for ", Name);
4997 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004998 // GI <module-name> v
4999 case 'I': {
5000 First += 2;
5001 ModuleName *Module = nullptr;
5002 if (getDerived().parseModuleNameOpt(Module))
5003 return nullptr;
5004 if (Module == nullptr)
5005 return nullptr;
5006 return make<SpecialName>("initializer for module ", Module);
5007 }
Richard Smithc20d1442018-08-20 20:14:49 +00005008 }
5009 }
5010 return nullptr;
5011}
5012
5013// <encoding> ::= <function name> <bare-function-type>
5014// ::= <data name>
5015// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005016template <typename Derived, typename Alloc>
5017Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005018 // The template parameters of an encoding are unrelated to those of the
5019 // enclosing context.
5020 class SaveTemplateParams {
5021 AbstractManglingParser *Parser;
5022 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005023 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005024
5025 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005026 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005027 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005028 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005029 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005030 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005031 }
5032 ~SaveTemplateParams() {
5033 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005034 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005035 }
5036 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005037
Richard Smithc20d1442018-08-20 20:14:49 +00005038 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005039 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005040
5041 auto IsEndOfEncoding = [&] {
5042 // The set of chars that can potentially follow an <encoding> (none of which
5043 // can start a <type>). Enumerating these allows us to avoid speculative
5044 // parsing.
5045 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5046 };
5047
5048 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005049 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005050 if (Name == nullptr)
5051 return nullptr;
5052
5053 if (resolveForwardTemplateRefs(NameInfo))
5054 return nullptr;
5055
5056 if (IsEndOfEncoding())
5057 return Name;
5058
5059 Node *Attrs = nullptr;
5060 if (consumeIf("Ua9enable_ifI")) {
5061 size_t BeforeArgs = Names.size();
5062 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005063 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005064 if (Arg == nullptr)
5065 return nullptr;
5066 Names.push_back(Arg);
5067 }
5068 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005069 if (!Attrs)
5070 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005071 }
5072
5073 Node *ReturnType = nullptr;
5074 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005075 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005076 if (ReturnType == nullptr)
5077 return nullptr;
5078 }
5079
5080 if (consumeIf('v'))
5081 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5082 Attrs, NameInfo.CVQualifiers,
5083 NameInfo.ReferenceQualifier);
5084
5085 size_t ParamsBegin = Names.size();
5086 do {
Pavel Labathba825192018-10-16 14:29:14 +00005087 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005088 if (Ty == nullptr)
5089 return nullptr;
5090 Names.push_back(Ty);
5091 } while (!IsEndOfEncoding());
5092
5093 return make<FunctionEncoding>(ReturnType, Name,
5094 popTrailingNodeArray(ParamsBegin),
5095 Attrs, NameInfo.CVQualifiers,
5096 NameInfo.ReferenceQualifier);
5097}
5098
5099template <class Float>
5100struct FloatData;
5101
5102template <>
5103struct FloatData<float>
5104{
5105 static const size_t mangled_size = 8;
5106 static const size_t max_demangled_size = 24;
5107 static constexpr const char* spec = "%af";
5108};
5109
5110template <>
5111struct FloatData<double>
5112{
5113 static const size_t mangled_size = 16;
5114 static const size_t max_demangled_size = 32;
5115 static constexpr const char* spec = "%a";
5116};
5117
5118template <>
5119struct FloatData<long double>
5120{
5121#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
Piggy NL8b1770b2022-05-26 22:59:49 +08005122 defined(__wasm__) || defined(__riscv)
Richard Smithc20d1442018-08-20 20:14:49 +00005123 static const size_t mangled_size = 32;
5124#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5125 static const size_t mangled_size = 16;
5126#else
5127 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5128#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005129 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5130 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5131 // Negatives are one character longer than positives.
5132 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5133 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5134 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005135 static constexpr const char *spec = "%LaL";
5136};
5137
Pavel Labathba825192018-10-16 14:29:14 +00005138template <typename Alloc, typename Derived>
5139template <class Float>
5140Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005141 const size_t N = FloatData<Float>::mangled_size;
5142 if (numLeft() <= N)
5143 return nullptr;
5144 StringView Data(First, First + N);
5145 for (char C : Data)
5146 if (!std::isxdigit(C))
5147 return nullptr;
5148 First += N;
5149 if (!consumeIf('E'))
5150 return nullptr;
5151 return make<FloatLiteralImpl<Float>>(Data);
5152}
5153
5154// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005155template <typename Alloc, typename Derived>
5156bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005157 if (!(look() >= '0' && look() <= '9') &&
5158 !(look() >= 'A' && look() <= 'Z'))
5159 return true;
5160
5161 size_t Id = 0;
5162 while (true) {
5163 if (look() >= '0' && look() <= '9') {
5164 Id *= 36;
5165 Id += static_cast<size_t>(look() - '0');
5166 } else if (look() >= 'A' && look() <= 'Z') {
5167 Id *= 36;
5168 Id += static_cast<size_t>(look() - 'A') + 10;
5169 } else {
5170 *Out = Id;
5171 return false;
5172 }
5173 ++First;
5174 }
5175}
5176
5177// <substitution> ::= S <seq-id> _
5178// ::= S_
5179// <substitution> ::= Sa # ::std::allocator
5180// <substitution> ::= Sb # ::std::basic_string
5181// <substitution> ::= Ss # ::std::basic_string < char,
5182// ::std::char_traits<char>,
5183// ::std::allocator<char> >
5184// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5185// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5186// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005187// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005188template <typename Derived, typename Alloc>
5189Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005190 if (!consumeIf('S'))
5191 return nullptr;
5192
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005193 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005194 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005195 switch (look()) {
5196 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005197 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005198 break;
5199 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005200 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005201 break;
5202 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005203 Kind = SpecialSubKind::iostream;
5204 break;
5205 case 'i':
5206 Kind = SpecialSubKind::istream;
5207 break;
5208 case 'o':
5209 Kind = SpecialSubKind::ostream;
5210 break;
5211 case 's':
5212 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005213 break;
5214 default:
5215 return nullptr;
5216 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005217 ++First;
5218 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005219 if (!SpecialSub)
5220 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005221
Richard Smithc20d1442018-08-20 20:14:49 +00005222 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5223 // has ABI tags, the tags are appended to the substitution; the result is a
5224 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005225 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005226 if (WithTags != SpecialSub) {
5227 Subs.push_back(WithTags);
5228 SpecialSub = WithTags;
5229 }
5230 return SpecialSub;
5231 }
5232
5233 // ::= S_
5234 if (consumeIf('_')) {
5235 if (Subs.empty())
5236 return nullptr;
5237 return Subs[0];
5238 }
5239
5240 // ::= S <seq-id> _
5241 size_t Index = 0;
5242 if (parseSeqId(&Index))
5243 return nullptr;
5244 ++Index;
5245 if (!consumeIf('_') || Index >= Subs.size())
5246 return nullptr;
5247 return Subs[Index];
5248}
5249
5250// <template-param> ::= T_ # first template parameter
5251// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005252// ::= TL <level-1> __
5253// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005254template <typename Derived, typename Alloc>
5255Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005256 if (!consumeIf('T'))
5257 return nullptr;
5258
Richard Smithdf1c14c2019-09-06 23:53:21 +00005259 size_t Level = 0;
5260 if (consumeIf('L')) {
5261 if (parsePositiveInteger(&Level))
5262 return nullptr;
5263 ++Level;
5264 if (!consumeIf('_'))
5265 return nullptr;
5266 }
5267
Richard Smithc20d1442018-08-20 20:14:49 +00005268 size_t Index = 0;
5269 if (!consumeIf('_')) {
5270 if (parsePositiveInteger(&Index))
5271 return nullptr;
5272 ++Index;
5273 if (!consumeIf('_'))
5274 return nullptr;
5275 }
5276
Richard Smithc20d1442018-08-20 20:14:49 +00005277 // If we're in a context where this <template-param> refers to a
5278 // <template-arg> further ahead in the mangled name (currently just conversion
5279 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005280 // This can only happen at the outermost level.
5281 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005282 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5283 if (!ForwardRef)
5284 return nullptr;
5285 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5286 ForwardTemplateRefs.push_back(
5287 static_cast<ForwardTemplateReference *>(ForwardRef));
5288 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005289 }
5290
Richard Smithdf1c14c2019-09-06 23:53:21 +00005291 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5292 Index >= TemplateParams[Level]->size()) {
5293 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5294 // list are mangled as the corresponding artificial template type parameter.
5295 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5296 // This will be popped by the ScopedTemplateParamList in
5297 // parseUnnamedTypeName.
5298 if (Level == TemplateParams.size())
5299 TemplateParams.push_back(nullptr);
5300 return make<NameType>("auto");
5301 }
5302
Richard Smithc20d1442018-08-20 20:14:49 +00005303 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005304 }
5305
5306 return (*TemplateParams[Level])[Index];
5307}
5308
5309// <template-param-decl> ::= Ty # type parameter
5310// ::= Tn <type> # non-type parameter
5311// ::= Tt <template-param-decl>* E # template parameter
5312// ::= Tp <template-param-decl> # parameter pack
5313template <typename Derived, typename Alloc>
5314Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5315 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5316 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5317 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5318 if (N) TemplateParams.back()->push_back(N);
5319 return N;
5320 };
5321
5322 if (consumeIf("Ty")) {
5323 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5324 if (!Name)
5325 return nullptr;
5326 return make<TypeTemplateParamDecl>(Name);
5327 }
5328
5329 if (consumeIf("Tn")) {
5330 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5331 if (!Name)
5332 return nullptr;
5333 Node *Type = parseType();
5334 if (!Type)
5335 return nullptr;
5336 return make<NonTypeTemplateParamDecl>(Name, Type);
5337 }
5338
5339 if (consumeIf("Tt")) {
5340 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5341 if (!Name)
5342 return nullptr;
5343 size_t ParamsBegin = Names.size();
5344 ScopedTemplateParamList TemplateTemplateParamParams(this);
5345 while (!consumeIf("E")) {
5346 Node *P = parseTemplateParamDecl();
5347 if (!P)
5348 return nullptr;
5349 Names.push_back(P);
5350 }
5351 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5352 return make<TemplateTemplateParamDecl>(Name, Params);
5353 }
5354
5355 if (consumeIf("Tp")) {
5356 Node *P = parseTemplateParamDecl();
5357 if (!P)
5358 return nullptr;
5359 return make<TemplateParamPackDecl>(P);
5360 }
5361
5362 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005363}
5364
5365// <template-arg> ::= <type> # type or template
5366// ::= X <expression> E # expression
5367// ::= <expr-primary> # simple expressions
5368// ::= J <template-arg>* E # argument pack
5369// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005370template <typename Derived, typename Alloc>
5371Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005372 switch (look()) {
5373 case 'X': {
5374 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005375 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005376 if (Arg == nullptr || !consumeIf('E'))
5377 return nullptr;
5378 return Arg;
5379 }
5380 case 'J': {
5381 ++First;
5382 size_t ArgsBegin = Names.size();
5383 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005384 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005385 if (Arg == nullptr)
5386 return nullptr;
5387 Names.push_back(Arg);
5388 }
5389 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5390 return make<TemplateArgumentPack>(Args);
5391 }
5392 case 'L': {
5393 // ::= LZ <encoding> E # extension
5394 if (look(1) == 'Z') {
5395 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005396 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005397 if (Arg == nullptr || !consumeIf('E'))
5398 return nullptr;
5399 return Arg;
5400 }
5401 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005402 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005403 }
5404 default:
Pavel Labathba825192018-10-16 14:29:14 +00005405 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005406 }
5407}
5408
5409// <template-args> ::= I <template-arg>* E
5410// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005411template <typename Derived, typename Alloc>
5412Node *
5413AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005414 if (!consumeIf('I'))
5415 return nullptr;
5416
5417 // <template-params> refer to the innermost <template-args>. Clear out any
5418 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005419 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005420 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005421 TemplateParams.push_back(&OuterTemplateParams);
5422 OuterTemplateParams.clear();
5423 }
Richard Smithc20d1442018-08-20 20:14:49 +00005424
5425 size_t ArgsBegin = Names.size();
5426 while (!consumeIf('E')) {
5427 if (TagTemplates) {
5428 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005429 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005430 TemplateParams = std::move(OldParams);
5431 if (Arg == nullptr)
5432 return nullptr;
5433 Names.push_back(Arg);
5434 Node *TableEntry = Arg;
5435 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5436 TableEntry = make<ParameterPack>(
5437 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005438 if (!TableEntry)
5439 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005440 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005441 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005442 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005443 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005444 if (Arg == nullptr)
5445 return nullptr;
5446 Names.push_back(Arg);
5447 }
5448 }
5449 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5450}
5451
5452// <mangled-name> ::= _Z <encoding>
5453// ::= <type>
5454// extension ::= ___Z <encoding> _block_invoke
5455// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5456// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005457template <typename Derived, typename Alloc>
5458Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005459 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005460 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005461 if (Encoding == nullptr)
5462 return nullptr;
5463 if (look() == '.') {
5464 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5465 First = Last;
5466 }
5467 if (numLeft() != 0)
5468 return nullptr;
5469 return Encoding;
5470 }
5471
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005472 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005473 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005474 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5475 return nullptr;
5476 bool RequireNumber = consumeIf('_');
5477 if (parseNumber().empty() && RequireNumber)
5478 return nullptr;
5479 if (look() == '.')
5480 First = Last;
5481 if (numLeft() != 0)
5482 return nullptr;
5483 return make<SpecialName>("invocation function for block in ", Encoding);
5484 }
5485
Pavel Labathba825192018-10-16 14:29:14 +00005486 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005487 if (numLeft() != 0)
5488 return nullptr;
5489 return Ty;
5490}
5491
Pavel Labathba825192018-10-16 14:29:14 +00005492template <typename Alloc>
5493struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5494 using AbstractManglingParser<ManglingParser<Alloc>,
5495 Alloc>::AbstractManglingParser;
5496};
5497
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005498DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005499
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005500#endif // DEMANGLE_ITANIUMDEMANGLE_H