blob: fa121cc1f3256b1174b8e522450cc4f2185b2226 [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
3035 auto Op = std::lower_bound(
3036 &Ops[0], &Ops[NumOps], First,
3037 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3038 if (Op == &Ops[NumOps] || *Op != First)
3039 return nullptr;
3040
3041 First += 2;
3042 return Op;
3043}
3044
3045// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003046// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003047// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003048template <typename Derived, typename Alloc>
3049Node *
3050AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003051 if (const auto *Op = parseOperatorEncoding()) {
3052 if (Op->getKind() == OperatorInfo::CCast) {
3053 // ::= cv <type> # (cast)
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003054 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);
Richard Smithc20d1442018-08-20 20:14:49 +00003055 // If we're parsing an encoding, State != nullptr and the conversion
3056 // operators' <type> could have a <template-param> that refers to some
3057 // <template-arg>s further ahead in the mangled name.
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003058 ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,
Richard Smithc20d1442018-08-20 20:14:49 +00003059 PermitForwardTemplateReferences ||
3060 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003061 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003062 if (Ty == nullptr)
3063 return nullptr;
3064 if (State) State->CtorDtorConversion = true;
3065 return make<ConversionOperatorType>(Ty);
3066 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003067
3068 if (Op->getKind() >= OperatorInfo::Unnameable)
3069 /* Not a nameable operator. */
3070 return nullptr;
3071 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3072 /* Not a nameable MemberExpr */
3073 return nullptr;
3074
3075 return make<NameType>(Op->getName());
3076 }
3077
3078 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003079 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003080 Node *SN = getDerived().parseSourceName(State);
3081 if (SN == nullptr)
3082 return nullptr;
3083 return make<LiteralOperator>(SN);
3084 }
3085
3086 if (consumeIf('v')) {
3087 // ::= v <digit> <source-name> # vendor extended operator
3088 if (look() >= '0' && look() <= '9') {
3089 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003090 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003091 if (SN == nullptr)
3092 return nullptr;
3093 return make<ConversionOperatorType>(SN);
3094 }
3095 return nullptr;
3096 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003097
Richard Smithc20d1442018-08-20 20:14:49 +00003098 return nullptr;
3099}
3100
3101// <ctor-dtor-name> ::= C1 # complete object constructor
3102// ::= C2 # base object constructor
3103// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003104// extension ::= C4 # gcc old-style "[unified]" constructor
3105// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003106// ::= D0 # deleting destructor
3107// ::= D1 # complete object destructor
3108// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003109// extension ::= D4 # gcc old-style "[unified]" destructor
3110// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003111template <typename Derived, typename Alloc>
3112Node *
3113AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3114 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003115 if (SoFar->getKind() == Node::KSpecialSubstitution) {
Nathan Sidwell28201492022-03-28 12:55:45 -07003116 // Expand the special substitution.
3117 SoFar = make<ExpandedSpecialSubstitution>(
3118 static_cast<SpecialSubstitution *>(SoFar));
3119 if (!SoFar)
3120 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003121 }
3122
3123 if (consumeIf('C')) {
3124 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003125 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3126 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003127 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003128 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003129 ++First;
3130 if (State) State->CtorDtorConversion = true;
3131 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003132 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003133 return nullptr;
3134 }
Nico Weber29294792019-04-03 23:14:33 +00003135 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003136 }
3137
Nico Weber29294792019-04-03 23:14:33 +00003138 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3139 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003140 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003141 First += 2;
3142 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003143 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003144 }
3145
3146 return nullptr;
3147}
3148
Nathan Sidwellac492da2022-04-05 09:25:47 -07003149// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3150// <unqualified-name> E
3151// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3152// <template-args> E
Richard Smithc20d1442018-08-20 20:14:49 +00003153//
Nathan Sidwellac492da2022-04-05 09:25:47 -07003154// <prefix> ::= <prefix> <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003155// ::= <template-prefix> <template-args>
3156// ::= <template-param>
3157// ::= <decltype>
3158// ::= # empty
3159// ::= <substitution>
3160// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003161// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003162//
3163// <data-member-prefix> := <member source-name> [<template-args>] M
3164//
3165// <template-prefix> ::= <prefix> <template unqualified-name>
3166// ::= <template-param>
3167// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003168template <typename Derived, typename Alloc>
3169Node *
3170AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003171 if (!consumeIf('N'))
3172 return nullptr;
3173
3174 Qualifiers CVTmp = parseCVQualifiers();
3175 if (State) State->CVQualifiers = CVTmp;
3176
3177 if (consumeIf('O')) {
3178 if (State) State->ReferenceQualifier = FrefQualRValue;
3179 } else if (consumeIf('R')) {
3180 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003181 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003182 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003183 }
Richard Smithc20d1442018-08-20 20:14:49 +00003184
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003185 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003186 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003187 if (State)
3188 // Only set end-with-template on the case that does that.
3189 State->EndsWithTemplateArgs = false;
3190
Richard Smithc20d1442018-08-20 20:14:49 +00003191 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003192 // ::= <template-param>
3193 if (SoFar != nullptr)
3194 return nullptr; // Cannot have a prefix.
3195 SoFar = getDerived().parseTemplateParam();
3196 } else if (look() == 'I') {
3197 // ::= <template-prefix> <template-args>
3198 if (SoFar == nullptr)
3199 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003200 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003201 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003202 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003203 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3204 // Semantically <template-args> <template-args> cannot be generated by a
3205 // C++ entity. There will always be [something like] a name between
3206 // them.
3207 return nullptr;
3208 if (State)
3209 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003210 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003211 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3212 // ::= <decltype>
3213 if (SoFar != nullptr)
3214 return nullptr; // Cannot have a prefix.
3215 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003216 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003217 ModuleName *Module = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003218
3219 if (look() == 'S') {
3220 // ::= <substitution>
3221 Node *S = nullptr;
3222 if (look(1) == 't') {
3223 First += 2;
3224 S = make<NameType>("std");
3225 } else {
3226 S = getDerived().parseSubstitution();
3227 }
3228 if (!S)
3229 return nullptr;
3230 if (S->getKind() == Node::KModuleName) {
3231 Module = static_cast<ModuleName *>(S);
Nathan Sidwellac492da2022-04-05 09:25:47 -07003232 } else if (SoFar != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003233 return nullptr; // Cannot have a prefix.
3234 } else {
3235 SoFar = S;
3236 continue; // Do not push a new substitution.
3237 }
3238 }
3239
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003240 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003241 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003242 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003243
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003244 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003245 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003246 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003247
3248 // No longer used.
3249 // <data-member-prefix> := <member source-name> [<template-args>] M
3250 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003251 }
3252
3253 if (SoFar == nullptr || Subs.empty())
3254 return nullptr;
3255
3256 Subs.pop_back();
3257 return SoFar;
3258}
3259
3260// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003261template <typename Derived, typename Alloc>
3262Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3263 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003264 if (SN == nullptr)
3265 return nullptr;
3266 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003267 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003268 if (TA == nullptr)
3269 return nullptr;
3270 return make<NameWithTemplateArgs>(SN, TA);
3271 }
3272 return SN;
3273}
3274
3275// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3276// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003277template <typename Derived, typename Alloc>
3278Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003279 Node *Result;
3280 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003281 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003282 else
Pavel Labathba825192018-10-16 14:29:14 +00003283 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003284 if (Result == nullptr)
3285 return nullptr;
3286 return make<DtorName>(Result);
3287}
3288
3289// <unresolved-type> ::= <template-param>
3290// ::= <decltype>
3291// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003292template <typename Derived, typename Alloc>
3293Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003294 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003295 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003296 if (TP == nullptr)
3297 return nullptr;
3298 Subs.push_back(TP);
3299 return TP;
3300 }
3301 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003302 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003303 if (DT == nullptr)
3304 return nullptr;
3305 Subs.push_back(DT);
3306 return DT;
3307 }
Pavel Labathba825192018-10-16 14:29:14 +00003308 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003309}
3310
3311// <base-unresolved-name> ::= <simple-id> # unresolved name
3312// extension ::= <operator-name> # unresolved operator-function-id
3313// extension ::= <operator-name> <template-args> # unresolved operator template-id
3314// ::= on <operator-name> # unresolved operator-function-id
3315// ::= on <operator-name> <template-args> # unresolved operator template-id
3316// ::= dn <destructor-name> # destructor or pseudo-destructor;
3317// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003318template <typename Derived, typename Alloc>
3319Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003320 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003321 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003322
3323 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003324 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003325
3326 consumeIf("on");
3327
Pavel Labathba825192018-10-16 14:29:14 +00003328 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003329 if (Oper == nullptr)
3330 return nullptr;
3331 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003332 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003333 if (TA == nullptr)
3334 return nullptr;
3335 return make<NameWithTemplateArgs>(Oper, TA);
3336 }
3337 return Oper;
3338}
3339
3340// <unresolved-name>
3341// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3342// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3343// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3344// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003345// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003346// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3347// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3348// # T::N::x /decltype(p)::N::x
3349// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3350//
3351// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003352template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003353Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003354 Node *SoFar = nullptr;
3355
3356 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3357 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3358 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003359 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003360 if (SoFar == nullptr)
3361 return nullptr;
3362
3363 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003364 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003365 if (TA == nullptr)
3366 return nullptr;
3367 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003368 if (!SoFar)
3369 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003370 }
3371
3372 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003373 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003374 if (Qual == nullptr)
3375 return nullptr;
3376 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003377 if (!SoFar)
3378 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003379 }
3380
Pavel Labathba825192018-10-16 14:29:14 +00003381 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003382 if (Base == nullptr)
3383 return nullptr;
3384 return make<QualifiedName>(SoFar, Base);
3385 }
3386
Richard Smithc20d1442018-08-20 20:14:49 +00003387 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3388 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003389 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003390 if (SoFar == nullptr)
3391 return nullptr;
3392 if (Global)
3393 SoFar = make<GlobalQualifiedName>(SoFar);
3394 return SoFar;
3395 }
3396
3397 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3398 if (std::isdigit(look())) {
3399 do {
Pavel Labathba825192018-10-16 14:29:14 +00003400 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003401 if (Qual == nullptr)
3402 return nullptr;
3403 if (SoFar)
3404 SoFar = make<QualifiedName>(SoFar, Qual);
3405 else if (Global)
3406 SoFar = make<GlobalQualifiedName>(Qual);
3407 else
3408 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003409 if (!SoFar)
3410 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003411 } while (!consumeIf('E'));
3412 }
3413 // sr <unresolved-type> <base-unresolved-name>
3414 // sr <unresolved-type> <template-args> <base-unresolved-name>
3415 else {
Pavel Labathba825192018-10-16 14:29:14 +00003416 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003417 if (SoFar == nullptr)
3418 return nullptr;
3419
3420 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003421 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003422 if (TA == nullptr)
3423 return nullptr;
3424 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003425 if (!SoFar)
3426 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003427 }
3428 }
3429
3430 assert(SoFar != nullptr);
3431
Pavel Labathba825192018-10-16 14:29:14 +00003432 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003433 if (Base == nullptr)
3434 return nullptr;
3435 return make<QualifiedName>(SoFar, Base);
3436}
3437
3438// <abi-tags> ::= <abi-tag> [<abi-tags>]
3439// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003440template <typename Derived, typename Alloc>
3441Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003442 while (consumeIf('B')) {
3443 StringView SN = parseBareSourceName();
3444 if (SN.empty())
3445 return nullptr;
3446 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003447 if (!N)
3448 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003449 }
3450 return N;
3451}
3452
3453// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003454template <typename Alloc, typename Derived>
3455StringView
3456AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003457 const char *Tmp = First;
3458 if (AllowNegative)
3459 consumeIf('n');
3460 if (numLeft() == 0 || !std::isdigit(*First))
3461 return StringView();
3462 while (numLeft() != 0 && std::isdigit(*First))
3463 ++First;
3464 return StringView(Tmp, First);
3465}
3466
3467// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003468template <typename Alloc, typename Derived>
3469bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003470 *Out = 0;
3471 if (look() < '0' || look() > '9')
3472 return true;
3473 while (look() >= '0' && look() <= '9') {
3474 *Out *= 10;
3475 *Out += static_cast<size_t>(consume() - '0');
3476 }
3477 return false;
3478}
3479
Pavel Labathba825192018-10-16 14:29:14 +00003480template <typename Alloc, typename Derived>
3481StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003482 size_t Int = 0;
3483 if (parsePositiveInteger(&Int) || numLeft() < Int)
3484 return StringView();
3485 StringView R(First, First + Int);
3486 First += Int;
3487 return R;
3488}
3489
3490// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3491//
3492// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3493// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3494// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3495//
3496// <ref-qualifier> ::= R # & ref-qualifier
3497// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003498template <typename Derived, typename Alloc>
3499Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003500 Qualifiers CVQuals = parseCVQualifiers();
3501
3502 Node *ExceptionSpec = nullptr;
3503 if (consumeIf("Do")) {
3504 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003505 if (!ExceptionSpec)
3506 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003507 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003508 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003509 if (E == nullptr || !consumeIf('E'))
3510 return nullptr;
3511 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003512 if (!ExceptionSpec)
3513 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003514 } else if (consumeIf("Dw")) {
3515 size_t SpecsBegin = Names.size();
3516 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003517 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003518 if (T == nullptr)
3519 return nullptr;
3520 Names.push_back(T);
3521 }
3522 ExceptionSpec =
3523 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003524 if (!ExceptionSpec)
3525 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003526 }
3527
3528 consumeIf("Dx"); // transaction safe
3529
3530 if (!consumeIf('F'))
3531 return nullptr;
3532 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003533 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003534 if (ReturnType == nullptr)
3535 return nullptr;
3536
3537 FunctionRefQual ReferenceQualifier = FrefQualNone;
3538 size_t ParamsBegin = Names.size();
3539 while (true) {
3540 if (consumeIf('E'))
3541 break;
3542 if (consumeIf('v'))
3543 continue;
3544 if (consumeIf("RE")) {
3545 ReferenceQualifier = FrefQualLValue;
3546 break;
3547 }
3548 if (consumeIf("OE")) {
3549 ReferenceQualifier = FrefQualRValue;
3550 break;
3551 }
Pavel Labathba825192018-10-16 14:29:14 +00003552 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003553 if (T == nullptr)
3554 return nullptr;
3555 Names.push_back(T);
3556 }
3557
3558 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3559 return make<FunctionType>(ReturnType, Params, CVQuals,
3560 ReferenceQualifier, ExceptionSpec);
3561}
3562
3563// extension:
3564// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3565// ::= Dv [<dimension expression>] _ <element type>
3566// <extended element type> ::= <element type>
3567// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003568template <typename Derived, typename Alloc>
3569Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003570 if (!consumeIf("Dv"))
3571 return nullptr;
3572 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003573 Node *DimensionNumber = make<NameType>(parseNumber());
3574 if (!DimensionNumber)
3575 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003576 if (!consumeIf('_'))
3577 return nullptr;
3578 if (consumeIf('p'))
3579 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003580 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003581 if (ElemType == nullptr)
3582 return nullptr;
3583 return make<VectorType>(ElemType, DimensionNumber);
3584 }
3585
3586 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003587 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003588 if (!DimExpr)
3589 return nullptr;
3590 if (!consumeIf('_'))
3591 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003592 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003593 if (!ElemType)
3594 return nullptr;
3595 return make<VectorType>(ElemType, DimExpr);
3596 }
Pavel Labathba825192018-10-16 14:29:14 +00003597 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003598 if (!ElemType)
3599 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003600 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003601}
3602
3603// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3604// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003605template <typename Derived, typename Alloc>
3606Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003607 if (!consumeIf('D'))
3608 return nullptr;
3609 if (!consumeIf('t') && !consumeIf('T'))
3610 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003611 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003612 if (E == nullptr)
3613 return nullptr;
3614 if (!consumeIf('E'))
3615 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003616 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003617}
3618
3619// <array-type> ::= A <positive dimension number> _ <element type>
3620// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003621template <typename Derived, typename Alloc>
3622Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003623 if (!consumeIf('A'))
3624 return nullptr;
3625
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003626 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003627
Richard Smithc20d1442018-08-20 20:14:49 +00003628 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003629 Dimension = make<NameType>(parseNumber());
3630 if (!Dimension)
3631 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003632 if (!consumeIf('_'))
3633 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003634 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003635 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003636 if (DimExpr == nullptr)
3637 return nullptr;
3638 if (!consumeIf('_'))
3639 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003640 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003641 }
3642
Pavel Labathba825192018-10-16 14:29:14 +00003643 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003644 if (Ty == nullptr)
3645 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003646 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003647}
3648
3649// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003650template <typename Derived, typename Alloc>
3651Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003652 if (!consumeIf('M'))
3653 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003654 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003655 if (ClassType == nullptr)
3656 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003657 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003658 if (MemberType == nullptr)
3659 return nullptr;
3660 return make<PointerToMemberType>(ClassType, MemberType);
3661}
3662
3663// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3664// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3665// ::= Tu <name> # dependent elaborated type specifier using 'union'
3666// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003667template <typename Derived, typename Alloc>
3668Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003669 StringView ElabSpef;
3670 if (consumeIf("Ts"))
3671 ElabSpef = "struct";
3672 else if (consumeIf("Tu"))
3673 ElabSpef = "union";
3674 else if (consumeIf("Te"))
3675 ElabSpef = "enum";
3676
Pavel Labathba825192018-10-16 14:29:14 +00003677 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003678 if (Name == nullptr)
3679 return nullptr;
3680
3681 if (!ElabSpef.empty())
3682 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3683
3684 return Name;
3685}
3686
3687// <qualified-type> ::= <qualifiers> <type>
3688// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3689// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003690template <typename Derived, typename Alloc>
3691Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003692 if (consumeIf('U')) {
3693 StringView Qual = parseBareSourceName();
3694 if (Qual.empty())
3695 return nullptr;
3696
Richard Smithc20d1442018-08-20 20:14:49 +00003697 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3698 if (Qual.startsWith("objcproto")) {
3699 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3700 StringView Proto;
3701 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003702 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()),
3703 SaveLast(Last, ProtoSourceName.end());
Richard Smithc20d1442018-08-20 20:14:49 +00003704 Proto = parseBareSourceName();
3705 }
3706 if (Proto.empty())
3707 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003708 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003709 if (Child == nullptr)
3710 return nullptr;
3711 return make<ObjCProtoName>(Child, Proto);
3712 }
3713
Alex Orlovf50df922021-03-24 10:21:32 +04003714 Node *TA = nullptr;
3715 if (look() == 'I') {
3716 TA = getDerived().parseTemplateArgs();
3717 if (TA == nullptr)
3718 return nullptr;
3719 }
3720
Pavel Labathba825192018-10-16 14:29:14 +00003721 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003722 if (Child == nullptr)
3723 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003724 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003725 }
3726
3727 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003728 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003729 if (Ty == nullptr)
3730 return nullptr;
3731 if (Quals != QualNone)
3732 Ty = make<QualType>(Ty, Quals);
3733 return Ty;
3734}
3735
3736// <type> ::= <builtin-type>
3737// ::= <qualified-type>
3738// ::= <function-type>
3739// ::= <class-enum-type>
3740// ::= <array-type>
3741// ::= <pointer-to-member-type>
3742// ::= <template-param>
3743// ::= <template-template-param> <template-args>
3744// ::= <decltype>
3745// ::= P <type> # pointer
3746// ::= R <type> # l-value reference
3747// ::= O <type> # r-value reference (C++11)
3748// ::= C <type> # complex pair (C99)
3749// ::= G <type> # imaginary (C99)
3750// ::= <substitution> # See Compression below
3751// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3752// extension ::= <vector-type> # <vector-type> starts with Dv
3753//
3754// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3755// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003756template <typename Derived, typename Alloc>
3757Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003758 Node *Result = nullptr;
3759
Richard Smithc20d1442018-08-20 20:14:49 +00003760 switch (look()) {
3761 // ::= <qualified-type>
3762 case 'r':
3763 case 'V':
3764 case 'K': {
3765 unsigned AfterQuals = 0;
3766 if (look(AfterQuals) == 'r') ++AfterQuals;
3767 if (look(AfterQuals) == 'V') ++AfterQuals;
3768 if (look(AfterQuals) == 'K') ++AfterQuals;
3769
3770 if (look(AfterQuals) == 'F' ||
3771 (look(AfterQuals) == 'D' &&
3772 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3773 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003774 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003775 break;
3776 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003777 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003778 }
3779 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003780 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003781 break;
3782 }
3783 // <builtin-type> ::= v # void
3784 case 'v':
3785 ++First;
3786 return make<NameType>("void");
3787 // ::= w # wchar_t
3788 case 'w':
3789 ++First;
3790 return make<NameType>("wchar_t");
3791 // ::= b # bool
3792 case 'b':
3793 ++First;
3794 return make<NameType>("bool");
3795 // ::= c # char
3796 case 'c':
3797 ++First;
3798 return make<NameType>("char");
3799 // ::= a # signed char
3800 case 'a':
3801 ++First;
3802 return make<NameType>("signed char");
3803 // ::= h # unsigned char
3804 case 'h':
3805 ++First;
3806 return make<NameType>("unsigned char");
3807 // ::= s # short
3808 case 's':
3809 ++First;
3810 return make<NameType>("short");
3811 // ::= t # unsigned short
3812 case 't':
3813 ++First;
3814 return make<NameType>("unsigned short");
3815 // ::= i # int
3816 case 'i':
3817 ++First;
3818 return make<NameType>("int");
3819 // ::= j # unsigned int
3820 case 'j':
3821 ++First;
3822 return make<NameType>("unsigned int");
3823 // ::= l # long
3824 case 'l':
3825 ++First;
3826 return make<NameType>("long");
3827 // ::= m # unsigned long
3828 case 'm':
3829 ++First;
3830 return make<NameType>("unsigned long");
3831 // ::= x # long long, __int64
3832 case 'x':
3833 ++First;
3834 return make<NameType>("long long");
3835 // ::= y # unsigned long long, __int64
3836 case 'y':
3837 ++First;
3838 return make<NameType>("unsigned long long");
3839 // ::= n # __int128
3840 case 'n':
3841 ++First;
3842 return make<NameType>("__int128");
3843 // ::= o # unsigned __int128
3844 case 'o':
3845 ++First;
3846 return make<NameType>("unsigned __int128");
3847 // ::= f # float
3848 case 'f':
3849 ++First;
3850 return make<NameType>("float");
3851 // ::= d # double
3852 case 'd':
3853 ++First;
3854 return make<NameType>("double");
3855 // ::= e # long double, __float80
3856 case 'e':
3857 ++First;
3858 return make<NameType>("long double");
3859 // ::= g # __float128
3860 case 'g':
3861 ++First;
3862 return make<NameType>("__float128");
3863 // ::= z # ellipsis
3864 case 'z':
3865 ++First;
3866 return make<NameType>("...");
3867
3868 // <builtin-type> ::= u <source-name> # vendor extended type
3869 case 'u': {
3870 ++First;
3871 StringView Res = parseBareSourceName();
3872 if (Res.empty())
3873 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003874 // Typically, <builtin-type>s are not considered substitution candidates,
3875 // but the exception to that exception is vendor extended types (Itanium C++
3876 // ABI 5.9.1).
3877 Result = make<NameType>(Res);
3878 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003879 }
3880 case 'D':
3881 switch (look(1)) {
3882 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3883 case 'd':
3884 First += 2;
3885 return make<NameType>("decimal64");
3886 // ::= De # IEEE 754r decimal floating point (128 bits)
3887 case 'e':
3888 First += 2;
3889 return make<NameType>("decimal128");
3890 // ::= Df # IEEE 754r decimal floating point (32 bits)
3891 case 'f':
3892 First += 2;
3893 return make<NameType>("decimal32");
3894 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3895 case 'h':
3896 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003897 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003898 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3899 case 'F': {
3900 First += 2;
3901 Node *DimensionNumber = make<NameType>(parseNumber());
3902 if (!DimensionNumber)
3903 return nullptr;
3904 if (!consumeIf('_'))
3905 return nullptr;
3906 return make<BinaryFPType>(DimensionNumber);
3907 }
Senran Zhange025ba52022-03-27 00:04:23 +08003908 // ::= DB <number> _ # C23 signed _BitInt(N)
3909 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
3910 // ::= DU <number> _ # C23 unsigned _BitInt(N)
3911 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
3912 case 'B':
3913 case 'U': {
3914 bool Signed = look(1) == 'B';
3915 First += 2;
3916 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())
3917 : getDerived().parseExpr();
3918 if (!Size)
3919 return nullptr;
3920 if (!consumeIf('_'))
3921 return nullptr;
3922 return make<BitIntType>(Size, Signed);
3923 }
Richard Smithc20d1442018-08-20 20:14:49 +00003924 // ::= Di # char32_t
3925 case 'i':
3926 First += 2;
3927 return make<NameType>("char32_t");
3928 // ::= Ds # char16_t
3929 case 's':
3930 First += 2;
3931 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003932 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3933 case 'u':
3934 First += 2;
3935 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003936 // ::= Da # auto (in dependent new-expressions)
3937 case 'a':
3938 First += 2;
3939 return make<NameType>("auto");
3940 // ::= Dc # decltype(auto)
3941 case 'c':
3942 First += 2;
3943 return make<NameType>("decltype(auto)");
3944 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3945 case 'n':
3946 First += 2;
3947 return make<NameType>("std::nullptr_t");
3948
3949 // ::= <decltype>
3950 case 't':
3951 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003952 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003953 break;
3954 }
3955 // extension ::= <vector-type> # <vector-type> starts with Dv
3956 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003957 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003958 break;
3959 }
3960 // ::= Dp <type> # pack expansion (C++0x)
3961 case 'p': {
3962 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003963 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003964 if (!Child)
3965 return nullptr;
3966 Result = make<ParameterPackExpansion>(Child);
3967 break;
3968 }
3969 // Exception specifier on a function type.
3970 case 'o':
3971 case 'O':
3972 case 'w':
3973 // Transaction safe function type.
3974 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003975 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003976 break;
3977 }
3978 break;
3979 // ::= <function-type>
3980 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003981 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003982 break;
3983 }
3984 // ::= <array-type>
3985 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003986 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003987 break;
3988 }
3989 // ::= <pointer-to-member-type>
3990 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003991 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003992 break;
3993 }
3994 // ::= <template-param>
3995 case 'T': {
3996 // This could be an elaborate type specifier on a <class-enum-type>.
3997 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00003998 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003999 break;
4000 }
4001
Pavel Labathba825192018-10-16 14:29:14 +00004002 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004003 if (Result == nullptr)
4004 return nullptr;
4005
4006 // Result could be either of:
4007 // <type> ::= <template-param>
4008 // <type> ::= <template-template-param> <template-args>
4009 //
4010 // <template-template-param> ::= <template-param>
4011 // ::= <substitution>
4012 //
4013 // If this is followed by some <template-args>, and we're permitted to
4014 // parse them, take the second production.
4015
4016 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004017 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004018 if (TA == nullptr)
4019 return nullptr;
4020 Result = make<NameWithTemplateArgs>(Result, TA);
4021 }
4022 break;
4023 }
4024 // ::= P <type> # pointer
4025 case 'P': {
4026 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004027 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004028 if (Ptr == nullptr)
4029 return nullptr;
4030 Result = make<PointerType>(Ptr);
4031 break;
4032 }
4033 // ::= R <type> # l-value reference
4034 case 'R': {
4035 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004036 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004037 if (Ref == nullptr)
4038 return nullptr;
4039 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4040 break;
4041 }
4042 // ::= O <type> # r-value reference (C++11)
4043 case 'O': {
4044 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004045 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004046 if (Ref == nullptr)
4047 return nullptr;
4048 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4049 break;
4050 }
4051 // ::= C <type> # complex pair (C99)
4052 case 'C': {
4053 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004054 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004055 if (P == nullptr)
4056 return nullptr;
4057 Result = make<PostfixQualifiedType>(P, " complex");
4058 break;
4059 }
4060 // ::= G <type> # imaginary (C99)
4061 case 'G': {
4062 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004063 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004064 if (P == nullptr)
4065 return P;
4066 Result = make<PostfixQualifiedType>(P, " imaginary");
4067 break;
4068 }
4069 // ::= <substitution> # See Compression below
4070 case 'S': {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004071 if (look(1) != 't') {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004072 bool IsSubst = false;
4073 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4074 if (!Result)
Richard Smithc20d1442018-08-20 20:14:49 +00004075 return nullptr;
4076
4077 // Sub could be either of:
4078 // <type> ::= <substitution>
4079 // <type> ::= <template-template-param> <template-args>
4080 //
4081 // <template-template-param> ::= <template-param>
4082 // ::= <substitution>
4083 //
4084 // If this is followed by some <template-args>, and we're permitted to
4085 // parse them, take the second production.
4086
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004087 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4088 if (!IsSubst)
4089 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00004090 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004091 if (TA == nullptr)
4092 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004093 Result = make<NameWithTemplateArgs>(Result, TA);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004094 } else if (IsSubst) {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004095 // If all we parsed was a substitution, don't re-insert into the
4096 // substitution table.
4097 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00004098 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004099 break;
Richard Smithc20d1442018-08-20 20:14:49 +00004100 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004101 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004102 }
4103 // ::= <class-enum-type>
4104 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004105 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004106 break;
4107 }
4108 }
4109
4110 // If we parsed a type, insert it into the substitution table. Note that all
4111 // <builtin-type>s and <substitution>s have already bailed out, because they
4112 // don't get substitutions.
4113 if (Result != nullptr)
4114 Subs.push_back(Result);
4115 return Result;
4116}
4117
Pavel Labathba825192018-10-16 14:29:14 +00004118template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004119Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4120 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004121 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004122 if (E == nullptr)
4123 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004124 return make<PrefixExpr>(Kind, E, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004125}
4126
Pavel Labathba825192018-10-16 14:29:14 +00004127template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004128Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4129 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004130 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004131 if (LHS == nullptr)
4132 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004133 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004134 if (RHS == nullptr)
4135 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004136 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004137}
4138
Pavel Labathba825192018-10-16 14:29:14 +00004139template <typename Derived, typename Alloc>
4140Node *
4141AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004142 StringView Tmp = parseNumber(true);
4143 if (!Tmp.empty() && consumeIf('E'))
4144 return make<IntegerLiteral>(Lit, Tmp);
4145 return nullptr;
4146}
4147
4148// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004149template <typename Alloc, typename Derived>
4150Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004151 Qualifiers CVR = QualNone;
4152 if (consumeIf('r'))
4153 CVR |= QualRestrict;
4154 if (consumeIf('V'))
4155 CVR |= QualVolatile;
4156 if (consumeIf('K'))
4157 CVR |= QualConst;
4158 return CVR;
4159}
4160
4161// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4162// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4163// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4164// ::= 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 -04004165// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004166template <typename Derived, typename Alloc>
4167Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004168 if (consumeIf("fpT"))
4169 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004170 if (consumeIf("fp")) {
4171 parseCVQualifiers();
4172 StringView Num = parseNumber();
4173 if (!consumeIf('_'))
4174 return nullptr;
4175 return make<FunctionParam>(Num);
4176 }
4177 if (consumeIf("fL")) {
4178 if (parseNumber().empty())
4179 return nullptr;
4180 if (!consumeIf('p'))
4181 return nullptr;
4182 parseCVQualifiers();
4183 StringView Num = parseNumber();
4184 if (!consumeIf('_'))
4185 return nullptr;
4186 return make<FunctionParam>(Num);
4187 }
4188 return nullptr;
4189}
4190
Richard Smithc20d1442018-08-20 20:14:49 +00004191// cv <type> <expression> # conversion with one argument
4192// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004193template <typename Derived, typename Alloc>
4194Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004195 if (!consumeIf("cv"))
4196 return nullptr;
4197 Node *Ty;
4198 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004199 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004200 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004201 }
4202
4203 if (Ty == nullptr)
4204 return nullptr;
4205
4206 if (consumeIf('_')) {
4207 size_t ExprsBegin = Names.size();
4208 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004209 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004210 if (E == nullptr)
4211 return E;
4212 Names.push_back(E);
4213 }
4214 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4215 return make<ConversionExpr>(Ty, Exprs);
4216 }
4217
Pavel Labathba825192018-10-16 14:29:14 +00004218 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004219 if (E[0] == nullptr)
4220 return nullptr;
4221 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4222}
4223
4224// <expr-primary> ::= L <type> <value number> E # integer literal
4225// ::= L <type> <value float> E # floating literal
4226// ::= L <string type> E # string literal
4227// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004228// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004229// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4230// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004231template <typename Derived, typename Alloc>
4232Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004233 if (!consumeIf('L'))
4234 return nullptr;
4235 switch (look()) {
4236 case 'w':
4237 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004238 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004239 case 'b':
4240 if (consumeIf("b0E"))
4241 return make<BoolExpr>(0);
4242 if (consumeIf("b1E"))
4243 return make<BoolExpr>(1);
4244 return nullptr;
4245 case 'c':
4246 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004247 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004248 case 'a':
4249 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004250 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004251 case 'h':
4252 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004253 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004254 case 's':
4255 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004256 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004257 case 't':
4258 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004259 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004260 case 'i':
4261 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004262 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004263 case 'j':
4264 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004265 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004266 case 'l':
4267 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004268 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004269 case 'm':
4270 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004271 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004272 case 'x':
4273 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004274 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004275 case 'y':
4276 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004277 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004278 case 'n':
4279 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004280 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004281 case 'o':
4282 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004283 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004284 case 'f':
4285 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004286 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004287 case 'd':
4288 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004289 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004290 case 'e':
4291 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004292#if defined(__powerpc__) || defined(__s390__)
4293 // Handle cases where long doubles encoded with e have the same size
4294 // and representation as doubles.
4295 return getDerived().template parseFloatingLiteral<double>();
4296#else
Pavel Labathba825192018-10-16 14:29:14 +00004297 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004298#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004299 case '_':
4300 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004301 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004302 if (R != nullptr && consumeIf('E'))
4303 return R;
4304 }
4305 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004306 case 'A': {
4307 Node *T = getDerived().parseType();
4308 if (T == nullptr)
4309 return nullptr;
4310 // FIXME: We need to include the string contents in the mangling.
4311 if (consumeIf('E'))
4312 return make<StringLiteral>(T);
4313 return nullptr;
4314 }
4315 case 'D':
gbreynooc0559322022-04-28 15:55:26 +01004316 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
Richard Smithdf1c14c2019-09-06 23:53:21 +00004317 return make<NameType>("nullptr");
4318 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004319 case 'T':
4320 // Invalid mangled name per
4321 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4322 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004323 case 'U': {
4324 // FIXME: Should we support LUb... for block literals?
4325 if (look(1) != 'l')
4326 return nullptr;
4327 Node *T = parseUnnamedTypeName(nullptr);
4328 if (!T || !consumeIf('E'))
4329 return nullptr;
4330 return make<LambdaExpr>(T);
4331 }
Richard Smithc20d1442018-08-20 20:14:49 +00004332 default: {
4333 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004334 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004335 if (T == nullptr)
4336 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004337 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004338 if (N.empty())
4339 return nullptr;
4340 if (!consumeIf('E'))
4341 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004342 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004343 }
4344 }
4345}
4346
4347// <braced-expression> ::= <expression>
4348// ::= di <field source-name> <braced-expression> # .name = expr
4349// ::= dx <index expression> <braced-expression> # [expr] = expr
4350// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004351template <typename Derived, typename Alloc>
4352Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004353 if (look() == 'd') {
4354 switch (look(1)) {
4355 case 'i': {
4356 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004357 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004358 if (Field == nullptr)
4359 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004360 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004361 if (Init == nullptr)
4362 return nullptr;
4363 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4364 }
4365 case 'x': {
4366 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004367 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004368 if (Index == nullptr)
4369 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004370 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004371 if (Init == nullptr)
4372 return nullptr;
4373 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4374 }
4375 case 'X': {
4376 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004377 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004378 if (RangeBegin == nullptr)
4379 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004380 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004381 if (RangeEnd == nullptr)
4382 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004383 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004384 if (Init == nullptr)
4385 return nullptr;
4386 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4387 }
4388 }
4389 }
Pavel Labathba825192018-10-16 14:29:14 +00004390 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004391}
4392
4393// (not yet in the spec)
4394// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4395// ::= fR <binary-operator-name> <expression> <expression>
4396// ::= fl <binary-operator-name> <expression>
4397// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004398template <typename Derived, typename Alloc>
4399Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004400 if (!consumeIf('f'))
4401 return nullptr;
4402
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004403 bool IsLeftFold = false, HasInitializer = false;
4404 switch (look()) {
4405 default:
Richard Smithc20d1442018-08-20 20:14:49 +00004406 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004407 case 'L':
4408 IsLeftFold = true;
4409 HasInitializer = true;
4410 break;
4411 case 'R':
4412 HasInitializer = true;
4413 break;
4414 case 'l':
4415 IsLeftFold = true;
4416 break;
4417 case 'r':
4418 break;
4419 }
Richard Smithc20d1442018-08-20 20:14:49 +00004420 ++First;
4421
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004422 const auto *Op = parseOperatorEncoding();
Nathan Sidwellce967252022-02-18 11:06:58 -08004423 if (!Op)
4424 return nullptr;
4425 if (!(Op->getKind() == OperatorInfo::Binary
4426 || (Op->getKind() == OperatorInfo::Member
4427 && Op->getName().back() == '*')))
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004428 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004429
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004430 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004431 if (Pack == nullptr)
4432 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004433
4434 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004435 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004436 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004437 if (Init == nullptr)
4438 return nullptr;
4439 }
4440
4441 if (IsLeftFold && Init)
4442 std::swap(Pack, Init);
4443
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004444 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004445}
4446
Richard Smith1865d2f2020-10-22 19:29:36 -07004447// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4448//
4449// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4450template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004451Node *
4452AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4453 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004454 Node *Ty = getDerived().parseType();
4455 if (!Ty)
4456 return nullptr;
4457 Node *Expr = getDerived().parseExpr();
4458 if (!Expr)
4459 return nullptr;
4460 StringView Offset = getDerived().parseNumber(true);
4461 if (!consumeIf('E'))
4462 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004463 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004464}
4465
4466// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4467// <union-selector> ::= _ [<number>]
4468//
4469// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4470template <typename Derived, typename Alloc>
4471Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4472 Node *Ty = getDerived().parseType();
4473 if (!Ty)
4474 return nullptr;
4475 Node *Expr = getDerived().parseExpr();
4476 if (!Expr)
4477 return nullptr;
4478 StringView Offset = getDerived().parseNumber(true);
4479 size_t SelectorsBegin = Names.size();
4480 while (consumeIf('_')) {
4481 Node *Selector = make<NameType>(parseNumber());
4482 if (!Selector)
4483 return nullptr;
4484 Names.push_back(Selector);
4485 }
4486 bool OnePastTheEnd = consumeIf('p');
4487 if (!consumeIf('E'))
4488 return nullptr;
4489 return make<SubobjectExpr>(
4490 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4491}
4492
Richard Smithc20d1442018-08-20 20:14:49 +00004493// <expression> ::= <unary operator-name> <expression>
4494// ::= <binary operator-name> <expression> <expression>
4495// ::= <ternary operator-name> <expression> <expression> <expression>
4496// ::= cl <expression>+ E # call
4497// ::= cv <type> <expression> # conversion with one argument
4498// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4499// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4500// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4501// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4502// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4503// ::= [gs] dl <expression> # delete expression
4504// ::= [gs] da <expression> # delete[] expression
4505// ::= pp_ <expression> # prefix ++
4506// ::= mm_ <expression> # prefix --
4507// ::= ti <type> # typeid (type)
4508// ::= te <expression> # typeid (expression)
4509// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4510// ::= sc <type> <expression> # static_cast<type> (expression)
4511// ::= cc <type> <expression> # const_cast<type> (expression)
4512// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4513// ::= st <type> # sizeof (a type)
4514// ::= sz <expression> # sizeof (an expression)
4515// ::= at <type> # alignof (a type)
4516// ::= az <expression> # alignof (an expression)
4517// ::= nx <expression> # noexcept (expression)
4518// ::= <template-param>
4519// ::= <function-param>
4520// ::= dt <expression> <unresolved-name> # expr.name
4521// ::= pt <expression> <unresolved-name> # expr->name
4522// ::= ds <expression> <expression> # expr.*expr
4523// ::= sZ <template-param> # size of a parameter pack
4524// ::= sZ <function-param> # size of a function parameter pack
4525// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4526// ::= sp <expression> # pack expansion
4527// ::= tw <expression> # throw expression
4528// ::= tr # throw with no operand (rethrow)
4529// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4530// # freestanding dependent name (e.g., T::x),
4531// # objectless nonstatic member reference
4532// ::= fL <binary-operator-name> <expression> <expression>
4533// ::= fR <binary-operator-name> <expression> <expression>
4534// ::= fl <binary-operator-name> <expression>
4535// ::= fr <binary-operator-name> <expression>
4536// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004537template <typename Derived, typename Alloc>
4538Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004539 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004540
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004541 const auto *Op = parseOperatorEncoding();
4542 if (Op) {
4543 auto Sym = Op->getSymbol();
4544 switch (Op->getKind()) {
4545 case OperatorInfo::Binary:
4546 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004547 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004548 case OperatorInfo::Prefix:
4549 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004550 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004551 case OperatorInfo::Postfix: {
4552 // Postfix unary operator: expr @
4553 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004554 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004555 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004556 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004557 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004558 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004559 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004560 case OperatorInfo::Array: {
4561 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004562 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004563 if (Base == nullptr)
4564 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004565 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004566 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004567 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004568 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004569 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004570 case OperatorInfo::Member: {
4571 // Member access lhs @ rhs
4572 Node *LHS = getDerived().parseExpr();
4573 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004574 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004575 Node *RHS = getDerived().parseExpr();
4576 if (RHS == nullptr)
4577 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004578 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004579 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004580 case OperatorInfo::New: {
4581 // New
4582 // # new (expr-list) type [(init)]
4583 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4584 // # new[] (expr-list) type [(init)]
4585 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004586 size_t Exprs = Names.size();
4587 while (!consumeIf('_')) {
4588 Node *Ex = getDerived().parseExpr();
4589 if (Ex == nullptr)
4590 return nullptr;
4591 Names.push_back(Ex);
4592 }
4593 NodeArray ExprList = popTrailingNodeArray(Exprs);
4594 Node *Ty = getDerived().parseType();
4595 if (Ty == nullptr)
4596 return nullptr;
4597 bool HaveInits = consumeIf("pi");
4598 size_t InitsBegin = Names.size();
4599 while (!consumeIf('E')) {
4600 if (!HaveInits)
4601 return nullptr;
4602 Node *Init = getDerived().parseExpr();
4603 if (Init == nullptr)
4604 return Init;
4605 Names.push_back(Init);
4606 }
4607 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004608 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004609 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004610 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004611 case OperatorInfo::Del: {
4612 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004613 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004614 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004615 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004616 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4617 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004618 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004619 case OperatorInfo::Call: {
4620 // Function Call
4621 Node *Callee = getDerived().parseExpr();
4622 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004623 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004624 size_t ExprsBegin = Names.size();
4625 while (!consumeIf('E')) {
4626 Node *E = getDerived().parseExpr();
4627 if (E == nullptr)
4628 return nullptr;
4629 Names.push_back(E);
4630 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004631 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4632 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004633 }
4634 case OperatorInfo::CCast: {
4635 // C Cast: (type)expr
4636 Node *Ty;
4637 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004638 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004639 Ty = getDerived().parseType();
4640 }
4641 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004642 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004643
4644 size_t ExprsBegin = Names.size();
4645 bool IsMany = consumeIf('_');
4646 while (!consumeIf('E')) {
4647 Node *E = getDerived().parseExpr();
4648 if (E == nullptr)
4649 return E;
4650 Names.push_back(E);
4651 if (!IsMany)
4652 break;
4653 }
4654 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4655 if (!IsMany && Exprs.size() != 1)
4656 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004657 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004658 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004659 case OperatorInfo::Conditional: {
4660 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004661 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004662 if (Cond == nullptr)
4663 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004664 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004665 if (LHS == nullptr)
4666 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004667 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004668 if (RHS == nullptr)
4669 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004670 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004671 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004672 case OperatorInfo::NamedCast: {
4673 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004674 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004675 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004676 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004677 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004678 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004679 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004680 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004681 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004682 case OperatorInfo::OfIdOp: {
4683 // [sizeof/alignof/typeid] ( <type>|<expr> )
4684 Node *Arg =
4685 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4686 if (!Arg)
4687 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004688 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004689 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004690 case OperatorInfo::NameOnly: {
4691 // Not valid as an expression operand.
4692 return nullptr;
4693 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004694 }
4695 DEMANGLE_UNREACHABLE;
4696 }
4697
4698 if (numLeft() < 2)
4699 return nullptr;
4700
4701 if (look() == 'L')
4702 return getDerived().parseExprPrimary();
4703 if (look() == 'T')
4704 return getDerived().parseTemplateParam();
4705 if (look() == 'f') {
4706 // Disambiguate a fold expression from a <function-param>.
4707 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4708 return getDerived().parseFunctionParam();
4709 return getDerived().parseFoldExpr();
4710 }
4711 if (consumeIf("il")) {
4712 size_t InitsBegin = Names.size();
4713 while (!consumeIf('E')) {
4714 Node *E = getDerived().parseBracedExpr();
4715 if (E == nullptr)
4716 return nullptr;
4717 Names.push_back(E);
4718 }
4719 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4720 }
4721 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004722 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004723 if (consumeIf("nx")) {
4724 Node *Ex = getDerived().parseExpr();
4725 if (Ex == nullptr)
4726 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004727 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004728 }
4729 if (consumeIf("so"))
4730 return parseSubobjectExpr();
4731 if (consumeIf("sp")) {
4732 Node *Child = getDerived().parseExpr();
4733 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004734 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004735 return make<ParameterPackExpansion>(Child);
4736 }
4737 if (consumeIf("sZ")) {
4738 if (look() == 'T') {
4739 Node *R = getDerived().parseTemplateParam();
4740 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004741 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004742 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004743 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004744 Node *FP = getDerived().parseFunctionParam();
4745 if (FP == nullptr)
4746 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004747 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004748 }
4749 if (consumeIf("sP")) {
4750 size_t ArgsBegin = Names.size();
4751 while (!consumeIf('E')) {
4752 Node *Arg = getDerived().parseTemplateArg();
4753 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004754 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004755 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004756 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004757 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4758 if (!Pack)
4759 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004760 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004761 }
4762 if (consumeIf("tl")) {
4763 Node *Ty = getDerived().parseType();
4764 if (Ty == nullptr)
4765 return nullptr;
4766 size_t InitsBegin = Names.size();
4767 while (!consumeIf('E')) {
4768 Node *E = getDerived().parseBracedExpr();
4769 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004770 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004771 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004772 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004773 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4774 }
4775 if (consumeIf("tr"))
4776 return make<NameType>("throw");
4777 if (consumeIf("tw")) {
4778 Node *Ex = getDerived().parseExpr();
4779 if (Ex == nullptr)
4780 return nullptr;
4781 return make<ThrowExpr>(Ex);
4782 }
4783 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004784 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4785 if (!Name)
4786 return nullptr;
4787 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4788 // standard encoding expects a <template-arg>, and would be otherwise be
4789 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4790 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4791 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004792 bool IsUUID = false;
4793 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004794 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004795 if (consumeIf('t')) {
4796 UUID = getDerived().parseType();
4797 IsUUID = true;
4798 } else if (consumeIf('z')) {
4799 UUID = getDerived().parseExpr();
4800 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004801 }
4802 }
4803 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004804 if (IsUUID) {
4805 if (UUID == nullptr)
4806 return nullptr;
4807 Names.push_back(UUID);
4808 } else {
4809 while (!consumeIf('E')) {
4810 Node *E = getDerived().parseTemplateArg();
4811 if (E == nullptr)
4812 return E;
4813 Names.push_back(E);
4814 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004815 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004816 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4817 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004818 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004819
4820 // Only unresolved names remain.
4821 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004822}
4823
4824// <call-offset> ::= h <nv-offset> _
4825// ::= v <v-offset> _
4826//
4827// <nv-offset> ::= <offset number>
4828// # non-virtual base override
4829//
4830// <v-offset> ::= <offset number> _ <virtual offset number>
4831// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004832template <typename Alloc, typename Derived>
4833bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004834 // Just scan through the call offset, we never add this information into the
4835 // output.
4836 if (consumeIf('h'))
4837 return parseNumber(true).empty() || !consumeIf('_');
4838 if (consumeIf('v'))
4839 return parseNumber(true).empty() || !consumeIf('_') ||
4840 parseNumber(true).empty() || !consumeIf('_');
4841 return true;
4842}
4843
4844// <special-name> ::= TV <type> # virtual table
4845// ::= TT <type> # VTT structure (construction vtable index)
4846// ::= TI <type> # typeinfo structure
4847// ::= TS <type> # typeinfo name (null-terminated byte string)
4848// ::= Tc <call-offset> <call-offset> <base encoding>
4849// # base is the nominal target function of thunk
4850// # first call-offset is 'this' adjustment
4851// # second call-offset is result adjustment
4852// ::= T <call-offset> <base encoding>
4853// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004854// # Guard variable for one-time initialization
4855// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004856// # No <type>
4857// ::= TW <object name> # Thread-local wrapper
4858// ::= TH <object name> # Thread-local initialization
4859// ::= GR <object name> _ # First temporary
4860// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004861// # construction vtable for second-in-first
4862// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004863// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004864// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004865template <typename Derived, typename Alloc>
4866Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004867 switch (look()) {
4868 case 'T':
4869 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004870 // TA <template-arg> # template parameter object
4871 //
4872 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4873 case 'A': {
4874 First += 2;
4875 Node *Arg = getDerived().parseTemplateArg();
4876 if (Arg == nullptr)
4877 return nullptr;
4878 return make<SpecialName>("template parameter object for ", Arg);
4879 }
Richard Smithc20d1442018-08-20 20:14:49 +00004880 // TV <type> # virtual table
4881 case 'V': {
4882 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004883 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004884 if (Ty == nullptr)
4885 return nullptr;
4886 return make<SpecialName>("vtable for ", Ty);
4887 }
4888 // TT <type> # VTT structure (construction vtable index)
4889 case 'T': {
4890 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004891 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004892 if (Ty == nullptr)
4893 return nullptr;
4894 return make<SpecialName>("VTT for ", Ty);
4895 }
4896 // TI <type> # typeinfo structure
4897 case 'I': {
4898 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004899 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004900 if (Ty == nullptr)
4901 return nullptr;
4902 return make<SpecialName>("typeinfo for ", Ty);
4903 }
4904 // TS <type> # typeinfo name (null-terminated byte string)
4905 case 'S': {
4906 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004907 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004908 if (Ty == nullptr)
4909 return nullptr;
4910 return make<SpecialName>("typeinfo name for ", Ty);
4911 }
4912 // Tc <call-offset> <call-offset> <base encoding>
4913 case 'c': {
4914 First += 2;
4915 if (parseCallOffset() || parseCallOffset())
4916 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004917 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004918 if (Encoding == nullptr)
4919 return nullptr;
4920 return make<SpecialName>("covariant return thunk to ", Encoding);
4921 }
4922 // extension ::= TC <first type> <number> _ <second type>
4923 // # construction vtable for second-in-first
4924 case 'C': {
4925 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004926 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004927 if (FirstType == nullptr)
4928 return nullptr;
4929 if (parseNumber(true).empty() || !consumeIf('_'))
4930 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004931 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004932 if (SecondType == nullptr)
4933 return nullptr;
4934 return make<CtorVtableSpecialName>(SecondType, FirstType);
4935 }
4936 // TW <object name> # Thread-local wrapper
4937 case 'W': {
4938 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004939 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004940 if (Name == nullptr)
4941 return nullptr;
4942 return make<SpecialName>("thread-local wrapper routine for ", Name);
4943 }
4944 // TH <object name> # Thread-local initialization
4945 case 'H': {
4946 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004947 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004948 if (Name == nullptr)
4949 return nullptr;
4950 return make<SpecialName>("thread-local initialization routine for ", Name);
4951 }
4952 // T <call-offset> <base encoding>
4953 default: {
4954 ++First;
4955 bool IsVirt = look() == 'v';
4956 if (parseCallOffset())
4957 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004958 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004959 if (BaseEncoding == nullptr)
4960 return nullptr;
4961 if (IsVirt)
4962 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4963 else
4964 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4965 }
4966 }
4967 case 'G':
4968 switch (look(1)) {
4969 // GV <object name> # Guard variable for one-time initialization
4970 case 'V': {
4971 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004972 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004973 if (Name == nullptr)
4974 return nullptr;
4975 return make<SpecialName>("guard variable for ", Name);
4976 }
4977 // GR <object name> # reference temporary for object
4978 // GR <object name> _ # First temporary
4979 // GR <object name> <seq-id> _ # Subsequent temporaries
4980 case 'R': {
4981 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004982 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004983 if (Name == nullptr)
4984 return nullptr;
4985 size_t Count;
4986 bool ParsedSeqId = !parseSeqId(&Count);
4987 if (!consumeIf('_') && ParsedSeqId)
4988 return nullptr;
4989 return make<SpecialName>("reference temporary for ", Name);
4990 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004991 // GI <module-name> v
4992 case 'I': {
4993 First += 2;
4994 ModuleName *Module = nullptr;
4995 if (getDerived().parseModuleNameOpt(Module))
4996 return nullptr;
4997 if (Module == nullptr)
4998 return nullptr;
4999 return make<SpecialName>("initializer for module ", Module);
5000 }
Richard Smithc20d1442018-08-20 20:14:49 +00005001 }
5002 }
5003 return nullptr;
5004}
5005
5006// <encoding> ::= <function name> <bare-function-type>
5007// ::= <data name>
5008// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005009template <typename Derived, typename Alloc>
5010Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005011 // The template parameters of an encoding are unrelated to those of the
5012 // enclosing context.
5013 class SaveTemplateParams {
5014 AbstractManglingParser *Parser;
5015 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005016 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005017
5018 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005019 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005020 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005021 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005022 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005023 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005024 }
5025 ~SaveTemplateParams() {
5026 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005027 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005028 }
5029 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005030
Richard Smithc20d1442018-08-20 20:14:49 +00005031 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005032 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005033
5034 auto IsEndOfEncoding = [&] {
5035 // The set of chars that can potentially follow an <encoding> (none of which
5036 // can start a <type>). Enumerating these allows us to avoid speculative
5037 // parsing.
5038 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5039 };
5040
5041 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005042 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005043 if (Name == nullptr)
5044 return nullptr;
5045
5046 if (resolveForwardTemplateRefs(NameInfo))
5047 return nullptr;
5048
5049 if (IsEndOfEncoding())
5050 return Name;
5051
5052 Node *Attrs = nullptr;
5053 if (consumeIf("Ua9enable_ifI")) {
5054 size_t BeforeArgs = Names.size();
5055 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005056 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005057 if (Arg == nullptr)
5058 return nullptr;
5059 Names.push_back(Arg);
5060 }
5061 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005062 if (!Attrs)
5063 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005064 }
5065
5066 Node *ReturnType = nullptr;
5067 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005068 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005069 if (ReturnType == nullptr)
5070 return nullptr;
5071 }
5072
5073 if (consumeIf('v'))
5074 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5075 Attrs, NameInfo.CVQualifiers,
5076 NameInfo.ReferenceQualifier);
5077
5078 size_t ParamsBegin = Names.size();
5079 do {
Pavel Labathba825192018-10-16 14:29:14 +00005080 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005081 if (Ty == nullptr)
5082 return nullptr;
5083 Names.push_back(Ty);
5084 } while (!IsEndOfEncoding());
5085
5086 return make<FunctionEncoding>(ReturnType, Name,
5087 popTrailingNodeArray(ParamsBegin),
5088 Attrs, NameInfo.CVQualifiers,
5089 NameInfo.ReferenceQualifier);
5090}
5091
5092template <class Float>
5093struct FloatData;
5094
5095template <>
5096struct FloatData<float>
5097{
5098 static const size_t mangled_size = 8;
5099 static const size_t max_demangled_size = 24;
5100 static constexpr const char* spec = "%af";
5101};
5102
5103template <>
5104struct FloatData<double>
5105{
5106 static const size_t mangled_size = 16;
5107 static const size_t max_demangled_size = 32;
5108 static constexpr const char* spec = "%a";
5109};
5110
5111template <>
5112struct FloatData<long double>
5113{
5114#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
Piggy NL8b1770b2022-05-26 22:59:49 +08005115 defined(__wasm__) || defined(__riscv)
Richard Smithc20d1442018-08-20 20:14:49 +00005116 static const size_t mangled_size = 32;
5117#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5118 static const size_t mangled_size = 16;
5119#else
5120 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5121#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005122 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5123 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5124 // Negatives are one character longer than positives.
5125 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5126 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5127 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005128 static constexpr const char *spec = "%LaL";
5129};
5130
Pavel Labathba825192018-10-16 14:29:14 +00005131template <typename Alloc, typename Derived>
5132template <class Float>
5133Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005134 const size_t N = FloatData<Float>::mangled_size;
5135 if (numLeft() <= N)
5136 return nullptr;
5137 StringView Data(First, First + N);
5138 for (char C : Data)
5139 if (!std::isxdigit(C))
5140 return nullptr;
5141 First += N;
5142 if (!consumeIf('E'))
5143 return nullptr;
5144 return make<FloatLiteralImpl<Float>>(Data);
5145}
5146
5147// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005148template <typename Alloc, typename Derived>
5149bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005150 if (!(look() >= '0' && look() <= '9') &&
5151 !(look() >= 'A' && look() <= 'Z'))
5152 return true;
5153
5154 size_t Id = 0;
5155 while (true) {
5156 if (look() >= '0' && look() <= '9') {
5157 Id *= 36;
5158 Id += static_cast<size_t>(look() - '0');
5159 } else if (look() >= 'A' && look() <= 'Z') {
5160 Id *= 36;
5161 Id += static_cast<size_t>(look() - 'A') + 10;
5162 } else {
5163 *Out = Id;
5164 return false;
5165 }
5166 ++First;
5167 }
5168}
5169
5170// <substitution> ::= S <seq-id> _
5171// ::= S_
5172// <substitution> ::= Sa # ::std::allocator
5173// <substitution> ::= Sb # ::std::basic_string
5174// <substitution> ::= Ss # ::std::basic_string < char,
5175// ::std::char_traits<char>,
5176// ::std::allocator<char> >
5177// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5178// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5179// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005180// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005181template <typename Derived, typename Alloc>
5182Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005183 if (!consumeIf('S'))
5184 return nullptr;
5185
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005186 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005187 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005188 switch (look()) {
5189 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005190 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005191 break;
5192 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005193 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005194 break;
5195 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005196 Kind = SpecialSubKind::iostream;
5197 break;
5198 case 'i':
5199 Kind = SpecialSubKind::istream;
5200 break;
5201 case 'o':
5202 Kind = SpecialSubKind::ostream;
5203 break;
5204 case 's':
5205 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005206 break;
5207 default:
5208 return nullptr;
5209 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005210 ++First;
5211 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005212 if (!SpecialSub)
5213 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005214
Richard Smithc20d1442018-08-20 20:14:49 +00005215 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5216 // has ABI tags, the tags are appended to the substitution; the result is a
5217 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005218 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005219 if (WithTags != SpecialSub) {
5220 Subs.push_back(WithTags);
5221 SpecialSub = WithTags;
5222 }
5223 return SpecialSub;
5224 }
5225
5226 // ::= S_
5227 if (consumeIf('_')) {
5228 if (Subs.empty())
5229 return nullptr;
5230 return Subs[0];
5231 }
5232
5233 // ::= S <seq-id> _
5234 size_t Index = 0;
5235 if (parseSeqId(&Index))
5236 return nullptr;
5237 ++Index;
5238 if (!consumeIf('_') || Index >= Subs.size())
5239 return nullptr;
5240 return Subs[Index];
5241}
5242
5243// <template-param> ::= T_ # first template parameter
5244// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005245// ::= TL <level-1> __
5246// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005247template <typename Derived, typename Alloc>
5248Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005249 if (!consumeIf('T'))
5250 return nullptr;
5251
Richard Smithdf1c14c2019-09-06 23:53:21 +00005252 size_t Level = 0;
5253 if (consumeIf('L')) {
5254 if (parsePositiveInteger(&Level))
5255 return nullptr;
5256 ++Level;
5257 if (!consumeIf('_'))
5258 return nullptr;
5259 }
5260
Richard Smithc20d1442018-08-20 20:14:49 +00005261 size_t Index = 0;
5262 if (!consumeIf('_')) {
5263 if (parsePositiveInteger(&Index))
5264 return nullptr;
5265 ++Index;
5266 if (!consumeIf('_'))
5267 return nullptr;
5268 }
5269
Richard Smithc20d1442018-08-20 20:14:49 +00005270 // If we're in a context where this <template-param> refers to a
5271 // <template-arg> further ahead in the mangled name (currently just conversion
5272 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005273 // This can only happen at the outermost level.
5274 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005275 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5276 if (!ForwardRef)
5277 return nullptr;
5278 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5279 ForwardTemplateRefs.push_back(
5280 static_cast<ForwardTemplateReference *>(ForwardRef));
5281 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005282 }
5283
Richard Smithdf1c14c2019-09-06 23:53:21 +00005284 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5285 Index >= TemplateParams[Level]->size()) {
5286 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5287 // list are mangled as the corresponding artificial template type parameter.
5288 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5289 // This will be popped by the ScopedTemplateParamList in
5290 // parseUnnamedTypeName.
5291 if (Level == TemplateParams.size())
5292 TemplateParams.push_back(nullptr);
5293 return make<NameType>("auto");
5294 }
5295
Richard Smithc20d1442018-08-20 20:14:49 +00005296 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005297 }
5298
5299 return (*TemplateParams[Level])[Index];
5300}
5301
5302// <template-param-decl> ::= Ty # type parameter
5303// ::= Tn <type> # non-type parameter
5304// ::= Tt <template-param-decl>* E # template parameter
5305// ::= Tp <template-param-decl> # parameter pack
5306template <typename Derived, typename Alloc>
5307Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5308 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5309 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5310 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5311 if (N) TemplateParams.back()->push_back(N);
5312 return N;
5313 };
5314
5315 if (consumeIf("Ty")) {
5316 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5317 if (!Name)
5318 return nullptr;
5319 return make<TypeTemplateParamDecl>(Name);
5320 }
5321
5322 if (consumeIf("Tn")) {
5323 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5324 if (!Name)
5325 return nullptr;
5326 Node *Type = parseType();
5327 if (!Type)
5328 return nullptr;
5329 return make<NonTypeTemplateParamDecl>(Name, Type);
5330 }
5331
5332 if (consumeIf("Tt")) {
5333 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5334 if (!Name)
5335 return nullptr;
5336 size_t ParamsBegin = Names.size();
5337 ScopedTemplateParamList TemplateTemplateParamParams(this);
5338 while (!consumeIf("E")) {
5339 Node *P = parseTemplateParamDecl();
5340 if (!P)
5341 return nullptr;
5342 Names.push_back(P);
5343 }
5344 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5345 return make<TemplateTemplateParamDecl>(Name, Params);
5346 }
5347
5348 if (consumeIf("Tp")) {
5349 Node *P = parseTemplateParamDecl();
5350 if (!P)
5351 return nullptr;
5352 return make<TemplateParamPackDecl>(P);
5353 }
5354
5355 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005356}
5357
5358// <template-arg> ::= <type> # type or template
5359// ::= X <expression> E # expression
5360// ::= <expr-primary> # simple expressions
5361// ::= J <template-arg>* E # argument pack
5362// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005363template <typename Derived, typename Alloc>
5364Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005365 switch (look()) {
5366 case 'X': {
5367 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005368 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005369 if (Arg == nullptr || !consumeIf('E'))
5370 return nullptr;
5371 return Arg;
5372 }
5373 case 'J': {
5374 ++First;
5375 size_t ArgsBegin = Names.size();
5376 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005377 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005378 if (Arg == nullptr)
5379 return nullptr;
5380 Names.push_back(Arg);
5381 }
5382 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5383 return make<TemplateArgumentPack>(Args);
5384 }
5385 case 'L': {
5386 // ::= LZ <encoding> E # extension
5387 if (look(1) == 'Z') {
5388 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005389 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005390 if (Arg == nullptr || !consumeIf('E'))
5391 return nullptr;
5392 return Arg;
5393 }
5394 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005395 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005396 }
5397 default:
Pavel Labathba825192018-10-16 14:29:14 +00005398 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005399 }
5400}
5401
5402// <template-args> ::= I <template-arg>* E
5403// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005404template <typename Derived, typename Alloc>
5405Node *
5406AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005407 if (!consumeIf('I'))
5408 return nullptr;
5409
5410 // <template-params> refer to the innermost <template-args>. Clear out any
5411 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005412 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005413 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005414 TemplateParams.push_back(&OuterTemplateParams);
5415 OuterTemplateParams.clear();
5416 }
Richard Smithc20d1442018-08-20 20:14:49 +00005417
5418 size_t ArgsBegin = Names.size();
5419 while (!consumeIf('E')) {
5420 if (TagTemplates) {
5421 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005422 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005423 TemplateParams = std::move(OldParams);
5424 if (Arg == nullptr)
5425 return nullptr;
5426 Names.push_back(Arg);
5427 Node *TableEntry = Arg;
5428 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5429 TableEntry = make<ParameterPack>(
5430 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005431 if (!TableEntry)
5432 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005433 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005434 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005435 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005436 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005437 if (Arg == nullptr)
5438 return nullptr;
5439 Names.push_back(Arg);
5440 }
5441 }
5442 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5443}
5444
5445// <mangled-name> ::= _Z <encoding>
5446// ::= <type>
5447// extension ::= ___Z <encoding> _block_invoke
5448// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5449// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005450template <typename Derived, typename Alloc>
5451Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005452 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005453 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005454 if (Encoding == nullptr)
5455 return nullptr;
5456 if (look() == '.') {
5457 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5458 First = Last;
5459 }
5460 if (numLeft() != 0)
5461 return nullptr;
5462 return Encoding;
5463 }
5464
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005465 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005466 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005467 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5468 return nullptr;
5469 bool RequireNumber = consumeIf('_');
5470 if (parseNumber().empty() && RequireNumber)
5471 return nullptr;
5472 if (look() == '.')
5473 First = Last;
5474 if (numLeft() != 0)
5475 return nullptr;
5476 return make<SpecialName>("invocation function for block in ", Encoding);
5477 }
5478
Pavel Labathba825192018-10-16 14:29:14 +00005479 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005480 if (numLeft() != 0)
5481 return nullptr;
5482 return Ty;
5483}
5484
Pavel Labathba825192018-10-16 14:29:14 +00005485template <typename Alloc>
5486struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5487 using AbstractManglingParser<ManglingParser<Alloc>,
5488 Alloc>::AbstractManglingParser;
5489};
5490
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005491DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005492
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005493#endif // DEMANGLE_ITANIUMDEMANGLE_H