blob: 9a0b9bfdea623d8ca2582782e5bbc1ee84df90eb [file] [log] [blame]
Richard Smithc20d1442018-08-20 20:14:49 +00001//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===//
2//
Chandler Carruth8ee27c32019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Richard Smithc20d1442018-08-20 20:14:49 +00006//
7//===----------------------------------------------------------------------===//
8//
Nathan Sidwell5b0a8cf2022-01-24 06:38:47 -08009// Generic itanium demangler library.
10// There are two copies of this file in the source tree. The one under
11// libcxxabi is the original and the one under llvm is the copy. Use
12// cp-to-llvm.sh to update the copy. See README.txt for more details.
Richard Smithc20d1442018-08-20 20:14:49 +000013//
14//===----------------------------------------------------------------------===//
15
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000016#ifndef DEMANGLE_ITANIUMDEMANGLE_H
17#define DEMANGLE_ITANIUMDEMANGLE_H
Richard Smithc20d1442018-08-20 20:14:49 +000018
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000019#include "DemangleConfig.h"
Richard Smithc20d1442018-08-20 20:14:49 +000020#include "StringView.h"
21#include "Utility.h"
Nathan Sidwellbbc632f2022-01-24 04:11:59 -080022#include <algorithm>
Richard Smithc20d1442018-08-20 20:14:49 +000023#include <cassert>
24#include <cctype>
25#include <cstdio>
26#include <cstdlib>
27#include <cstring>
Nathan Sidwellbbc632f2022-01-24 04:11:59 -080028#include <limits>
Richard Smithc20d1442018-08-20 20:14:49 +000029#include <utility>
30
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000031DEMANGLE_NAMESPACE_BEGIN
32
Mikhail Borisov8452f062021-08-17 18:06:53 -040033template <class T, size_t N> class PODSmallVector {
34 static_assert(std::is_pod<T>::value,
35 "T is required to be a plain old data type");
36
37 T *First = nullptr;
38 T *Last = nullptr;
39 T *Cap = nullptr;
40 T Inline[N] = {0};
41
42 bool isInline() const { return First == Inline; }
43
44 void clearInline() {
45 First = Inline;
46 Last = Inline;
47 Cap = Inline + N;
48 }
49
50 void reserve(size_t NewCap) {
51 size_t S = size();
52 if (isInline()) {
53 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
54 if (Tmp == nullptr)
55 std::terminate();
56 std::copy(First, Last, Tmp);
57 First = Tmp;
58 } else {
59 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
60 if (First == nullptr)
61 std::terminate();
62 }
63 Last = First + S;
64 Cap = First + NewCap;
65 }
66
67public:
68 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
69
70 PODSmallVector(const PODSmallVector &) = delete;
71 PODSmallVector &operator=(const PODSmallVector &) = delete;
72
73 PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {
74 if (Other.isInline()) {
75 std::copy(Other.begin(), Other.end(), First);
76 Last = First + Other.size();
77 Other.clear();
78 return;
79 }
80
81 First = Other.First;
82 Last = Other.Last;
83 Cap = Other.Cap;
84 Other.clearInline();
85 }
86
87 PODSmallVector &operator=(PODSmallVector &&Other) {
88 if (Other.isInline()) {
89 if (!isInline()) {
90 std::free(First);
91 clearInline();
92 }
93 std::copy(Other.begin(), Other.end(), First);
94 Last = First + Other.size();
95 Other.clear();
96 return *this;
97 }
98
99 if (isInline()) {
100 First = Other.First;
101 Last = Other.Last;
102 Cap = Other.Cap;
103 Other.clearInline();
104 return *this;
105 }
106
107 std::swap(First, Other.First);
108 std::swap(Last, Other.Last);
109 std::swap(Cap, Other.Cap);
110 Other.clear();
111 return *this;
112 }
113
114 // NOLINTNEXTLINE(readability-identifier-naming)
115 void push_back(const T &Elem) {
116 if (Last == Cap)
117 reserve(size() * 2);
118 *Last++ = Elem;
119 }
120
121 // NOLINTNEXTLINE(readability-identifier-naming)
122 void pop_back() {
123 assert(Last != First && "Popping empty vector!");
124 --Last;
125 }
126
127 void dropBack(size_t Index) {
128 assert(Index <= size() && "dropBack() can't expand!");
129 Last = First + Index;
130 }
131
132 T *begin() { return First; }
133 T *end() { return Last; }
134
135 bool empty() const { return First == Last; }
136 size_t size() const { return static_cast<size_t>(Last - First); }
137 T &back() {
138 assert(Last != First && "Calling back() on empty vector!");
139 return *(Last - 1);
140 }
141 T &operator[](size_t Index) {
142 assert(Index < size() && "Invalid access!");
143 return *(begin() + Index);
144 }
145 void clear() { Last = First; }
146
147 ~PODSmallVector() {
148 if (!isInline())
149 std::free(First);
150 }
151};
152
Richard Smithc20d1442018-08-20 20:14:49 +0000153// Base class of all AST nodes. The AST is built by the parser, then is
154// traversed by the printLeft/Right functions to produce a demangled string.
155class Node {
156public:
157 enum Kind : unsigned char {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -0700158#define NODE(NodeKind) K##NodeKind,
159#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +0000160 };
161
162 /// Three-way bool to track a cached value. Unknown is possible if this node
163 /// has an unexpanded parameter pack below it that may affect this cache.
164 enum class Cache : unsigned char { Yes, No, Unknown, };
165
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800166 /// Operator precedence for expression nodes. Used to determine required
167 /// parens in expression emission.
168 enum class Prec {
169 Primary,
170 Postfix,
171 Unary,
172 Cast,
173 PtrMem,
174 Multiplicative,
175 Additive,
176 Shift,
177 Spaceship,
178 Relational,
179 Equality,
180 And,
181 Xor,
182 Ior,
183 AndIf,
184 OrIf,
185 Conditional,
186 Assign,
187 Comma,
188 Default,
189 };
190
Richard Smithc20d1442018-08-20 20:14:49 +0000191private:
192 Kind K;
193
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800194 Prec Precedence : 6;
195
Richard Smithc20d1442018-08-20 20:14:49 +0000196 // FIXME: Make these protected.
197public:
198 /// Tracks if this node has a component on its right side, in which case we
199 /// need to call printRight.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800200 Cache RHSComponentCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000201
202 /// Track if this node is a (possibly qualified) array type. This can affect
203 /// how we format the output string.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800204 Cache ArrayCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000205
206 /// Track if this node is a (possibly qualified) function type. This can
207 /// affect how we format the output string.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800208 Cache FunctionCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000209
210public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800211 Node(Kind K_, Prec Precedence_ = Prec::Primary,
212 Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,
213 Cache FunctionCache_ = Cache::No)
214 : K(K_), Precedence(Precedence_), RHSComponentCache(RHSComponentCache_),
215 ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {}
216 Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_ = Cache::No,
217 Cache FunctionCache_ = Cache::No)
218 : Node(K_, Prec::Primary, RHSComponentCache_, ArrayCache_,
219 FunctionCache_) {}
Richard Smithc20d1442018-08-20 20:14:49 +0000220
221 /// Visit the most-derived object corresponding to this object.
222 template<typename Fn> void visit(Fn F) const;
223
224 // The following function is provided by all derived classes:
225 //
226 // Call F with arguments that, when passed to the constructor of this node,
227 // would construct an equivalent node.
228 //template<typename Fn> void match(Fn F) const;
229
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700230 bool hasRHSComponent(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000231 if (RHSComponentCache != Cache::Unknown)
232 return RHSComponentCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700233 return hasRHSComponentSlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000234 }
235
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700236 bool hasArray(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000237 if (ArrayCache != Cache::Unknown)
238 return ArrayCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700239 return hasArraySlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000240 }
241
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700242 bool hasFunction(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000243 if (FunctionCache != Cache::Unknown)
244 return FunctionCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700245 return hasFunctionSlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000246 }
247
248 Kind getKind() const { return K; }
249
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800250 Prec getPrecedence() const { return Precedence; }
251
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700252 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
253 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
254 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
Richard Smithc20d1442018-08-20 20:14:49 +0000255
256 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
257 // get at a node that actually represents some concrete syntax.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700258 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }
Richard Smithc20d1442018-08-20 20:14:49 +0000259
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800260 // Print this node as an expression operand, surrounding it in parentheses if
261 // its precedence is [Strictly] weaker than P.
262 void printAsOperand(OutputBuffer &OB, Prec P = Prec::Default,
263 bool StrictlyWorse = false) const {
264 bool Paren =
265 unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse);
266 if (Paren)
267 OB.printOpen();
268 print(OB);
269 if (Paren)
270 OB.printClose();
271 }
272
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700273 void print(OutputBuffer &OB) const {
274 printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000275 if (RHSComponentCache != Cache::No)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700276 printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000277 }
278
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -0800279 // Print the "left" side of this Node into OutputBuffer.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700280 virtual void printLeft(OutputBuffer &) const = 0;
Richard Smithc20d1442018-08-20 20:14:49 +0000281
282 // Print the "right". This distinction is necessary to represent C++ types
283 // that appear on the RHS of their subtype, such as arrays or functions.
284 // Since most types don't have such a component, provide a default
285 // implementation.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700286 virtual void printRight(OutputBuffer &) const {}
Richard Smithc20d1442018-08-20 20:14:49 +0000287
288 virtual StringView getBaseName() const { return StringView(); }
289
290 // Silence compiler warnings, this dtor will never be called.
291 virtual ~Node() = default;
292
293#ifndef NDEBUG
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000294 DEMANGLE_DUMP_METHOD void dump() const;
Richard Smithc20d1442018-08-20 20:14:49 +0000295#endif
296};
297
298class NodeArray {
299 Node **Elements;
300 size_t NumElements;
301
302public:
303 NodeArray() : Elements(nullptr), NumElements(0) {}
304 NodeArray(Node **Elements_, size_t NumElements_)
305 : Elements(Elements_), NumElements(NumElements_) {}
306
307 bool empty() const { return NumElements == 0; }
308 size_t size() const { return NumElements; }
309
310 Node **begin() const { return Elements; }
311 Node **end() const { return Elements + NumElements; }
312
313 Node *operator[](size_t Idx) const { return Elements[Idx]; }
314
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700315 void printWithComma(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000316 bool FirstElement = true;
317 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700318 size_t BeforeComma = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +0000319 if (!FirstElement)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700320 OB += ", ";
321 size_t AfterComma = OB.getCurrentPosition();
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800322 Elements[Idx]->printAsOperand(OB, Node::Prec::Comma);
Richard Smithc20d1442018-08-20 20:14:49 +0000323
324 // Elements[Idx] is an empty parameter pack expansion, we should erase the
325 // comma we just printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700326 if (AfterComma == OB.getCurrentPosition()) {
327 OB.setCurrentPosition(BeforeComma);
Richard Smithc20d1442018-08-20 20:14:49 +0000328 continue;
329 }
330
331 FirstElement = false;
332 }
333 }
334};
335
336struct NodeArrayNode : Node {
337 NodeArray Array;
338 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
339
340 template<typename Fn> void match(Fn F) const { F(Array); }
341
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700342 void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000343};
344
345class DotSuffix final : public Node {
346 const Node *Prefix;
347 const StringView Suffix;
348
349public:
350 DotSuffix(const Node *Prefix_, StringView Suffix_)
351 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
352
353 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
354
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700355 void printLeft(OutputBuffer &OB) const override {
356 Prefix->print(OB);
357 OB += " (";
358 OB += Suffix;
359 OB += ")";
Richard Smithc20d1442018-08-20 20:14:49 +0000360 }
361};
362
363class VendorExtQualType final : public Node {
364 const Node *Ty;
365 StringView Ext;
Alex Orlovf50df922021-03-24 10:21:32 +0400366 const Node *TA;
Richard Smithc20d1442018-08-20 20:14:49 +0000367
368public:
Alex Orlovf50df922021-03-24 10:21:32 +0400369 VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)
370 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
Richard Smithc20d1442018-08-20 20:14:49 +0000371
Alex Orlovf50df922021-03-24 10:21:32 +0400372 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
Richard Smithc20d1442018-08-20 20:14:49 +0000373
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700374 void printLeft(OutputBuffer &OB) const override {
375 Ty->print(OB);
376 OB += " ";
377 OB += Ext;
Alex Orlovf50df922021-03-24 10:21:32 +0400378 if (TA != nullptr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700379 TA->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000380 }
381};
382
383enum FunctionRefQual : unsigned char {
384 FrefQualNone,
385 FrefQualLValue,
386 FrefQualRValue,
387};
388
389enum Qualifiers {
390 QualNone = 0,
391 QualConst = 0x1,
392 QualVolatile = 0x2,
393 QualRestrict = 0x4,
394};
395
396inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
397 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
398}
399
Richard Smithdf1c14c2019-09-06 23:53:21 +0000400class QualType final : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +0000401protected:
402 const Qualifiers Quals;
403 const Node *Child;
404
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700405 void printQuals(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000406 if (Quals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700407 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000408 if (Quals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700409 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000410 if (Quals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700411 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000412 }
413
414public:
415 QualType(const Node *Child_, Qualifiers Quals_)
416 : Node(KQualType, Child_->RHSComponentCache,
417 Child_->ArrayCache, Child_->FunctionCache),
418 Quals(Quals_), Child(Child_) {}
419
420 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
421
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700422 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
423 return Child->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000424 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700425 bool hasArraySlow(OutputBuffer &OB) const override {
426 return Child->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000427 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700428 bool hasFunctionSlow(OutputBuffer &OB) const override {
429 return Child->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000430 }
431
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700432 void printLeft(OutputBuffer &OB) const override {
433 Child->printLeft(OB);
434 printQuals(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000435 }
436
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700437 void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000438};
439
440class ConversionOperatorType final : public Node {
441 const Node *Ty;
442
443public:
444 ConversionOperatorType(const Node *Ty_)
445 : Node(KConversionOperatorType), Ty(Ty_) {}
446
447 template<typename Fn> void match(Fn F) const { F(Ty); }
448
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700449 void printLeft(OutputBuffer &OB) const override {
450 OB += "operator ";
451 Ty->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000452 }
453};
454
455class PostfixQualifiedType final : public Node {
456 const Node *Ty;
457 const StringView Postfix;
458
459public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -0700460 PostfixQualifiedType(const Node *Ty_, StringView Postfix_)
Richard Smithc20d1442018-08-20 20:14:49 +0000461 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
462
463 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
464
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700465 void printLeft(OutputBuffer &OB) const override {
466 Ty->printLeft(OB);
467 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +0000468 }
469};
470
471class NameType final : public Node {
472 const StringView Name;
473
474public:
475 NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
476
477 template<typename Fn> void match(Fn F) const { F(Name); }
478
479 StringView getName() const { return Name; }
480 StringView getBaseName() const override { return Name; }
481
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700482 void printLeft(OutputBuffer &OB) const override { OB += Name; }
Richard Smithc20d1442018-08-20 20:14:49 +0000483};
484
485class ElaboratedTypeSpefType : public Node {
486 StringView Kind;
487 Node *Child;
488public:
489 ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
490 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
491
492 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
493
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700494 void printLeft(OutputBuffer &OB) const override {
495 OB += Kind;
496 OB += ' ';
497 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000498 }
499};
500
501struct AbiTagAttr : Node {
502 Node *Base;
503 StringView Tag;
504
505 AbiTagAttr(Node* Base_, StringView Tag_)
506 : Node(KAbiTagAttr, Base_->RHSComponentCache,
507 Base_->ArrayCache, Base_->FunctionCache),
508 Base(Base_), Tag(Tag_) {}
509
510 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
511
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700512 void printLeft(OutputBuffer &OB) const override {
513 Base->printLeft(OB);
514 OB += "[abi:";
515 OB += Tag;
516 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +0000517 }
518};
519
520class EnableIfAttr : public Node {
521 NodeArray Conditions;
522public:
523 EnableIfAttr(NodeArray Conditions_)
524 : Node(KEnableIfAttr), Conditions(Conditions_) {}
525
526 template<typename Fn> void match(Fn F) const { F(Conditions); }
527
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700528 void printLeft(OutputBuffer &OB) const override {
529 OB += " [enable_if:";
530 Conditions.printWithComma(OB);
531 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +0000532 }
533};
534
535class ObjCProtoName : public Node {
536 const Node *Ty;
537 StringView Protocol;
538
539 friend class PointerType;
540
541public:
542 ObjCProtoName(const Node *Ty_, StringView Protocol_)
543 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
544
545 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
546
547 bool isObjCObject() const {
548 return Ty->getKind() == KNameType &&
549 static_cast<const NameType *>(Ty)->getName() == "objc_object";
550 }
551
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700552 void printLeft(OutputBuffer &OB) const override {
553 Ty->print(OB);
554 OB += "<";
555 OB += Protocol;
556 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +0000557 }
558};
559
560class PointerType final : public Node {
561 const Node *Pointee;
562
563public:
564 PointerType(const Node *Pointee_)
565 : Node(KPointerType, Pointee_->RHSComponentCache),
566 Pointee(Pointee_) {}
567
568 template<typename Fn> void match(Fn F) const { F(Pointee); }
569
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700570 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
571 return Pointee->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000572 }
573
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700574 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000575 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
576 if (Pointee->getKind() != KObjCProtoName ||
577 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700578 Pointee->printLeft(OB);
579 if (Pointee->hasArray(OB))
580 OB += " ";
581 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
582 OB += "(";
583 OB += "*";
Richard Smithc20d1442018-08-20 20:14:49 +0000584 } else {
585 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700586 OB += "id<";
587 OB += objcProto->Protocol;
588 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +0000589 }
590 }
591
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700592 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000593 if (Pointee->getKind() != KObjCProtoName ||
594 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700595 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
596 OB += ")";
597 Pointee->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000598 }
599 }
600};
601
602enum class ReferenceKind {
603 LValue,
604 RValue,
605};
606
607// Represents either a LValue or an RValue reference type.
608class ReferenceType : public Node {
609 const Node *Pointee;
610 ReferenceKind RK;
611
612 mutable bool Printing = false;
613
614 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
615 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
616 // other combination collapses to a lvalue ref.
Mikhail Borisov05f77222021-08-17 18:10:57 -0400617 //
618 // A combination of a TemplateForwardReference and a back-ref Substitution
619 // from an ill-formed string may have created a cycle; use cycle detection to
620 // avoid looping forever.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700621 std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000622 auto SoFar = std::make_pair(RK, Pointee);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400623 // Track the chain of nodes for the Floyd's 'tortoise and hare'
624 // cycle-detection algorithm, since getSyntaxNode(S) is impure
625 PODSmallVector<const Node *, 8> Prev;
Richard Smithc20d1442018-08-20 20:14:49 +0000626 for (;;) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700627 const Node *SN = SoFar.second->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000628 if (SN->getKind() != KReferenceType)
629 break;
630 auto *RT = static_cast<const ReferenceType *>(SN);
631 SoFar.second = RT->Pointee;
632 SoFar.first = std::min(SoFar.first, RT->RK);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400633
634 // The middle of Prev is the 'slow' pointer moving at half speed
635 Prev.push_back(SoFar.second);
636 if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {
637 // Cycle detected
638 SoFar.second = nullptr;
639 break;
640 }
Richard Smithc20d1442018-08-20 20:14:49 +0000641 }
642 return SoFar;
643 }
644
645public:
646 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
647 : Node(KReferenceType, Pointee_->RHSComponentCache),
648 Pointee(Pointee_), RK(RK_) {}
649
650 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
651
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700652 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
653 return Pointee->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000654 }
655
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700656 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000657 if (Printing)
658 return;
659 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700660 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400661 if (!Collapsed.second)
662 return;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700663 Collapsed.second->printLeft(OB);
664 if (Collapsed.second->hasArray(OB))
665 OB += " ";
666 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
667 OB += "(";
Richard Smithc20d1442018-08-20 20:14:49 +0000668
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700669 OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
Richard Smithc20d1442018-08-20 20:14:49 +0000670 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700671 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000672 if (Printing)
673 return;
674 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700675 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400676 if (!Collapsed.second)
677 return;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700678 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
679 OB += ")";
680 Collapsed.second->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000681 }
682};
683
684class PointerToMemberType final : public Node {
685 const Node *ClassType;
686 const Node *MemberType;
687
688public:
689 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
690 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
691 ClassType(ClassType_), MemberType(MemberType_) {}
692
693 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
694
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700695 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
696 return MemberType->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000697 }
698
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700699 void printLeft(OutputBuffer &OB) const override {
700 MemberType->printLeft(OB);
701 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
702 OB += "(";
Richard Smithc20d1442018-08-20 20:14:49 +0000703 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700704 OB += " ";
705 ClassType->print(OB);
706 OB += "::*";
Richard Smithc20d1442018-08-20 20:14:49 +0000707 }
708
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700709 void printRight(OutputBuffer &OB) const override {
710 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
711 OB += ")";
712 MemberType->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000713 }
714};
715
Richard Smithc20d1442018-08-20 20:14:49 +0000716class ArrayType final : public Node {
717 const Node *Base;
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800718 Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000719
720public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800721 ArrayType(const Node *Base_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000722 : Node(KArrayType,
723 /*RHSComponentCache=*/Cache::Yes,
724 /*ArrayCache=*/Cache::Yes),
725 Base(Base_), Dimension(Dimension_) {}
726
727 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
728
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700729 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
730 bool hasArraySlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000731
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700732 void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000733
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700734 void printRight(OutputBuffer &OB) const override {
735 if (OB.back() != ']')
736 OB += " ";
737 OB += "[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800738 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700739 Dimension->print(OB);
740 OB += "]";
741 Base->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000742 }
743};
744
745class FunctionType final : public Node {
746 const Node *Ret;
747 NodeArray Params;
748 Qualifiers CVQuals;
749 FunctionRefQual RefQual;
750 const Node *ExceptionSpec;
751
752public:
753 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
754 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
755 : Node(KFunctionType,
756 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
757 /*FunctionCache=*/Cache::Yes),
758 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
759 ExceptionSpec(ExceptionSpec_) {}
760
761 template<typename Fn> void match(Fn F) const {
762 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
763 }
764
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700765 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
766 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000767
768 // Handle C++'s ... quirky decl grammar by using the left & right
769 // distinction. Consider:
770 // int (*f(float))(char) {}
771 // f is a function that takes a float and returns a pointer to a function
772 // that takes a char and returns an int. If we're trying to print f, start
773 // by printing out the return types's left, then print our parameters, then
774 // finally print right of the return type.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700775 void printLeft(OutputBuffer &OB) const override {
776 Ret->printLeft(OB);
777 OB += " ";
Richard Smithc20d1442018-08-20 20:14:49 +0000778 }
779
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700780 void printRight(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800781 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700782 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800783 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700784 Ret->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000785
786 if (CVQuals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700787 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000788 if (CVQuals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700789 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000790 if (CVQuals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700791 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000792
793 if (RefQual == FrefQualLValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700794 OB += " &";
Richard Smithc20d1442018-08-20 20:14:49 +0000795 else if (RefQual == FrefQualRValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700796 OB += " &&";
Richard Smithc20d1442018-08-20 20:14:49 +0000797
798 if (ExceptionSpec != nullptr) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700799 OB += ' ';
800 ExceptionSpec->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000801 }
802 }
803};
804
805class NoexceptSpec : public Node {
806 const Node *E;
807public:
808 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
809
810 template<typename Fn> void match(Fn F) const { F(E); }
811
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700812 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800813 OB += "noexcept";
814 OB.printOpen();
815 E->printAsOperand(OB);
816 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000817 }
818};
819
820class DynamicExceptionSpec : public Node {
821 NodeArray Types;
822public:
823 DynamicExceptionSpec(NodeArray Types_)
824 : Node(KDynamicExceptionSpec), Types(Types_) {}
825
826 template<typename Fn> void match(Fn F) const { F(Types); }
827
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700828 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800829 OB += "throw";
830 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700831 Types.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800832 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000833 }
834};
835
836class FunctionEncoding final : public Node {
837 const Node *Ret;
838 const Node *Name;
839 NodeArray Params;
840 const Node *Attrs;
841 Qualifiers CVQuals;
842 FunctionRefQual RefQual;
843
844public:
845 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
846 const Node *Attrs_, Qualifiers CVQuals_,
847 FunctionRefQual RefQual_)
848 : Node(KFunctionEncoding,
849 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
850 /*FunctionCache=*/Cache::Yes),
851 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
852 CVQuals(CVQuals_), RefQual(RefQual_) {}
853
854 template<typename Fn> void match(Fn F) const {
855 F(Ret, Name, Params, Attrs, CVQuals, RefQual);
856 }
857
858 Qualifiers getCVQuals() const { return CVQuals; }
859 FunctionRefQual getRefQual() const { return RefQual; }
860 NodeArray getParams() const { return Params; }
861 const Node *getReturnType() const { return Ret; }
862
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700863 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
864 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000865
866 const Node *getName() const { return Name; }
867
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700868 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000869 if (Ret) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700870 Ret->printLeft(OB);
871 if (!Ret->hasRHSComponent(OB))
872 OB += " ";
Richard Smithc20d1442018-08-20 20:14:49 +0000873 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700874 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000875 }
876
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700877 void printRight(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800878 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700879 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800880 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000881 if (Ret)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700882 Ret->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000883
884 if (CVQuals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700885 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000886 if (CVQuals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700887 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000888 if (CVQuals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700889 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000890
891 if (RefQual == FrefQualLValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700892 OB += " &";
Richard Smithc20d1442018-08-20 20:14:49 +0000893 else if (RefQual == FrefQualRValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700894 OB += " &&";
Richard Smithc20d1442018-08-20 20:14:49 +0000895
896 if (Attrs != nullptr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700897 Attrs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000898 }
899};
900
901class LiteralOperator : public Node {
902 const Node *OpName;
903
904public:
905 LiteralOperator(const Node *OpName_)
906 : Node(KLiteralOperator), OpName(OpName_) {}
907
908 template<typename Fn> void match(Fn F) const { F(OpName); }
909
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700910 void printLeft(OutputBuffer &OB) const override {
911 OB += "operator\"\" ";
912 OpName->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000913 }
914};
915
916class SpecialName final : public Node {
917 const StringView Special;
918 const Node *Child;
919
920public:
921 SpecialName(StringView Special_, const Node *Child_)
922 : Node(KSpecialName), Special(Special_), Child(Child_) {}
923
924 template<typename Fn> void match(Fn F) const { F(Special, Child); }
925
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700926 void printLeft(OutputBuffer &OB) const override {
927 OB += Special;
928 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000929 }
930};
931
932class CtorVtableSpecialName final : public Node {
933 const Node *FirstType;
934 const Node *SecondType;
935
936public:
937 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
938 : Node(KCtorVtableSpecialName),
939 FirstType(FirstType_), SecondType(SecondType_) {}
940
941 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
942
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700943 void printLeft(OutputBuffer &OB) const override {
944 OB += "construction vtable for ";
945 FirstType->print(OB);
946 OB += "-in-";
947 SecondType->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000948 }
949};
950
951struct NestedName : Node {
952 Node *Qual;
953 Node *Name;
954
955 NestedName(Node *Qual_, Node *Name_)
956 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
957
958 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
959
960 StringView getBaseName() const override { return Name->getBaseName(); }
961
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700962 void printLeft(OutputBuffer &OB) const override {
963 Qual->print(OB);
964 OB += "::";
965 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000966 }
967};
968
Nathan Sidwelledde7bb2022-01-26 07:22:04 -0800969struct ModuleName : Node {
970 ModuleName *Parent;
971 Node *Name;
972 bool IsPartition;
973
974 ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false)
975 : Node(KModuleName), Parent(Parent_), Name(Name_),
976 IsPartition(IsPartition_) {}
977
Nathan Sidwelldafcca22022-03-29 04:43:16 -0700978 template <typename Fn> void match(Fn F) const {
979 F(Parent, Name, IsPartition);
980 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -0800981
982 void printLeft(OutputBuffer &OB) const override {
983 if (Parent)
984 Parent->print(OB);
985 if (Parent || IsPartition)
986 OB += IsPartition ? ':' : '.';
987 Name->print(OB);
988 }
989};
990
991struct ModuleEntity : Node {
992 ModuleName *Module;
993 Node *Name;
994
995 ModuleEntity(ModuleName *Module_, Node *Name_)
996 : Node(KModuleEntity), Module(Module_), Name(Name_) {}
997
998 template <typename Fn> void match(Fn F) const { F(Module, Name); }
999
1000 StringView getBaseName() const override { return Name->getBaseName(); }
1001
1002 void printLeft(OutputBuffer &OB) const override {
1003 Name->print(OB);
1004 OB += '@';
1005 Module->print(OB);
1006 }
1007};
1008
Richard Smithc20d1442018-08-20 20:14:49 +00001009struct LocalName : Node {
1010 Node *Encoding;
1011 Node *Entity;
1012
1013 LocalName(Node *Encoding_, Node *Entity_)
1014 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
1015
1016 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
1017
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001018 void printLeft(OutputBuffer &OB) const override {
1019 Encoding->print(OB);
1020 OB += "::";
1021 Entity->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001022 }
1023};
1024
1025class QualifiedName final : public Node {
1026 // qualifier::name
1027 const Node *Qualifier;
1028 const Node *Name;
1029
1030public:
1031 QualifiedName(const Node *Qualifier_, const Node *Name_)
1032 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
1033
1034 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
1035
1036 StringView getBaseName() const override { return Name->getBaseName(); }
1037
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001038 void printLeft(OutputBuffer &OB) const override {
1039 Qualifier->print(OB);
1040 OB += "::";
1041 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001042 }
1043};
1044
1045class VectorType final : public Node {
1046 const Node *BaseType;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001047 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001048
1049public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001050 VectorType(const Node *BaseType_, const Node *Dimension_)
1051 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001052
1053 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
1054
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001055 void printLeft(OutputBuffer &OB) const override {
1056 BaseType->print(OB);
1057 OB += " vector[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001058 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001059 Dimension->print(OB);
1060 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001061 }
1062};
1063
1064class PixelVectorType final : public Node {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001065 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001066
1067public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001068 PixelVectorType(const Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +00001069 : Node(KPixelVectorType), Dimension(Dimension_) {}
1070
1071 template<typename Fn> void match(Fn F) const { F(Dimension); }
1072
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001073 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001074 // FIXME: This should demangle as "vector pixel".
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001075 OB += "pixel vector[";
1076 Dimension->print(OB);
1077 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001078 }
1079};
1080
Pengfei Wang50e90b82021-09-23 11:02:25 +08001081class BinaryFPType final : public Node {
1082 const Node *Dimension;
1083
1084public:
1085 BinaryFPType(const Node *Dimension_)
1086 : Node(KBinaryFPType), Dimension(Dimension_) {}
1087
1088 template<typename Fn> void match(Fn F) const { F(Dimension); }
1089
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001090 void printLeft(OutputBuffer &OB) const override {
1091 OB += "_Float";
1092 Dimension->print(OB);
Pengfei Wang50e90b82021-09-23 11:02:25 +08001093 }
1094};
1095
Richard Smithdf1c14c2019-09-06 23:53:21 +00001096enum class TemplateParamKind { Type, NonType, Template };
1097
1098/// An invented name for a template parameter for which we don't have a
1099/// corresponding template argument.
1100///
1101/// This node is created when parsing the <lambda-sig> for a lambda with
1102/// explicit template arguments, which might be referenced in the parameter
1103/// types appearing later in the <lambda-sig>.
1104class SyntheticTemplateParamName final : public Node {
1105 TemplateParamKind Kind;
1106 unsigned Index;
1107
1108public:
1109 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
1110 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
1111
1112 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
1113
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001114 void printLeft(OutputBuffer &OB) const override {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001115 switch (Kind) {
1116 case TemplateParamKind::Type:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001117 OB += "$T";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001118 break;
1119 case TemplateParamKind::NonType:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001120 OB += "$N";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001121 break;
1122 case TemplateParamKind::Template:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001123 OB += "$TT";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001124 break;
1125 }
1126 if (Index > 0)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001127 OB << Index - 1;
Richard Smithdf1c14c2019-09-06 23:53:21 +00001128 }
1129};
1130
1131/// A template type parameter declaration, 'typename T'.
1132class TypeTemplateParamDecl final : public Node {
1133 Node *Name;
1134
1135public:
1136 TypeTemplateParamDecl(Node *Name_)
1137 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
1138
1139 template<typename Fn> void match(Fn F) const { F(Name); }
1140
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001141 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001142
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001143 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001144};
1145
1146/// A non-type template parameter declaration, 'int N'.
1147class NonTypeTemplateParamDecl final : public Node {
1148 Node *Name;
1149 Node *Type;
1150
1151public:
1152 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
1153 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
1154
1155 template<typename Fn> void match(Fn F) const { F(Name, Type); }
1156
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001157 void printLeft(OutputBuffer &OB) const override {
1158 Type->printLeft(OB);
1159 if (!Type->hasRHSComponent(OB))
1160 OB += " ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001161 }
1162
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001163 void printRight(OutputBuffer &OB) const override {
1164 Name->print(OB);
1165 Type->printRight(OB);
Richard Smithdf1c14c2019-09-06 23:53:21 +00001166 }
1167};
1168
1169/// A template template parameter declaration,
1170/// 'template<typename T> typename N'.
1171class TemplateTemplateParamDecl final : public Node {
1172 Node *Name;
1173 NodeArray Params;
1174
1175public:
1176 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
1177 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1178 Params(Params_) {}
1179
1180 template<typename Fn> void match(Fn F) const { F(Name, Params); }
1181
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001182 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001183 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001184 OB += "template<";
1185 Params.printWithComma(OB);
1186 OB += "> typename ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001187 }
1188
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001189 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001190};
1191
1192/// A template parameter pack declaration, 'typename ...T'.
1193class TemplateParamPackDecl final : public Node {
1194 Node *Param;
1195
1196public:
1197 TemplateParamPackDecl(Node *Param_)
1198 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1199
1200 template<typename Fn> void match(Fn F) const { F(Param); }
1201
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001202 void printLeft(OutputBuffer &OB) const override {
1203 Param->printLeft(OB);
1204 OB += "...";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001205 }
1206
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001207 void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001208};
1209
Richard Smithc20d1442018-08-20 20:14:49 +00001210/// An unexpanded parameter pack (either in the expression or type context). If
1211/// this AST is correct, this node will have a ParameterPackExpansion node above
1212/// it.
1213///
1214/// This node is created when some <template-args> are found that apply to an
1215/// <encoding>, and is stored in the TemplateParams table. In order for this to
1216/// appear in the final AST, it has to referenced via a <template-param> (ie,
1217/// T_).
1218class ParameterPack final : public Node {
1219 NodeArray Data;
1220
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08001221 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1222 // one.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001223 void initializePackExpansion(OutputBuffer &OB) const {
1224 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1225 OB.CurrentPackMax = static_cast<unsigned>(Data.size());
1226 OB.CurrentPackIndex = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00001227 }
1228 }
1229
1230public:
1231 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1232 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
1233 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1234 return P->ArrayCache == Cache::No;
1235 }))
1236 ArrayCache = Cache::No;
1237 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1238 return P->FunctionCache == Cache::No;
1239 }))
1240 FunctionCache = Cache::No;
1241 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1242 return P->RHSComponentCache == Cache::No;
1243 }))
1244 RHSComponentCache = Cache::No;
1245 }
1246
1247 template<typename Fn> void match(Fn F) const { F(Data); }
1248
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001249 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1250 initializePackExpansion(OB);
1251 size_t Idx = OB.CurrentPackIndex;
1252 return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001253 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001254 bool hasArraySlow(OutputBuffer &OB) const override {
1255 initializePackExpansion(OB);
1256 size_t Idx = OB.CurrentPackIndex;
1257 return Idx < Data.size() && Data[Idx]->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001258 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001259 bool hasFunctionSlow(OutputBuffer &OB) const override {
1260 initializePackExpansion(OB);
1261 size_t Idx = OB.CurrentPackIndex;
1262 return Idx < Data.size() && Data[Idx]->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001263 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001264 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1265 initializePackExpansion(OB);
1266 size_t Idx = OB.CurrentPackIndex;
1267 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;
Richard Smithc20d1442018-08-20 20:14:49 +00001268 }
1269
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001270 void printLeft(OutputBuffer &OB) const override {
1271 initializePackExpansion(OB);
1272 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001273 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001274 Data[Idx]->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001275 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001276 void printRight(OutputBuffer &OB) const override {
1277 initializePackExpansion(OB);
1278 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001279 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001280 Data[Idx]->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001281 }
1282};
1283
1284/// A variadic template argument. This node represents an occurrence of
1285/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1286/// one of it's Elements is. The parser inserts a ParameterPack into the
1287/// TemplateParams table if the <template-args> this pack belongs to apply to an
1288/// <encoding>.
1289class TemplateArgumentPack final : public Node {
1290 NodeArray Elements;
1291public:
1292 TemplateArgumentPack(NodeArray Elements_)
1293 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1294
1295 template<typename Fn> void match(Fn F) const { F(Elements); }
1296
1297 NodeArray getElements() const { return Elements; }
1298
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001299 void printLeft(OutputBuffer &OB) const override {
1300 Elements.printWithComma(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001301 }
1302};
1303
1304/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1305/// which each have Child->ParameterPackSize elements.
1306class ParameterPackExpansion final : public Node {
1307 const Node *Child;
1308
1309public:
1310 ParameterPackExpansion(const Node *Child_)
1311 : Node(KParameterPackExpansion), Child(Child_) {}
1312
1313 template<typename Fn> void match(Fn F) const { F(Child); }
1314
1315 const Node *getChild() const { return Child; }
1316
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001317 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001318 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001319 SwapAndRestore<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1320 SwapAndRestore<unsigned> SavePackMax(OB.CurrentPackMax, Max);
1321 size_t StreamPos = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +00001322
1323 // Print the first element in the pack. If Child contains a ParameterPack,
1324 // it will set up S.CurrentPackMax and print the first element.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001325 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001326
1327 // No ParameterPack was found in Child. This can occur if we've found a pack
1328 // expansion on a <function-param>.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001329 if (OB.CurrentPackMax == Max) {
1330 OB += "...";
Richard Smithc20d1442018-08-20 20:14:49 +00001331 return;
1332 }
1333
1334 // We found a ParameterPack, but it has no elements. Erase whatever we may
1335 // of printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001336 if (OB.CurrentPackMax == 0) {
1337 OB.setCurrentPosition(StreamPos);
Richard Smithc20d1442018-08-20 20:14:49 +00001338 return;
1339 }
1340
1341 // Else, iterate through the rest of the elements in the pack.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001342 for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {
1343 OB += ", ";
1344 OB.CurrentPackIndex = I;
1345 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001346 }
1347 }
1348};
1349
1350class TemplateArgs final : public Node {
1351 NodeArray Params;
1352
1353public:
1354 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1355
1356 template<typename Fn> void match(Fn F) const { F(Params); }
1357
1358 NodeArray getParams() { return Params; }
1359
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001360 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001361 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001362 OB += "<";
1363 Params.printWithComma(OB);
1364 if (OB.back() == '>')
1365 OB += " ";
1366 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +00001367 }
1368};
1369
Richard Smithb485b352018-08-24 23:30:26 +00001370/// A forward-reference to a template argument that was not known at the point
1371/// where the template parameter name was parsed in a mangling.
1372///
1373/// This is created when demangling the name of a specialization of a
1374/// conversion function template:
1375///
1376/// \code
1377/// struct A {
1378/// template<typename T> operator T*();
1379/// };
1380/// \endcode
1381///
1382/// When demangling a specialization of the conversion function template, we
1383/// encounter the name of the template (including the \c T) before we reach
1384/// the template argument list, so we cannot substitute the parameter name
1385/// for the corresponding argument while parsing. Instead, we create a
1386/// \c ForwardTemplateReference node that is resolved after we parse the
1387/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001388struct ForwardTemplateReference : Node {
1389 size_t Index;
1390 Node *Ref = nullptr;
1391
1392 // If we're currently printing this node. It is possible (though invalid) for
1393 // a forward template reference to refer to itself via a substitution. This
1394 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1395 // out if more than one print* function is active.
1396 mutable bool Printing = false;
1397
1398 ForwardTemplateReference(size_t Index_)
1399 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1400 Cache::Unknown),
1401 Index(Index_) {}
1402
1403 // We don't provide a matcher for these, because the value of the node is
1404 // not determined by its construction parameters, and it generally needs
1405 // special handling.
1406 template<typename Fn> void match(Fn F) const = delete;
1407
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001408 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001409 if (Printing)
1410 return false;
1411 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001412 return Ref->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001413 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001414 bool hasArraySlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001415 if (Printing)
1416 return false;
1417 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001418 return Ref->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001419 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001420 bool hasFunctionSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001421 if (Printing)
1422 return false;
1423 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001424 return Ref->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001425 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001426 const Node *getSyntaxNode(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001427 if (Printing)
1428 return this;
1429 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001430 return Ref->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001431 }
1432
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001433 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001434 if (Printing)
1435 return;
1436 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001437 Ref->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001438 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001439 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001440 if (Printing)
1441 return;
1442 SwapAndRestore<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001443 Ref->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001444 }
1445};
1446
1447struct NameWithTemplateArgs : Node {
1448 // name<template_args>
1449 Node *Name;
1450 Node *TemplateArgs;
1451
1452 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1453 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1454
1455 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1456
1457 StringView getBaseName() const override { return Name->getBaseName(); }
1458
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001459 void printLeft(OutputBuffer &OB) const override {
1460 Name->print(OB);
1461 TemplateArgs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001462 }
1463};
1464
1465class GlobalQualifiedName final : public Node {
1466 Node *Child;
1467
1468public:
1469 GlobalQualifiedName(Node* Child_)
1470 : Node(KGlobalQualifiedName), Child(Child_) {}
1471
1472 template<typename Fn> void match(Fn F) const { F(Child); }
1473
1474 StringView getBaseName() const override { return Child->getBaseName(); }
1475
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001476 void printLeft(OutputBuffer &OB) const override {
1477 OB += "::";
1478 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001479 }
1480};
1481
Richard Smithc20d1442018-08-20 20:14:49 +00001482enum class SpecialSubKind {
1483 allocator,
1484 basic_string,
1485 string,
1486 istream,
1487 ostream,
1488 iostream,
1489};
1490
1491class ExpandedSpecialSubstitution final : public Node {
1492 SpecialSubKind SSK;
1493
1494public:
1495 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
1496 : Node(KExpandedSpecialSubstitution), SSK(SSK_) {}
1497
1498 template<typename Fn> void match(Fn F) const { F(SSK); }
1499
1500 StringView getBaseName() const override {
1501 switch (SSK) {
1502 case SpecialSubKind::allocator:
1503 return StringView("allocator");
1504 case SpecialSubKind::basic_string:
1505 return StringView("basic_string");
1506 case SpecialSubKind::string:
1507 return StringView("basic_string");
1508 case SpecialSubKind::istream:
1509 return StringView("basic_istream");
1510 case SpecialSubKind::ostream:
1511 return StringView("basic_ostream");
1512 case SpecialSubKind::iostream:
1513 return StringView("basic_iostream");
1514 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001515 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001516 }
1517
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001518 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001519 switch (SSK) {
1520 case SpecialSubKind::allocator:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001521 OB += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001522 break;
1523 case SpecialSubKind::basic_string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001524 OB += "std::basic_string";
Richard Smithb485b352018-08-24 23:30:26 +00001525 break;
Richard Smithc20d1442018-08-20 20:14:49 +00001526 case SpecialSubKind::string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001527 OB += "std::basic_string<char, std::char_traits<char>, "
1528 "std::allocator<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001529 break;
1530 case SpecialSubKind::istream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001531 OB += "std::basic_istream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001532 break;
1533 case SpecialSubKind::ostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001534 OB += "std::basic_ostream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001535 break;
1536 case SpecialSubKind::iostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001537 OB += "std::basic_iostream<char, std::char_traits<char> >";
Richard Smithc20d1442018-08-20 20:14:49 +00001538 break;
1539 }
1540 }
1541};
1542
1543class SpecialSubstitution final : public Node {
1544public:
1545 SpecialSubKind SSK;
1546
1547 SpecialSubstitution(SpecialSubKind SSK_)
1548 : Node(KSpecialSubstitution), SSK(SSK_) {}
1549
1550 template<typename Fn> void match(Fn F) const { F(SSK); }
1551
1552 StringView getBaseName() const override {
1553 switch (SSK) {
1554 case SpecialSubKind::allocator:
1555 return StringView("allocator");
1556 case SpecialSubKind::basic_string:
1557 return StringView("basic_string");
1558 case SpecialSubKind::string:
1559 return StringView("string");
1560 case SpecialSubKind::istream:
1561 return StringView("istream");
1562 case SpecialSubKind::ostream:
1563 return StringView("ostream");
1564 case SpecialSubKind::iostream:
1565 return StringView("iostream");
1566 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001567 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001568 }
1569
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001570 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001571 switch (SSK) {
1572 case SpecialSubKind::allocator:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001573 OB += "std::allocator";
Richard Smithc20d1442018-08-20 20:14:49 +00001574 break;
1575 case SpecialSubKind::basic_string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001576 OB += "std::basic_string";
Richard Smithc20d1442018-08-20 20:14:49 +00001577 break;
1578 case SpecialSubKind::string:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001579 OB += "std::string";
Richard Smithc20d1442018-08-20 20:14:49 +00001580 break;
1581 case SpecialSubKind::istream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001582 OB += "std::istream";
Richard Smithc20d1442018-08-20 20:14:49 +00001583 break;
1584 case SpecialSubKind::ostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001585 OB += "std::ostream";
Richard Smithc20d1442018-08-20 20:14:49 +00001586 break;
1587 case SpecialSubKind::iostream:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001588 OB += "std::iostream";
Richard Smithc20d1442018-08-20 20:14:49 +00001589 break;
1590 }
1591 }
1592};
1593
1594class CtorDtorName final : public Node {
1595 const Node *Basename;
1596 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001597 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001598
1599public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001600 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1601 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1602 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001603
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001604 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001605
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001606 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001607 if (IsDtor)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001608 OB += "~";
1609 OB += Basename->getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001610 }
1611};
1612
1613class DtorName : public Node {
1614 const Node *Base;
1615
1616public:
1617 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1618
1619 template<typename Fn> void match(Fn F) const { F(Base); }
1620
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001621 void printLeft(OutputBuffer &OB) const override {
1622 OB += "~";
1623 Base->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001624 }
1625};
1626
1627class UnnamedTypeName : public Node {
1628 const StringView Count;
1629
1630public:
1631 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1632
1633 template<typename Fn> void match(Fn F) const { F(Count); }
1634
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001635 void printLeft(OutputBuffer &OB) const override {
1636 OB += "'unnamed";
1637 OB += Count;
1638 OB += "\'";
Richard Smithc20d1442018-08-20 20:14:49 +00001639 }
1640};
1641
1642class ClosureTypeName : public Node {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001643 NodeArray TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00001644 NodeArray Params;
1645 StringView Count;
1646
1647public:
Richard Smithdf1c14c2019-09-06 23:53:21 +00001648 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1649 StringView Count_)
1650 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1651 Params(Params_), Count(Count_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001652
Richard Smithdf1c14c2019-09-06 23:53:21 +00001653 template<typename Fn> void match(Fn F) const {
1654 F(TemplateParams, Params, Count);
1655 }
1656
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001657 void printDeclarator(OutputBuffer &OB) const {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001658 if (!TemplateParams.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001659 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001660 OB += "<";
1661 TemplateParams.printWithComma(OB);
1662 OB += ">";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001663 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001664 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001665 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001666 OB.printClose();
Richard Smithdf1c14c2019-09-06 23:53:21 +00001667 }
Richard Smithc20d1442018-08-20 20:14:49 +00001668
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001669 void printLeft(OutputBuffer &OB) const override {
1670 OB += "\'lambda";
1671 OB += Count;
1672 OB += "\'";
1673 printDeclarator(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001674 }
1675};
1676
1677class StructuredBindingName : public Node {
1678 NodeArray Bindings;
1679public:
1680 StructuredBindingName(NodeArray Bindings_)
1681 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1682
1683 template<typename Fn> void match(Fn F) const { F(Bindings); }
1684
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001685 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001686 OB.printOpen('[');
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001687 Bindings.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001688 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001689 }
1690};
1691
1692// -- Expression Nodes --
1693
1694class BinaryExpr : public Node {
1695 const Node *LHS;
1696 const StringView InfixOperator;
1697 const Node *RHS;
1698
1699public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001700 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
1701 Prec Prec_)
1702 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
1703 RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001704
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001705 template <typename Fn> void match(Fn F) const {
1706 F(LHS, InfixOperator, RHS, getPrecedence());
1707 }
Richard Smithc20d1442018-08-20 20:14:49 +00001708
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001709 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell18505102022-03-25 04:34:19 -07001710 bool ParenAll = OB.isGtInsideTemplateArgs() &&
1711 (InfixOperator == ">" || InfixOperator == ">>");
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001712 if (ParenAll)
1713 OB.printOpen();
1714 // Assignment is right associative, with special LHS precedence.
1715 bool IsAssign = getPrecedence() == Prec::Assign;
1716 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1717 // No space before comma operator
1718 if (!(InfixOperator == ","))
1719 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001720 OB += InfixOperator;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001721 OB += " ";
1722 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1723 if (ParenAll)
1724 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001725 }
1726};
1727
1728class ArraySubscriptExpr : public Node {
1729 const Node *Op1;
1730 const Node *Op2;
1731
1732public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001733 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1734 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001735
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001736 template <typename Fn> void match(Fn F) const {
1737 F(Op1, Op2, getPrecedence());
1738 }
Richard Smithc20d1442018-08-20 20:14:49 +00001739
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001740 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001741 Op1->printAsOperand(OB, getPrecedence());
1742 OB.printOpen('[');
1743 Op2->printAsOperand(OB);
1744 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001745 }
1746};
1747
1748class PostfixExpr : public Node {
1749 const Node *Child;
1750 const StringView Operator;
1751
1752public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001753 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
1754 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001755
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001756 template <typename Fn> void match(Fn F) const {
1757 F(Child, Operator, getPrecedence());
1758 }
Richard Smithc20d1442018-08-20 20:14:49 +00001759
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001760 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001761 Child->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001762 OB += Operator;
Richard Smithc20d1442018-08-20 20:14:49 +00001763 }
1764};
1765
1766class ConditionalExpr : public Node {
1767 const Node *Cond;
1768 const Node *Then;
1769 const Node *Else;
1770
1771public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001772 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1773 Prec Prec_)
1774 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001775
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001776 template <typename Fn> void match(Fn F) const {
1777 F(Cond, Then, Else, getPrecedence());
1778 }
Richard Smithc20d1442018-08-20 20:14:49 +00001779
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001780 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001781 Cond->printAsOperand(OB, getPrecedence());
1782 OB += " ? ";
1783 Then->printAsOperand(OB);
1784 OB += " : ";
1785 Else->printAsOperand(OB, Prec::Assign, true);
Richard Smithc20d1442018-08-20 20:14:49 +00001786 }
1787};
1788
1789class MemberExpr : public Node {
1790 const Node *LHS;
1791 const StringView Kind;
1792 const Node *RHS;
1793
1794public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001795 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
1796 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001797
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001798 template <typename Fn> void match(Fn F) const {
1799 F(LHS, Kind, RHS, getPrecedence());
1800 }
Richard Smithc20d1442018-08-20 20:14:49 +00001801
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001802 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001803 LHS->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001804 OB += Kind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001805 RHS->printAsOperand(OB, getPrecedence(), false);
Richard Smithc20d1442018-08-20 20:14:49 +00001806 }
1807};
1808
Richard Smith1865d2f2020-10-22 19:29:36 -07001809class SubobjectExpr : public Node {
1810 const Node *Type;
1811 const Node *SubExpr;
1812 StringView Offset;
1813 NodeArray UnionSelectors;
1814 bool OnePastTheEnd;
1815
1816public:
1817 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1818 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1819 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1820 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1821
1822 template<typename Fn> void match(Fn F) const {
1823 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1824 }
1825
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001826 void printLeft(OutputBuffer &OB) const override {
1827 SubExpr->print(OB);
1828 OB += ".<";
1829 Type->print(OB);
1830 OB += " at offset ";
Richard Smith1865d2f2020-10-22 19:29:36 -07001831 if (Offset.empty()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001832 OB += "0";
Richard Smith1865d2f2020-10-22 19:29:36 -07001833 } else if (Offset[0] == 'n') {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001834 OB += "-";
1835 OB += Offset.dropFront();
Richard Smith1865d2f2020-10-22 19:29:36 -07001836 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001837 OB += Offset;
Richard Smith1865d2f2020-10-22 19:29:36 -07001838 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001839 OB += ">";
Richard Smith1865d2f2020-10-22 19:29:36 -07001840 }
1841};
1842
Richard Smithc20d1442018-08-20 20:14:49 +00001843class EnclosingExpr : public Node {
1844 const StringView Prefix;
1845 const Node *Infix;
1846 const StringView Postfix;
1847
1848public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001849 EnclosingExpr(StringView Prefix_, const Node *Infix_,
1850 Prec Prec_ = Prec::Primary)
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001851 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001852
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001853 template <typename Fn> void match(Fn F) const {
1854 F(Prefix, Infix, getPrecedence());
1855 }
Richard Smithc20d1442018-08-20 20:14:49 +00001856
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001857 void printLeft(OutputBuffer &OB) const override {
1858 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001859 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001860 Infix->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001861 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001862 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +00001863 }
1864};
1865
1866class CastExpr : public Node {
1867 // cast_kind<to>(from)
1868 const StringView CastKind;
1869 const Node *To;
1870 const Node *From;
1871
1872public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001873 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
1874 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001875
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001876 template <typename Fn> void match(Fn F) const {
1877 F(CastKind, To, From, getPrecedence());
1878 }
Richard Smithc20d1442018-08-20 20:14:49 +00001879
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001880 void printLeft(OutputBuffer &OB) const override {
1881 OB += CastKind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001882 {
1883 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
1884 OB += "<";
1885 To->printLeft(OB);
1886 if (OB.back() == '>')
1887 OB += " ";
1888 OB += ">";
1889 }
1890 OB.printOpen();
1891 From->printAsOperand(OB);
1892 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001893 }
1894};
1895
1896class SizeofParamPackExpr : public Node {
1897 const Node *Pack;
1898
1899public:
1900 SizeofParamPackExpr(const Node *Pack_)
1901 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1902
1903 template<typename Fn> void match(Fn F) const { F(Pack); }
1904
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001905 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001906 OB += "sizeof...";
1907 OB.printOpen();
Richard Smithc20d1442018-08-20 20:14:49 +00001908 ParameterPackExpansion PPE(Pack);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001909 PPE.printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001910 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001911 }
1912};
1913
1914class CallExpr : public Node {
1915 const Node *Callee;
1916 NodeArray Args;
1917
1918public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001919 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
1920 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001921
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001922 template <typename Fn> void match(Fn F) const {
1923 F(Callee, Args, getPrecedence());
1924 }
Richard Smithc20d1442018-08-20 20:14:49 +00001925
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001926 void printLeft(OutputBuffer &OB) const override {
1927 Callee->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001928 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001929 Args.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001930 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001931 }
1932};
1933
1934class NewExpr : public Node {
1935 // new (expr_list) type(init_list)
1936 NodeArray ExprList;
1937 Node *Type;
1938 NodeArray InitList;
1939 bool IsGlobal; // ::operator new ?
1940 bool IsArray; // new[] ?
1941public:
1942 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001943 bool IsArray_, Prec Prec_)
1944 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
1945 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001946
1947 template<typename Fn> void match(Fn F) const {
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001948 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00001949 }
1950
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001951 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001952 if (IsGlobal)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001953 OB += "::";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001954 OB += "new";
Richard Smithc20d1442018-08-20 20:14:49 +00001955 if (IsArray)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001956 OB += "[]";
Richard Smithc20d1442018-08-20 20:14:49 +00001957 if (!ExprList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001958 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001959 ExprList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001960 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001961 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001962 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001963 Type->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001964 if (!InitList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001965 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001966 InitList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001967 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001968 }
Richard Smithc20d1442018-08-20 20:14:49 +00001969 }
1970};
1971
1972class DeleteExpr : public Node {
1973 Node *Op;
1974 bool IsGlobal;
1975 bool IsArray;
1976
1977public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001978 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
1979 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
1980 IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001981
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001982 template <typename Fn> void match(Fn F) const {
1983 F(Op, IsGlobal, IsArray, getPrecedence());
1984 }
Richard Smithc20d1442018-08-20 20:14:49 +00001985
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001986 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001987 if (IsGlobal)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001988 OB += "::";
1989 OB += "delete";
Richard Smithc20d1442018-08-20 20:14:49 +00001990 if (IsArray)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001991 OB += "[]";
1992 OB += ' ';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001993 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001994 }
1995};
1996
1997class PrefixExpr : public Node {
1998 StringView Prefix;
1999 Node *Child;
2000
2001public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002002 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
2003 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002004
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002005 template <typename Fn> void match(Fn F) const {
2006 F(Prefix, Child, getPrecedence());
2007 }
Richard Smithc20d1442018-08-20 20:14:49 +00002008
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002009 void printLeft(OutputBuffer &OB) const override {
2010 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002011 Child->printAsOperand(OB, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00002012 }
2013};
2014
2015class FunctionParam : public Node {
2016 StringView Number;
2017
2018public:
2019 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
2020
2021 template<typename Fn> void match(Fn F) const { F(Number); }
2022
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002023 void printLeft(OutputBuffer &OB) const override {
2024 OB += "fp";
2025 OB += Number;
Richard Smithc20d1442018-08-20 20:14:49 +00002026 }
2027};
2028
2029class ConversionExpr : public Node {
2030 const Node *Type;
2031 NodeArray Expressions;
2032
2033public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002034 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2035 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002036
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002037 template <typename Fn> void match(Fn F) const {
2038 F(Type, Expressions, getPrecedence());
2039 }
Richard Smithc20d1442018-08-20 20:14:49 +00002040
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002041 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002042 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002043 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002044 OB.printClose();
2045 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002046 Expressions.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002047 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002048 }
2049};
2050
Richard Smith1865d2f2020-10-22 19:29:36 -07002051class PointerToMemberConversionExpr : public Node {
2052 const Node *Type;
2053 const Node *SubExpr;
2054 StringView Offset;
2055
2056public:
2057 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002058 StringView Offset_, Prec Prec_)
2059 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2060 SubExpr(SubExpr_), Offset(Offset_) {}
Richard Smith1865d2f2020-10-22 19:29:36 -07002061
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002062 template <typename Fn> void match(Fn F) const {
2063 F(Type, SubExpr, Offset, getPrecedence());
2064 }
Richard Smith1865d2f2020-10-22 19:29:36 -07002065
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002066 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002067 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002068 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002069 OB.printClose();
2070 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002071 SubExpr->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002072 OB.printClose();
Richard Smith1865d2f2020-10-22 19:29:36 -07002073 }
2074};
2075
Richard Smithc20d1442018-08-20 20:14:49 +00002076class InitListExpr : public Node {
2077 const Node *Ty;
2078 NodeArray Inits;
2079public:
2080 InitListExpr(const Node *Ty_, NodeArray Inits_)
2081 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2082
2083 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2084
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002085 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002086 if (Ty)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002087 Ty->print(OB);
2088 OB += '{';
2089 Inits.printWithComma(OB);
2090 OB += '}';
Richard Smithc20d1442018-08-20 20:14:49 +00002091 }
2092};
2093
2094class BracedExpr : public Node {
2095 const Node *Elem;
2096 const Node *Init;
2097 bool IsArray;
2098public:
2099 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2100 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2101
2102 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
2103
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002104 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002105 if (IsArray) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002106 OB += '[';
2107 Elem->print(OB);
2108 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002109 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002110 OB += '.';
2111 Elem->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002112 }
2113 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002114 OB += " = ";
2115 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002116 }
2117};
2118
2119class BracedRangeExpr : public Node {
2120 const Node *First;
2121 const Node *Last;
2122 const Node *Init;
2123public:
2124 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2125 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2126
2127 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2128
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002129 void printLeft(OutputBuffer &OB) const override {
2130 OB += '[';
2131 First->print(OB);
2132 OB += " ... ";
2133 Last->print(OB);
2134 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002135 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002136 OB += " = ";
2137 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002138 }
2139};
2140
2141class FoldExpr : public Node {
2142 const Node *Pack, *Init;
2143 StringView OperatorName;
2144 bool IsLeftFold;
2145
2146public:
2147 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
2148 const Node *Init_)
2149 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2150 IsLeftFold(IsLeftFold_) {}
2151
2152 template<typename Fn> void match(Fn F) const {
2153 F(IsLeftFold, OperatorName, Pack, Init);
2154 }
2155
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002156 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002157 auto PrintPack = [&] {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002158 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002159 ParameterPackExpansion(Pack).print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002160 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002161 };
2162
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002163 OB.printOpen();
2164 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2165 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2166 // Fold expr operands are cast-expressions
2167 if (!IsLeftFold || Init != nullptr) {
2168 // '(init|pack) op '
2169 if (IsLeftFold)
2170 Init->printAsOperand(OB, Prec::Cast, true);
2171 else
2172 PrintPack();
2173 OB << " " << OperatorName << " ";
Richard Smithc20d1442018-08-20 20:14:49 +00002174 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002175 OB << "...";
2176 if (IsLeftFold || Init != nullptr) {
2177 // ' op (init|pack)'
2178 OB << " " << OperatorName << " ";
2179 if (IsLeftFold)
2180 PrintPack();
2181 else
2182 Init->printAsOperand(OB, Prec::Cast, true);
2183 }
2184 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002185 }
2186};
2187
2188class ThrowExpr : public Node {
2189 const Node *Op;
2190
2191public:
2192 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2193
2194 template<typename Fn> void match(Fn F) const { F(Op); }
2195
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002196 void printLeft(OutputBuffer &OB) const override {
2197 OB += "throw ";
2198 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002199 }
2200};
2201
2202class BoolExpr : public Node {
2203 bool Value;
2204
2205public:
2206 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2207
2208 template<typename Fn> void match(Fn F) const { F(Value); }
2209
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002210 void printLeft(OutputBuffer &OB) const override {
2211 OB += Value ? StringView("true") : StringView("false");
Richard Smithc20d1442018-08-20 20:14:49 +00002212 }
2213};
2214
Richard Smithdf1c14c2019-09-06 23:53:21 +00002215class StringLiteral : public Node {
2216 const Node *Type;
2217
2218public:
2219 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2220
2221 template<typename Fn> void match(Fn F) const { F(Type); }
2222
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002223 void printLeft(OutputBuffer &OB) const override {
2224 OB += "\"<";
2225 Type->print(OB);
2226 OB += ">\"";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002227 }
2228};
2229
2230class LambdaExpr : public Node {
2231 const Node *Type;
2232
Richard Smithdf1c14c2019-09-06 23:53:21 +00002233public:
2234 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2235
2236 template<typename Fn> void match(Fn F) const { F(Type); }
2237
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002238 void printLeft(OutputBuffer &OB) const override {
2239 OB += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002240 if (Type->getKind() == KClosureTypeName)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002241 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2242 OB += "{...}";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002243 }
2244};
2245
Erik Pilkington0a170f12020-05-13 14:13:37 -04002246class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002247 // ty(integer)
2248 const Node *Ty;
2249 StringView Integer;
2250
2251public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002252 EnumLiteral(const Node *Ty_, StringView Integer_)
2253 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002254
2255 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2256
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002257 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002258 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002259 Ty->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002260 OB.printClose();
Erik Pilkington0a170f12020-05-13 14:13:37 -04002261
2262 if (Integer[0] == 'n')
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002263 OB << "-" << Integer.dropFront(1);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002264 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002265 OB << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002266 }
2267};
2268
2269class IntegerLiteral : public Node {
2270 StringView Type;
2271 StringView Value;
2272
2273public:
2274 IntegerLiteral(StringView Type_, StringView Value_)
2275 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2276
2277 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2278
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002279 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002280 if (Type.size() > 3) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002281 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002282 OB += Type;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002283 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002284 }
2285
2286 if (Value[0] == 'n') {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002287 OB += '-';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002288 OB += Value.dropFront(1);
Richard Smithc20d1442018-08-20 20:14:49 +00002289 } else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002290 OB += Value;
Richard Smithc20d1442018-08-20 20:14:49 +00002291
2292 if (Type.size() <= 3)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002293 OB += Type;
Richard Smithc20d1442018-08-20 20:14:49 +00002294 }
2295};
2296
2297template <class Float> struct FloatData;
2298
2299namespace float_literal_impl {
2300constexpr Node::Kind getFloatLiteralKind(float *) {
2301 return Node::KFloatLiteral;
2302}
2303constexpr Node::Kind getFloatLiteralKind(double *) {
2304 return Node::KDoubleLiteral;
2305}
2306constexpr Node::Kind getFloatLiteralKind(long double *) {
2307 return Node::KLongDoubleLiteral;
2308}
2309}
2310
2311template <class Float> class FloatLiteralImpl : public Node {
2312 const StringView Contents;
2313
2314 static constexpr Kind KindForClass =
2315 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2316
2317public:
2318 FloatLiteralImpl(StringView Contents_)
2319 : Node(KindForClass), Contents(Contents_) {}
2320
2321 template<typename Fn> void match(Fn F) const { F(Contents); }
2322
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002323 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002324 const char *first = Contents.begin();
2325 const char *last = Contents.end() + 1;
2326
2327 const size_t N = FloatData<Float>::mangled_size;
2328 if (static_cast<std::size_t>(last - first) > N) {
2329 last = first + N;
2330 union {
2331 Float value;
2332 char buf[sizeof(Float)];
2333 };
2334 const char *t = first;
2335 char *e = buf;
2336 for (; t != last; ++t, ++e) {
2337 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2338 : static_cast<unsigned>(*t - 'a' + 10);
2339 ++t;
2340 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2341 : static_cast<unsigned>(*t - 'a' + 10);
2342 *e = static_cast<char>((d1 << 4) + d0);
2343 }
2344#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2345 std::reverse(buf, e);
2346#endif
2347 char num[FloatData<Float>::max_demangled_size] = {0};
2348 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002349 OB += StringView(num, num + n);
Richard Smithc20d1442018-08-20 20:14:49 +00002350 }
2351 }
2352};
2353
2354using FloatLiteral = FloatLiteralImpl<float>;
2355using DoubleLiteral = FloatLiteralImpl<double>;
2356using LongDoubleLiteral = FloatLiteralImpl<long double>;
2357
2358/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2359/// appropriate derived class.
2360template<typename Fn>
2361void Node::visit(Fn F) const {
2362 switch (K) {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002363#define NODE(X) \
2364 case K##X: \
2365 return F(static_cast<const X *>(this));
2366#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002367 }
2368 assert(0 && "unknown mangling node kind");
2369}
2370
2371/// Determine the kind of a node from its type.
2372template<typename NodeT> struct NodeKind;
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002373#define NODE(X) \
2374 template <> struct NodeKind<X> { \
2375 static constexpr Node::Kind Kind = Node::K##X; \
2376 static constexpr const char *name() { return #X; } \
Richard Smithc20d1442018-08-20 20:14:49 +00002377 };
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002378#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002379
Pavel Labathba825192018-10-16 14:29:14 +00002380template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002381 const char *First;
2382 const char *Last;
2383
2384 // Name stack, this is used by the parser to hold temporary names that were
2385 // parsed. The parser collapses multiple names into new nodes to construct
2386 // the AST. Once the parser is finished, names.size() == 1.
2387 PODSmallVector<Node *, 32> Names;
2388
2389 // Substitution table. Itanium supports name substitutions as a means of
2390 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2391 // table.
2392 PODSmallVector<Node *, 32> Subs;
2393
Richard Smithdf1c14c2019-09-06 23:53:21 +00002394 using TemplateParamList = PODSmallVector<Node *, 8>;
2395
2396 class ScopedTemplateParamList {
2397 AbstractManglingParser *Parser;
2398 size_t OldNumTemplateParamLists;
2399 TemplateParamList Params;
2400
2401 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002402 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2403 : Parser(TheParser),
2404 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002405 Parser->TemplateParams.push_back(&Params);
2406 }
2407 ~ScopedTemplateParamList() {
2408 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2409 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2410 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002411 };
2412
Richard Smithc20d1442018-08-20 20:14:49 +00002413 // Template parameter table. Like the above, but referenced like "T42_".
2414 // This has a smaller size compared to Subs and Names because it can be
2415 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002416 TemplateParamList OuterTemplateParams;
2417
2418 // Lists of template parameters indexed by template parameter depth,
2419 // referenced like "TL2_4_". If nonempty, element 0 is always
2420 // OuterTemplateParams; inner elements are always template parameter lists of
2421 // lambda expressions. For a generic lambda with no explicit template
2422 // parameter list, the corresponding parameter list pointer will be null.
2423 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002424
2425 // Set of unresolved forward <template-param> references. These can occur in a
2426 // conversion operator's type, and are resolved in the enclosing <encoding>.
2427 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2428
Richard Smithc20d1442018-08-20 20:14:49 +00002429 bool TryToParseTemplateArgs = true;
2430 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002431 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2432
2433 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002434
2435 Alloc ASTAllocator;
2436
Pavel Labathba825192018-10-16 14:29:14 +00002437 AbstractManglingParser(const char *First_, const char *Last_)
2438 : First(First_), Last(Last_) {}
2439
2440 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002441
2442 void reset(const char *First_, const char *Last_) {
2443 First = First_;
2444 Last = Last_;
2445 Names.clear();
2446 Subs.clear();
2447 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002448 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002449 TryToParseTemplateArgs = true;
2450 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002451 for (int I = 0; I != 3; ++I)
2452 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002453 ASTAllocator.reset();
2454 }
2455
Richard Smithb485b352018-08-24 23:30:26 +00002456 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002457 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2458 }
2459
2460 template <class It> NodeArray makeNodeArray(It begin, It end) {
2461 size_t sz = static_cast<size_t>(end - begin);
2462 void *mem = ASTAllocator.allocateNodeArray(sz);
2463 Node **data = new (mem) Node *[sz];
2464 std::copy(begin, end, data);
2465 return NodeArray(data, sz);
2466 }
2467
2468 NodeArray popTrailingNodeArray(size_t FromPosition) {
2469 assert(FromPosition <= Names.size());
2470 NodeArray res =
2471 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2472 Names.dropBack(FromPosition);
2473 return res;
2474 }
2475
2476 bool consumeIf(StringView S) {
2477 if (StringView(First, Last).startsWith(S)) {
2478 First += S.size();
2479 return true;
2480 }
2481 return false;
2482 }
2483
2484 bool consumeIf(char C) {
2485 if (First != Last && *First == C) {
2486 ++First;
2487 return true;
2488 }
2489 return false;
2490 }
2491
2492 char consume() { return First != Last ? *First++ : '\0'; }
2493
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08002494 char look(unsigned Lookahead = 0) const {
Richard Smithc20d1442018-08-20 20:14:49 +00002495 if (static_cast<size_t>(Last - First) <= Lookahead)
2496 return '\0';
2497 return First[Lookahead];
2498 }
2499
2500 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2501
2502 StringView parseNumber(bool AllowNegative = false);
2503 Qualifiers parseCVQualifiers();
2504 bool parsePositiveInteger(size_t *Out);
2505 StringView parseBareSourceName();
2506
2507 bool parseSeqId(size_t *Out);
2508 Node *parseSubstitution();
2509 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002510 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002511 Node *parseTemplateArgs(bool TagTemplates = false);
2512 Node *parseTemplateArg();
2513
2514 /// Parse the <expr> production.
2515 Node *parseExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002516 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2517 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00002518 Node *parseIntegerLiteral(StringView Lit);
2519 Node *parseExprPrimary();
2520 template <class Float> Node *parseFloatingLiteral();
2521 Node *parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00002522 Node *parseConversionExpr();
2523 Node *parseBracedExpr();
2524 Node *parseFoldExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002525 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07002526 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002527
2528 /// Parse the <type> production.
2529 Node *parseType();
2530 Node *parseFunctionType();
2531 Node *parseVectorType();
2532 Node *parseDecltype();
2533 Node *parseArrayType();
2534 Node *parsePointerToMemberType();
2535 Node *parseClassEnumType();
2536 Node *parseQualifiedType();
2537
2538 Node *parseEncoding();
2539 bool parseCallOffset();
2540 Node *parseSpecialName();
2541
2542 /// Holds some extra information about a <name> that is being parsed. This
2543 /// information is only pertinent if the <name> refers to an <encoding>.
2544 struct NameState {
2545 bool CtorDtorConversion = false;
2546 bool EndsWithTemplateArgs = false;
2547 Qualifiers CVQualifiers = QualNone;
2548 FunctionRefQual ReferenceQualifier = FrefQualNone;
2549 size_t ForwardTemplateRefsBegin;
2550
Pavel Labathba825192018-10-16 14:29:14 +00002551 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002552 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2553 };
2554
2555 bool resolveForwardTemplateRefs(NameState &State) {
2556 size_t I = State.ForwardTemplateRefsBegin;
2557 size_t E = ForwardTemplateRefs.size();
2558 for (; I < E; ++I) {
2559 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002560 if (TemplateParams.empty() || !TemplateParams[0] ||
2561 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002562 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002563 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002564 }
2565 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2566 return false;
2567 }
2568
2569 /// Parse the <name> production>
2570 Node *parseName(NameState *State = nullptr);
2571 Node *parseLocalName(NameState *State);
2572 Node *parseOperatorName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002573 bool parseModuleNameOpt(ModuleName *&Module);
2574 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
Richard Smithc20d1442018-08-20 20:14:49 +00002575 Node *parseUnnamedTypeName(NameState *State);
2576 Node *parseSourceName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002577 Node *parseUnscopedName(NameState *State, bool *isSubstName);
Richard Smithc20d1442018-08-20 20:14:49 +00002578 Node *parseNestedName(NameState *State);
2579 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2580
2581 Node *parseAbiTags(Node *N);
2582
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002583 struct OperatorInfo {
2584 enum OIKind : unsigned char {
2585 Prefix, // Prefix unary: @ expr
2586 Postfix, // Postfix unary: expr @
2587 Binary, // Binary: lhs @ rhs
2588 Array, // Array index: lhs [ rhs ]
2589 Member, // Member access: lhs @ rhs
2590 New, // New
2591 Del, // Delete
2592 Call, // Function call: expr (expr*)
2593 CCast, // C cast: (type)expr
2594 Conditional, // Conditional: expr ? expr : expr
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08002595 NameOnly, // Overload only, not allowed in expression.
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002596 // Below do not have operator names
2597 NamedCast, // Named cast, @<type>(expr)
2598 OfIdOp, // alignof, sizeof, typeid
2599
2600 Unnameable = NamedCast,
2601 };
2602 char Enc[2]; // Encoding
2603 OIKind Kind; // Kind of operator
2604 bool Flag : 1; // Entry-specific flag
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002605 Node::Prec Prec : 7; // Precedence
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002606 const char *Name; // Spelling
2607
2608 public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002609 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2610 const char *N)
2611 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002612
2613 public:
2614 bool operator<(const OperatorInfo &Other) const {
2615 return *this < Other.Enc;
2616 }
2617 bool operator<(const char *Peek) const {
2618 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2619 }
2620 bool operator==(const char *Peek) const {
2621 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2622 }
2623 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2624
2625 public:
2626 StringView getSymbol() const {
2627 StringView Res = Name;
2628 if (Kind < Unnameable) {
2629 assert(Res.startsWith("operator") &&
2630 "operator name does not start with 'operator'");
2631 Res = Res.dropFront(sizeof("operator") - 1);
2632 Res.consumeFront(' ');
2633 }
2634 return Res;
2635 }
2636 StringView getName() const { return Name; }
2637 OIKind getKind() const { return Kind; }
2638 bool getFlag() const { return Flag; }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002639 Node::Prec getPrecedence() const { return Prec; }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002640 };
2641 const OperatorInfo *parseOperatorEncoding();
2642
Richard Smithc20d1442018-08-20 20:14:49 +00002643 /// Parse the <unresolved-name> production.
Nathan Sidwell77c52e22022-01-28 11:59:03 -08002644 Node *parseUnresolvedName(bool Global);
Richard Smithc20d1442018-08-20 20:14:49 +00002645 Node *parseSimpleId();
2646 Node *parseBaseUnresolvedName();
2647 Node *parseUnresolvedType();
2648 Node *parseDestructorName();
2649
2650 /// Top-level entry point into the parser.
2651 Node *parse();
2652};
2653
2654const char* parse_discriminator(const char* first, const char* last);
2655
2656// <name> ::= <nested-name> // N
2657// ::= <local-name> # See Scope Encoding below // Z
2658// ::= <unscoped-template-name> <template-args>
2659// ::= <unscoped-name>
2660//
2661// <unscoped-template-name> ::= <unscoped-name>
2662// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002663template <typename Derived, typename Alloc>
2664Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002665 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002666 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002667 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002668 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002669
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002670 Node *Result = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002671 bool IsSubst = false;
2672
2673 Result = getDerived().parseUnscopedName(State, &IsSubst);
2674 if (!Result)
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002675 return nullptr;
2676
2677 if (look() == 'I') {
2678 // ::= <unscoped-template-name> <template-args>
2679 if (!IsSubst)
2680 // An unscoped-template-name is substitutable.
2681 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00002682 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002683 if (TA == nullptr)
2684 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002685 if (State)
2686 State->EndsWithTemplateArgs = true;
2687 Result = make<NameWithTemplateArgs>(Result, TA);
2688 } else if (IsSubst) {
2689 // The substitution case must be followed by <template-args>.
2690 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002691 }
2692
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002693 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00002694}
2695
2696// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2697// := Z <function encoding> E s [<discriminator>]
2698// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002699template <typename Derived, typename Alloc>
2700Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002701 if (!consumeIf('Z'))
2702 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002703 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002704 if (Encoding == nullptr || !consumeIf('E'))
2705 return nullptr;
2706
2707 if (consumeIf('s')) {
2708 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002709 auto *StringLitName = make<NameType>("string literal");
2710 if (!StringLitName)
2711 return nullptr;
2712 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002713 }
2714
2715 if (consumeIf('d')) {
2716 parseNumber(true);
2717 if (!consumeIf('_'))
2718 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002719 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002720 if (N == nullptr)
2721 return nullptr;
2722 return make<LocalName>(Encoding, N);
2723 }
2724
Pavel Labathba825192018-10-16 14:29:14 +00002725 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002726 if (Entity == nullptr)
2727 return nullptr;
2728 First = parse_discriminator(First, Last);
2729 return make<LocalName>(Encoding, Entity);
2730}
2731
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08002732// <unscoped-name> ::= [L]* <unqualified-name>
2733// ::= St [L]* <unqualified-name> # ::std::
2734// [*] extension
Pavel Labathba825192018-10-16 14:29:14 +00002735template <typename Derived, typename Alloc>
2736Node *
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002737AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2738 bool *IsSubst) {
2739
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002740 Node *Std = nullptr;
2741 if (consumeIf("St")) {
2742 Std = make<NameType>("std");
2743 if (Std == nullptr)
Nathan Sidwell200e97c2022-01-21 11:37:01 -08002744 return nullptr;
2745 }
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002746 consumeIf('L');
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002747
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002748 Node *Res = nullptr;
2749 ModuleName *Module = nullptr;
2750 if (look() == 'S') {
2751 Node *S = getDerived().parseSubstitution();
2752 if (!S)
2753 return nullptr;
2754 if (S->getKind() == Node::KModuleName)
2755 Module = static_cast<ModuleName *>(S);
2756 else if (IsSubst && Std == nullptr) {
2757 Res = S;
2758 *IsSubst = true;
2759 } else {
2760 return nullptr;
2761 }
2762 }
2763
2764 if (Res == nullptr)
2765 Res = getDerived().parseUnqualifiedName(State, Std, Module);
2766
2767 return Res;
Richard Smithc20d1442018-08-20 20:14:49 +00002768}
2769
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002770// <unqualified-name> ::= [<module-name>] <operator-name> [<abi-tags>]
2771// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
2772// ::= [<module-name>] <source-name> [<abi-tags>]
2773// ::= [<module-name>] <unnamed-type-name> [<abi-tags>]
2774// # structured binding declaration
2775// ::= [<module-name>] DC <source-name>+ E
Pavel Labathba825192018-10-16 14:29:14 +00002776template <typename Derived, typename Alloc>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002777Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2778 NameState *State, Node *Scope, ModuleName *Module) {
2779 if (getDerived().parseModuleNameOpt(Module))
2780 return nullptr;
2781
Richard Smithc20d1442018-08-20 20:14:49 +00002782 Node *Result;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002783 if (look() == 'U') {
Pavel Labathba825192018-10-16 14:29:14 +00002784 Result = getDerived().parseUnnamedTypeName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002785 } else if (look() >= '1' && look() <= '9') {
Pavel Labathba825192018-10-16 14:29:14 +00002786 Result = getDerived().parseSourceName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002787 } else if (consumeIf("DC")) {
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002788 // Structured binding
Richard Smithc20d1442018-08-20 20:14:49 +00002789 size_t BindingsBegin = Names.size();
2790 do {
Pavel Labathba825192018-10-16 14:29:14 +00002791 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002792 if (Binding == nullptr)
2793 return nullptr;
2794 Names.push_back(Binding);
2795 } while (!consumeIf('E'));
2796 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002797 } else if (look() == 'C' || look() == 'D') {
2798 // A <ctor-dtor-name>.
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002799 if (Scope == nullptr || Module != nullptr)
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002800 return nullptr;
2801 Result = getDerived().parseCtorDtorName(Scope, State);
2802 } else {
Pavel Labathba825192018-10-16 14:29:14 +00002803 Result = getDerived().parseOperatorName(State);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002804 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002805
David Blaikie019fb1b2022-03-30 20:18:40 +00002806 if (Result != nullptr && Module != nullptr)
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002807 Result = make<ModuleEntity>(Module, Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002808 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002809 Result = getDerived().parseAbiTags(Result);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002810 if (Result != nullptr && Scope != nullptr)
2811 Result = make<NestedName>(Scope, Result);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002812
Richard Smithc20d1442018-08-20 20:14:49 +00002813 return Result;
2814}
2815
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002816// <module-name> ::= <module-subname>
2817// ::= <module-name> <module-subname>
2818// ::= <substitution> # passed in by caller
2819// <module-subname> ::= W <source-name>
2820// ::= W P <source-name>
2821template <typename Derived, typename Alloc>
2822bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2823 ModuleName *&Module) {
2824 while (consumeIf('W')) {
2825 bool IsPartition = consumeIf('P');
2826 Node *Sub = getDerived().parseSourceName(nullptr);
2827 if (!Sub)
2828 return true;
2829 Module =
2830 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2831 Subs.push_back(Module);
2832 }
2833
2834 return false;
2835}
2836
Richard Smithc20d1442018-08-20 20:14:49 +00002837// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2838// ::= <closure-type-name>
2839//
2840// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2841//
2842// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002843template <typename Derived, typename Alloc>
2844Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002845AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2846 // <template-params> refer to the innermost <template-args>. Clear out any
2847 // outer args that we may have inserted into TemplateParams.
2848 if (State != nullptr)
2849 TemplateParams.clear();
2850
Richard Smithc20d1442018-08-20 20:14:49 +00002851 if (consumeIf("Ut")) {
2852 StringView Count = parseNumber();
2853 if (!consumeIf('_'))
2854 return nullptr;
2855 return make<UnnamedTypeName>(Count);
2856 }
2857 if (consumeIf("Ul")) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002858 SwapAndRestore<size_t> SwapParams(ParsingLambdaParamsAtLevel,
2859 TemplateParams.size());
2860 ScopedTemplateParamList LambdaTemplateParams(this);
2861
2862 size_t ParamsBegin = Names.size();
2863 while (look() == 'T' &&
2864 StringView("yptn").find(look(1)) != StringView::npos) {
2865 Node *T = parseTemplateParamDecl();
2866 if (!T)
2867 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002868 Names.push_back(T);
2869 }
2870 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2871
2872 // FIXME: If TempParams is empty and none of the function parameters
2873 // includes 'auto', we should remove LambdaTemplateParams from the
2874 // TemplateParams list. Unfortunately, we don't find out whether there are
2875 // any 'auto' parameters until too late in an example such as:
2876 //
2877 // template<typename T> void f(
2878 // decltype([](decltype([]<typename T>(T v) {}),
2879 // auto) {})) {}
2880 // template<typename T> void f(
2881 // decltype([](decltype([]<typename T>(T w) {}),
2882 // int) {})) {}
2883 //
2884 // Here, the type of v is at level 2 but the type of w is at level 1. We
2885 // don't find this out until we encounter the type of the next parameter.
2886 //
2887 // However, compilers can't actually cope with the former example in
2888 // practice, and it's likely to be made ill-formed in future, so we don't
2889 // need to support it here.
2890 //
2891 // If we encounter an 'auto' in the function parameter types, we will
2892 // recreate a template parameter scope for it, but any intervening lambdas
2893 // will be parsed in the 'wrong' template parameter depth.
2894 if (TempParams.empty())
2895 TemplateParams.pop_back();
2896
Richard Smithc20d1442018-08-20 20:14:49 +00002897 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002898 do {
Pavel Labathba825192018-10-16 14:29:14 +00002899 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002900 if (P == nullptr)
2901 return nullptr;
2902 Names.push_back(P);
2903 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002904 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002905 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2906
Richard Smithc20d1442018-08-20 20:14:49 +00002907 StringView Count = parseNumber();
2908 if (!consumeIf('_'))
2909 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002910 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002911 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002912 if (consumeIf("Ub")) {
2913 (void)parseNumber();
2914 if (!consumeIf('_'))
2915 return nullptr;
2916 return make<NameType>("'block-literal'");
2917 }
Richard Smithc20d1442018-08-20 20:14:49 +00002918 return nullptr;
2919}
2920
2921// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002922template <typename Derived, typename Alloc>
2923Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002924 size_t Length = 0;
2925 if (parsePositiveInteger(&Length))
2926 return nullptr;
2927 if (numLeft() < Length || Length == 0)
2928 return nullptr;
2929 StringView Name(First, First + Length);
2930 First += Length;
2931 if (Name.startsWith("_GLOBAL__N"))
2932 return make<NameType>("(anonymous namespace)");
2933 return make<NameType>(Name);
2934}
2935
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002936// If the next 2 chars are an operator encoding, consume them and return their
2937// OperatorInfo. Otherwise return nullptr.
2938template <typename Derived, typename Alloc>
2939const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
2940AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
2941 static const OperatorInfo Ops[] = {
2942 // Keep ordered by encoding
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002943 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
2944 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
2945 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
2946 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
2947 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
2948 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary,
2949 "alignof "},
2950 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
2951 "operator co_await"},
2952 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
2953 "alignof "},
2954 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
2955 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
2956 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
2957 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
2958 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast,
2959 "operator"}, // C Cast
2960 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
2961 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
2962 "operator delete[]"},
2963 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
2964 "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,
2995 "operator new"},
2996 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
2997 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
2998 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
2999 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
3000 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
3001 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3002 "operator->*"},
3003 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
3004 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
3005 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
3006 "operator->"},
3007 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
3008 "operator?"},
3009 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
3010 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
3011 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3012 "reinterpret_cast"},
3013 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3014 "operator%"},
3015 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3016 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3017 "static_cast"},
3018 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3019 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3020 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
3021 "sizeof "},
3022 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3023 "typeid "},
3024 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix,
3025 "typeid "},
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003026 };
3027 const auto NumOps = sizeof(Ops) / sizeof(Ops[0]);
3028
3029#ifndef NDEBUG
3030 {
3031 // Verify table order.
3032 static bool Done;
3033 if (!Done) {
3034 Done = true;
3035 for (const auto *Op = &Ops[0]; Op != &Ops[NumOps - 1]; Op++)
3036 assert(Op[0] < Op[1] && "Operator table is not ordered");
3037 }
3038 }
3039#endif
3040
3041 if (numLeft() < 2)
3042 return nullptr;
3043
3044 auto Op = std::lower_bound(
3045 &Ops[0], &Ops[NumOps], First,
3046 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3047 if (Op == &Ops[NumOps] || *Op != First)
3048 return nullptr;
3049
3050 First += 2;
3051 return Op;
3052}
3053
3054// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003055// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003056// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003057template <typename Derived, typename Alloc>
3058Node *
3059AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003060 if (const auto *Op = parseOperatorEncoding()) {
3061 if (Op->getKind() == OperatorInfo::CCast) {
3062 // ::= cv <type> # (cast)
Richard Smithc20d1442018-08-20 20:14:49 +00003063 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
3064 // If we're parsing an encoding, State != nullptr and the conversion
3065 // operators' <type> could have a <template-param> that refers to some
3066 // <template-arg>s further ahead in the mangled name.
3067 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
3068 PermitForwardTemplateReferences ||
3069 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003070 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003071 if (Ty == nullptr)
3072 return nullptr;
3073 if (State) State->CtorDtorConversion = true;
3074 return make<ConversionOperatorType>(Ty);
3075 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003076
3077 if (Op->getKind() >= OperatorInfo::Unnameable)
3078 /* Not a nameable operator. */
3079 return nullptr;
3080 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3081 /* Not a nameable MemberExpr */
3082 return nullptr;
3083
3084 return make<NameType>(Op->getName());
3085 }
3086
3087 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003088 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003089 Node *SN = getDerived().parseSourceName(State);
3090 if (SN == nullptr)
3091 return nullptr;
3092 return make<LiteralOperator>(SN);
3093 }
3094
3095 if (consumeIf('v')) {
3096 // ::= v <digit> <source-name> # vendor extended operator
3097 if (look() >= '0' && look() <= '9') {
3098 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003099 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003100 if (SN == nullptr)
3101 return nullptr;
3102 return make<ConversionOperatorType>(SN);
3103 }
3104 return nullptr;
3105 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003106
Richard Smithc20d1442018-08-20 20:14:49 +00003107 return nullptr;
3108}
3109
3110// <ctor-dtor-name> ::= C1 # complete object constructor
3111// ::= C2 # base object constructor
3112// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003113// extension ::= C4 # gcc old-style "[unified]" constructor
3114// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003115// ::= D0 # deleting destructor
3116// ::= D1 # complete object destructor
3117// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003118// extension ::= D4 # gcc old-style "[unified]" destructor
3119// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003120template <typename Derived, typename Alloc>
3121Node *
3122AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3123 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003124 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3125 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3126 switch (SSK) {
3127 case SpecialSubKind::string:
3128 case SpecialSubKind::istream:
3129 case SpecialSubKind::ostream:
3130 case SpecialSubKind::iostream:
3131 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00003132 if (!SoFar)
3133 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00003134 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003135 default:
3136 break;
3137 }
3138 }
3139
3140 if (consumeIf('C')) {
3141 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003142 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3143 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003144 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003145 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003146 ++First;
3147 if (State) State->CtorDtorConversion = true;
3148 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003149 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003150 return nullptr;
3151 }
Nico Weber29294792019-04-03 23:14:33 +00003152 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003153 }
3154
Nico Weber29294792019-04-03 23:14:33 +00003155 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3156 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003157 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003158 First += 2;
3159 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003160 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003161 }
3162
3163 return nullptr;
3164}
3165
3166// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3167// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3168//
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003169// <prefix> ::= <prefix> [L]* <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003170// ::= <template-prefix> <template-args>
3171// ::= <template-param>
3172// ::= <decltype>
3173// ::= # empty
3174// ::= <substitution>
3175// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003176// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003177//
3178// <data-member-prefix> := <member source-name> [<template-args>] M
3179//
3180// <template-prefix> ::= <prefix> <template unqualified-name>
3181// ::= <template-param>
3182// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003183template <typename Derived, typename Alloc>
3184Node *
3185AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003186 if (!consumeIf('N'))
3187 return nullptr;
3188
3189 Qualifiers CVTmp = parseCVQualifiers();
3190 if (State) State->CVQualifiers = CVTmp;
3191
3192 if (consumeIf('O')) {
3193 if (State) State->ReferenceQualifier = FrefQualRValue;
3194 } else if (consumeIf('R')) {
3195 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003196 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003197 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003198 }
Richard Smithc20d1442018-08-20 20:14:49 +00003199
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003200 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003201 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003202 if (State)
3203 // Only set end-with-template on the case that does that.
3204 State->EndsWithTemplateArgs = false;
3205
Richard Smithc20d1442018-08-20 20:14:49 +00003206 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003207 // ::= <template-param>
3208 if (SoFar != nullptr)
3209 return nullptr; // Cannot have a prefix.
3210 SoFar = getDerived().parseTemplateParam();
3211 } else if (look() == 'I') {
3212 // ::= <template-prefix> <template-args>
3213 if (SoFar == nullptr)
3214 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003215 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003216 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003217 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003218 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3219 // Semantically <template-args> <template-args> cannot be generated by a
3220 // C++ entity. There will always be [something like] a name between
3221 // them.
3222 return nullptr;
3223 if (State)
3224 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003225 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003226 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3227 // ::= <decltype>
3228 if (SoFar != nullptr)
3229 return nullptr; // Cannot have a prefix.
3230 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003231 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003232 ModuleName *Module = nullptr;
3233 bool IsLocal = consumeIf('L'); // extension
3234
3235 if (look() == 'S') {
3236 // ::= <substitution>
3237 Node *S = nullptr;
3238 if (look(1) == 't') {
3239 First += 2;
3240 S = make<NameType>("std");
3241 } else {
3242 S = getDerived().parseSubstitution();
3243 }
3244 if (!S)
3245 return nullptr;
3246 if (S->getKind() == Node::KModuleName) {
3247 Module = static_cast<ModuleName *>(S);
3248 } else if (SoFar != nullptr || IsLocal) {
3249 return nullptr; // Cannot have a prefix.
3250 } else {
3251 SoFar = S;
3252 continue; // Do not push a new substitution.
3253 }
3254 }
3255
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003256 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003257 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003258 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003259
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003260 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003261 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003262 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003263
3264 // No longer used.
3265 // <data-member-prefix> := <member source-name> [<template-args>] M
3266 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003267 }
3268
3269 if (SoFar == nullptr || Subs.empty())
3270 return nullptr;
3271
3272 Subs.pop_back();
3273 return SoFar;
3274}
3275
3276// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003277template <typename Derived, typename Alloc>
3278Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3279 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003280 if (SN == nullptr)
3281 return nullptr;
3282 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003283 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003284 if (TA == nullptr)
3285 return nullptr;
3286 return make<NameWithTemplateArgs>(SN, TA);
3287 }
3288 return SN;
3289}
3290
3291// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3292// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003293template <typename Derived, typename Alloc>
3294Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003295 Node *Result;
3296 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003297 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003298 else
Pavel Labathba825192018-10-16 14:29:14 +00003299 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003300 if (Result == nullptr)
3301 return nullptr;
3302 return make<DtorName>(Result);
3303}
3304
3305// <unresolved-type> ::= <template-param>
3306// ::= <decltype>
3307// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003308template <typename Derived, typename Alloc>
3309Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003310 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003311 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003312 if (TP == nullptr)
3313 return nullptr;
3314 Subs.push_back(TP);
3315 return TP;
3316 }
3317 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003318 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003319 if (DT == nullptr)
3320 return nullptr;
3321 Subs.push_back(DT);
3322 return DT;
3323 }
Pavel Labathba825192018-10-16 14:29:14 +00003324 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003325}
3326
3327// <base-unresolved-name> ::= <simple-id> # unresolved name
3328// extension ::= <operator-name> # unresolved operator-function-id
3329// extension ::= <operator-name> <template-args> # unresolved operator template-id
3330// ::= on <operator-name> # unresolved operator-function-id
3331// ::= on <operator-name> <template-args> # unresolved operator template-id
3332// ::= dn <destructor-name> # destructor or pseudo-destructor;
3333// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003334template <typename Derived, typename Alloc>
3335Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003336 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003337 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003338
3339 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003340 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003341
3342 consumeIf("on");
3343
Pavel Labathba825192018-10-16 14:29:14 +00003344 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003345 if (Oper == nullptr)
3346 return nullptr;
3347 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003348 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003349 if (TA == nullptr)
3350 return nullptr;
3351 return make<NameWithTemplateArgs>(Oper, TA);
3352 }
3353 return Oper;
3354}
3355
3356// <unresolved-name>
3357// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3358// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3359// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3360// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003361// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003362// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3363// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3364// # T::N::x /decltype(p)::N::x
3365// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3366//
3367// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003368template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003369Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003370 Node *SoFar = nullptr;
3371
3372 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3373 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3374 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003375 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003376 if (SoFar == nullptr)
3377 return nullptr;
3378
3379 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003380 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003381 if (TA == nullptr)
3382 return nullptr;
3383 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003384 if (!SoFar)
3385 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003386 }
3387
3388 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003389 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003390 if (Qual == nullptr)
3391 return nullptr;
3392 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003393 if (!SoFar)
3394 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003395 }
3396
Pavel Labathba825192018-10-16 14:29:14 +00003397 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003398 if (Base == nullptr)
3399 return nullptr;
3400 return make<QualifiedName>(SoFar, Base);
3401 }
3402
Richard Smithc20d1442018-08-20 20:14:49 +00003403 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3404 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003405 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003406 if (SoFar == nullptr)
3407 return nullptr;
3408 if (Global)
3409 SoFar = make<GlobalQualifiedName>(SoFar);
3410 return SoFar;
3411 }
3412
3413 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3414 if (std::isdigit(look())) {
3415 do {
Pavel Labathba825192018-10-16 14:29:14 +00003416 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003417 if (Qual == nullptr)
3418 return nullptr;
3419 if (SoFar)
3420 SoFar = make<QualifiedName>(SoFar, Qual);
3421 else if (Global)
3422 SoFar = make<GlobalQualifiedName>(Qual);
3423 else
3424 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003425 if (!SoFar)
3426 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003427 } while (!consumeIf('E'));
3428 }
3429 // sr <unresolved-type> <base-unresolved-name>
3430 // sr <unresolved-type> <template-args> <base-unresolved-name>
3431 else {
Pavel Labathba825192018-10-16 14:29:14 +00003432 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003433 if (SoFar == nullptr)
3434 return nullptr;
3435
3436 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003437 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003438 if (TA == nullptr)
3439 return nullptr;
3440 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003441 if (!SoFar)
3442 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003443 }
3444 }
3445
3446 assert(SoFar != nullptr);
3447
Pavel Labathba825192018-10-16 14:29:14 +00003448 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003449 if (Base == nullptr)
3450 return nullptr;
3451 return make<QualifiedName>(SoFar, Base);
3452}
3453
3454// <abi-tags> ::= <abi-tag> [<abi-tags>]
3455// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003456template <typename Derived, typename Alloc>
3457Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003458 while (consumeIf('B')) {
3459 StringView SN = parseBareSourceName();
3460 if (SN.empty())
3461 return nullptr;
3462 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003463 if (!N)
3464 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003465 }
3466 return N;
3467}
3468
3469// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003470template <typename Alloc, typename Derived>
3471StringView
3472AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003473 const char *Tmp = First;
3474 if (AllowNegative)
3475 consumeIf('n');
3476 if (numLeft() == 0 || !std::isdigit(*First))
3477 return StringView();
3478 while (numLeft() != 0 && std::isdigit(*First))
3479 ++First;
3480 return StringView(Tmp, First);
3481}
3482
3483// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003484template <typename Alloc, typename Derived>
3485bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003486 *Out = 0;
3487 if (look() < '0' || look() > '9')
3488 return true;
3489 while (look() >= '0' && look() <= '9') {
3490 *Out *= 10;
3491 *Out += static_cast<size_t>(consume() - '0');
3492 }
3493 return false;
3494}
3495
Pavel Labathba825192018-10-16 14:29:14 +00003496template <typename Alloc, typename Derived>
3497StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003498 size_t Int = 0;
3499 if (parsePositiveInteger(&Int) || numLeft() < Int)
3500 return StringView();
3501 StringView R(First, First + Int);
3502 First += Int;
3503 return R;
3504}
3505
3506// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3507//
3508// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3509// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3510// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3511//
3512// <ref-qualifier> ::= R # & ref-qualifier
3513// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003514template <typename Derived, typename Alloc>
3515Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003516 Qualifiers CVQuals = parseCVQualifiers();
3517
3518 Node *ExceptionSpec = nullptr;
3519 if (consumeIf("Do")) {
3520 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003521 if (!ExceptionSpec)
3522 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003523 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003524 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003525 if (E == nullptr || !consumeIf('E'))
3526 return nullptr;
3527 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003528 if (!ExceptionSpec)
3529 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003530 } else if (consumeIf("Dw")) {
3531 size_t SpecsBegin = Names.size();
3532 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003533 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003534 if (T == nullptr)
3535 return nullptr;
3536 Names.push_back(T);
3537 }
3538 ExceptionSpec =
3539 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003540 if (!ExceptionSpec)
3541 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003542 }
3543
3544 consumeIf("Dx"); // transaction safe
3545
3546 if (!consumeIf('F'))
3547 return nullptr;
3548 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003549 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003550 if (ReturnType == nullptr)
3551 return nullptr;
3552
3553 FunctionRefQual ReferenceQualifier = FrefQualNone;
3554 size_t ParamsBegin = Names.size();
3555 while (true) {
3556 if (consumeIf('E'))
3557 break;
3558 if (consumeIf('v'))
3559 continue;
3560 if (consumeIf("RE")) {
3561 ReferenceQualifier = FrefQualLValue;
3562 break;
3563 }
3564 if (consumeIf("OE")) {
3565 ReferenceQualifier = FrefQualRValue;
3566 break;
3567 }
Pavel Labathba825192018-10-16 14:29:14 +00003568 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003569 if (T == nullptr)
3570 return nullptr;
3571 Names.push_back(T);
3572 }
3573
3574 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3575 return make<FunctionType>(ReturnType, Params, CVQuals,
3576 ReferenceQualifier, ExceptionSpec);
3577}
3578
3579// extension:
3580// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3581// ::= Dv [<dimension expression>] _ <element type>
3582// <extended element type> ::= <element type>
3583// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003584template <typename Derived, typename Alloc>
3585Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003586 if (!consumeIf("Dv"))
3587 return nullptr;
3588 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003589 Node *DimensionNumber = make<NameType>(parseNumber());
3590 if (!DimensionNumber)
3591 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003592 if (!consumeIf('_'))
3593 return nullptr;
3594 if (consumeIf('p'))
3595 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003596 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003597 if (ElemType == nullptr)
3598 return nullptr;
3599 return make<VectorType>(ElemType, DimensionNumber);
3600 }
3601
3602 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003603 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003604 if (!DimExpr)
3605 return nullptr;
3606 if (!consumeIf('_'))
3607 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003608 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003609 if (!ElemType)
3610 return nullptr;
3611 return make<VectorType>(ElemType, DimExpr);
3612 }
Pavel Labathba825192018-10-16 14:29:14 +00003613 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003614 if (!ElemType)
3615 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003616 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003617}
3618
3619// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3620// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003621template <typename Derived, typename Alloc>
3622Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003623 if (!consumeIf('D'))
3624 return nullptr;
3625 if (!consumeIf('t') && !consumeIf('T'))
3626 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003627 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003628 if (E == nullptr)
3629 return nullptr;
3630 if (!consumeIf('E'))
3631 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003632 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003633}
3634
3635// <array-type> ::= A <positive dimension number> _ <element type>
3636// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003637template <typename Derived, typename Alloc>
3638Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003639 if (!consumeIf('A'))
3640 return nullptr;
3641
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003642 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003643
Richard Smithc20d1442018-08-20 20:14:49 +00003644 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003645 Dimension = make<NameType>(parseNumber());
3646 if (!Dimension)
3647 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003648 if (!consumeIf('_'))
3649 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003650 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003651 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003652 if (DimExpr == nullptr)
3653 return nullptr;
3654 if (!consumeIf('_'))
3655 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003656 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003657 }
3658
Pavel Labathba825192018-10-16 14:29:14 +00003659 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003660 if (Ty == nullptr)
3661 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003662 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003663}
3664
3665// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003666template <typename Derived, typename Alloc>
3667Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003668 if (!consumeIf('M'))
3669 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003670 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003671 if (ClassType == nullptr)
3672 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003673 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003674 if (MemberType == nullptr)
3675 return nullptr;
3676 return make<PointerToMemberType>(ClassType, MemberType);
3677}
3678
3679// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3680// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3681// ::= Tu <name> # dependent elaborated type specifier using 'union'
3682// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003683template <typename Derived, typename Alloc>
3684Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003685 StringView ElabSpef;
3686 if (consumeIf("Ts"))
3687 ElabSpef = "struct";
3688 else if (consumeIf("Tu"))
3689 ElabSpef = "union";
3690 else if (consumeIf("Te"))
3691 ElabSpef = "enum";
3692
Pavel Labathba825192018-10-16 14:29:14 +00003693 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003694 if (Name == nullptr)
3695 return nullptr;
3696
3697 if (!ElabSpef.empty())
3698 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3699
3700 return Name;
3701}
3702
3703// <qualified-type> ::= <qualifiers> <type>
3704// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3705// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003706template <typename Derived, typename Alloc>
3707Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003708 if (consumeIf('U')) {
3709 StringView Qual = parseBareSourceName();
3710 if (Qual.empty())
3711 return nullptr;
3712
Richard Smithc20d1442018-08-20 20:14:49 +00003713 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3714 if (Qual.startsWith("objcproto")) {
3715 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3716 StringView Proto;
3717 {
3718 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3719 SaveLast(Last, ProtoSourceName.end());
3720 Proto = parseBareSourceName();
3721 }
3722 if (Proto.empty())
3723 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003724 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003725 if (Child == nullptr)
3726 return nullptr;
3727 return make<ObjCProtoName>(Child, Proto);
3728 }
3729
Alex Orlovf50df922021-03-24 10:21:32 +04003730 Node *TA = nullptr;
3731 if (look() == 'I') {
3732 TA = getDerived().parseTemplateArgs();
3733 if (TA == nullptr)
3734 return nullptr;
3735 }
3736
Pavel Labathba825192018-10-16 14:29:14 +00003737 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003738 if (Child == nullptr)
3739 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003740 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003741 }
3742
3743 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003744 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003745 if (Ty == nullptr)
3746 return nullptr;
3747 if (Quals != QualNone)
3748 Ty = make<QualType>(Ty, Quals);
3749 return Ty;
3750}
3751
3752// <type> ::= <builtin-type>
3753// ::= <qualified-type>
3754// ::= <function-type>
3755// ::= <class-enum-type>
3756// ::= <array-type>
3757// ::= <pointer-to-member-type>
3758// ::= <template-param>
3759// ::= <template-template-param> <template-args>
3760// ::= <decltype>
3761// ::= P <type> # pointer
3762// ::= R <type> # l-value reference
3763// ::= O <type> # r-value reference (C++11)
3764// ::= C <type> # complex pair (C99)
3765// ::= G <type> # imaginary (C99)
3766// ::= <substitution> # See Compression below
3767// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3768// extension ::= <vector-type> # <vector-type> starts with Dv
3769//
3770// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3771// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003772template <typename Derived, typename Alloc>
3773Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003774 Node *Result = nullptr;
3775
Richard Smithc20d1442018-08-20 20:14:49 +00003776 switch (look()) {
3777 // ::= <qualified-type>
3778 case 'r':
3779 case 'V':
3780 case 'K': {
3781 unsigned AfterQuals = 0;
3782 if (look(AfterQuals) == 'r') ++AfterQuals;
3783 if (look(AfterQuals) == 'V') ++AfterQuals;
3784 if (look(AfterQuals) == 'K') ++AfterQuals;
3785
3786 if (look(AfterQuals) == 'F' ||
3787 (look(AfterQuals) == 'D' &&
3788 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3789 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003790 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003791 break;
3792 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003793 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003794 }
3795 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003796 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003797 break;
3798 }
3799 // <builtin-type> ::= v # void
3800 case 'v':
3801 ++First;
3802 return make<NameType>("void");
3803 // ::= w # wchar_t
3804 case 'w':
3805 ++First;
3806 return make<NameType>("wchar_t");
3807 // ::= b # bool
3808 case 'b':
3809 ++First;
3810 return make<NameType>("bool");
3811 // ::= c # char
3812 case 'c':
3813 ++First;
3814 return make<NameType>("char");
3815 // ::= a # signed char
3816 case 'a':
3817 ++First;
3818 return make<NameType>("signed char");
3819 // ::= h # unsigned char
3820 case 'h':
3821 ++First;
3822 return make<NameType>("unsigned char");
3823 // ::= s # short
3824 case 's':
3825 ++First;
3826 return make<NameType>("short");
3827 // ::= t # unsigned short
3828 case 't':
3829 ++First;
3830 return make<NameType>("unsigned short");
3831 // ::= i # int
3832 case 'i':
3833 ++First;
3834 return make<NameType>("int");
3835 // ::= j # unsigned int
3836 case 'j':
3837 ++First;
3838 return make<NameType>("unsigned int");
3839 // ::= l # long
3840 case 'l':
3841 ++First;
3842 return make<NameType>("long");
3843 // ::= m # unsigned long
3844 case 'm':
3845 ++First;
3846 return make<NameType>("unsigned long");
3847 // ::= x # long long, __int64
3848 case 'x':
3849 ++First;
3850 return make<NameType>("long long");
3851 // ::= y # unsigned long long, __int64
3852 case 'y':
3853 ++First;
3854 return make<NameType>("unsigned long long");
3855 // ::= n # __int128
3856 case 'n':
3857 ++First;
3858 return make<NameType>("__int128");
3859 // ::= o # unsigned __int128
3860 case 'o':
3861 ++First;
3862 return make<NameType>("unsigned __int128");
3863 // ::= f # float
3864 case 'f':
3865 ++First;
3866 return make<NameType>("float");
3867 // ::= d # double
3868 case 'd':
3869 ++First;
3870 return make<NameType>("double");
3871 // ::= e # long double, __float80
3872 case 'e':
3873 ++First;
3874 return make<NameType>("long double");
3875 // ::= g # __float128
3876 case 'g':
3877 ++First;
3878 return make<NameType>("__float128");
3879 // ::= z # ellipsis
3880 case 'z':
3881 ++First;
3882 return make<NameType>("...");
3883
3884 // <builtin-type> ::= u <source-name> # vendor extended type
3885 case 'u': {
3886 ++First;
3887 StringView Res = parseBareSourceName();
3888 if (Res.empty())
3889 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003890 // Typically, <builtin-type>s are not considered substitution candidates,
3891 // but the exception to that exception is vendor extended types (Itanium C++
3892 // ABI 5.9.1).
3893 Result = make<NameType>(Res);
3894 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003895 }
3896 case 'D':
3897 switch (look(1)) {
3898 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3899 case 'd':
3900 First += 2;
3901 return make<NameType>("decimal64");
3902 // ::= De # IEEE 754r decimal floating point (128 bits)
3903 case 'e':
3904 First += 2;
3905 return make<NameType>("decimal128");
3906 // ::= Df # IEEE 754r decimal floating point (32 bits)
3907 case 'f':
3908 First += 2;
3909 return make<NameType>("decimal32");
3910 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3911 case 'h':
3912 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003913 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003914 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3915 case 'F': {
3916 First += 2;
3917 Node *DimensionNumber = make<NameType>(parseNumber());
3918 if (!DimensionNumber)
3919 return nullptr;
3920 if (!consumeIf('_'))
3921 return nullptr;
3922 return make<BinaryFPType>(DimensionNumber);
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 {
4199 SwapAndRestore<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':
4316 if (consumeIf("DnE"))
4317 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();
4423 if (!Op || Op->getKind() != OperatorInfo::Binary)
4424 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004425
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004426 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004427 if (Pack == nullptr)
4428 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004429
4430 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004431 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004432 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004433 if (Init == nullptr)
4434 return nullptr;
4435 }
4436
4437 if (IsLeftFold && Init)
4438 std::swap(Pack, Init);
4439
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004440 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004441}
4442
Richard Smith1865d2f2020-10-22 19:29:36 -07004443// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4444//
4445// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4446template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004447Node *
4448AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4449 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004450 Node *Ty = getDerived().parseType();
4451 if (!Ty)
4452 return nullptr;
4453 Node *Expr = getDerived().parseExpr();
4454 if (!Expr)
4455 return nullptr;
4456 StringView Offset = getDerived().parseNumber(true);
4457 if (!consumeIf('E'))
4458 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004459 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004460}
4461
4462// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4463// <union-selector> ::= _ [<number>]
4464//
4465// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4466template <typename Derived, typename Alloc>
4467Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4468 Node *Ty = getDerived().parseType();
4469 if (!Ty)
4470 return nullptr;
4471 Node *Expr = getDerived().parseExpr();
4472 if (!Expr)
4473 return nullptr;
4474 StringView Offset = getDerived().parseNumber(true);
4475 size_t SelectorsBegin = Names.size();
4476 while (consumeIf('_')) {
4477 Node *Selector = make<NameType>(parseNumber());
4478 if (!Selector)
4479 return nullptr;
4480 Names.push_back(Selector);
4481 }
4482 bool OnePastTheEnd = consumeIf('p');
4483 if (!consumeIf('E'))
4484 return nullptr;
4485 return make<SubobjectExpr>(
4486 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4487}
4488
Richard Smithc20d1442018-08-20 20:14:49 +00004489// <expression> ::= <unary operator-name> <expression>
4490// ::= <binary operator-name> <expression> <expression>
4491// ::= <ternary operator-name> <expression> <expression> <expression>
4492// ::= cl <expression>+ E # call
4493// ::= cv <type> <expression> # conversion with one argument
4494// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4495// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4496// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4497// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4498// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4499// ::= [gs] dl <expression> # delete expression
4500// ::= [gs] da <expression> # delete[] expression
4501// ::= pp_ <expression> # prefix ++
4502// ::= mm_ <expression> # prefix --
4503// ::= ti <type> # typeid (type)
4504// ::= te <expression> # typeid (expression)
4505// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4506// ::= sc <type> <expression> # static_cast<type> (expression)
4507// ::= cc <type> <expression> # const_cast<type> (expression)
4508// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4509// ::= st <type> # sizeof (a type)
4510// ::= sz <expression> # sizeof (an expression)
4511// ::= at <type> # alignof (a type)
4512// ::= az <expression> # alignof (an expression)
4513// ::= nx <expression> # noexcept (expression)
4514// ::= <template-param>
4515// ::= <function-param>
4516// ::= dt <expression> <unresolved-name> # expr.name
4517// ::= pt <expression> <unresolved-name> # expr->name
4518// ::= ds <expression> <expression> # expr.*expr
4519// ::= sZ <template-param> # size of a parameter pack
4520// ::= sZ <function-param> # size of a function parameter pack
4521// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4522// ::= sp <expression> # pack expansion
4523// ::= tw <expression> # throw expression
4524// ::= tr # throw with no operand (rethrow)
4525// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4526// # freestanding dependent name (e.g., T::x),
4527// # objectless nonstatic member reference
4528// ::= fL <binary-operator-name> <expression> <expression>
4529// ::= fR <binary-operator-name> <expression> <expression>
4530// ::= fl <binary-operator-name> <expression>
4531// ::= fr <binary-operator-name> <expression>
4532// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004533template <typename Derived, typename Alloc>
4534Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004535 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004536
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004537 const auto *Op = parseOperatorEncoding();
4538 if (Op) {
4539 auto Sym = Op->getSymbol();
4540 switch (Op->getKind()) {
4541 case OperatorInfo::Binary:
4542 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004543 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004544 case OperatorInfo::Prefix:
4545 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004546 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004547 case OperatorInfo::Postfix: {
4548 // Postfix unary operator: expr @
4549 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004550 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004551 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004552 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004553 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004554 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004555 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004556 case OperatorInfo::Array: {
4557 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004558 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004559 if (Base == nullptr)
4560 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004561 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004562 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004563 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004564 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004565 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004566 case OperatorInfo::Member: {
4567 // Member access lhs @ rhs
4568 Node *LHS = getDerived().parseExpr();
4569 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004570 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004571 Node *RHS = getDerived().parseExpr();
4572 if (RHS == nullptr)
4573 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004574 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004575 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004576 case OperatorInfo::New: {
4577 // New
4578 // # new (expr-list) type [(init)]
4579 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4580 // # new[] (expr-list) type [(init)]
4581 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004582 size_t Exprs = Names.size();
4583 while (!consumeIf('_')) {
4584 Node *Ex = getDerived().parseExpr();
4585 if (Ex == nullptr)
4586 return nullptr;
4587 Names.push_back(Ex);
4588 }
4589 NodeArray ExprList = popTrailingNodeArray(Exprs);
4590 Node *Ty = getDerived().parseType();
4591 if (Ty == nullptr)
4592 return nullptr;
4593 bool HaveInits = consumeIf("pi");
4594 size_t InitsBegin = Names.size();
4595 while (!consumeIf('E')) {
4596 if (!HaveInits)
4597 return nullptr;
4598 Node *Init = getDerived().parseExpr();
4599 if (Init == nullptr)
4600 return Init;
4601 Names.push_back(Init);
4602 }
4603 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004604 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004605 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004606 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004607 case OperatorInfo::Del: {
4608 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004609 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004610 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004611 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004612 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4613 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004614 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004615 case OperatorInfo::Call: {
4616 // Function Call
4617 Node *Callee = getDerived().parseExpr();
4618 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004619 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004620 size_t ExprsBegin = Names.size();
4621 while (!consumeIf('E')) {
4622 Node *E = getDerived().parseExpr();
4623 if (E == nullptr)
4624 return nullptr;
4625 Names.push_back(E);
4626 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004627 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4628 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004629 }
4630 case OperatorInfo::CCast: {
4631 // C Cast: (type)expr
4632 Node *Ty;
4633 {
4634 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
4635 Ty = getDerived().parseType();
4636 }
4637 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004638 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004639
4640 size_t ExprsBegin = Names.size();
4641 bool IsMany = consumeIf('_');
4642 while (!consumeIf('E')) {
4643 Node *E = getDerived().parseExpr();
4644 if (E == nullptr)
4645 return E;
4646 Names.push_back(E);
4647 if (!IsMany)
4648 break;
4649 }
4650 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4651 if (!IsMany && Exprs.size() != 1)
4652 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004653 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004654 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004655 case OperatorInfo::Conditional: {
4656 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004657 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004658 if (Cond == nullptr)
4659 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004660 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004661 if (LHS == nullptr)
4662 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004663 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004664 if (RHS == nullptr)
4665 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004666 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004667 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004668 case OperatorInfo::NamedCast: {
4669 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004670 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004671 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004672 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004673 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004674 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004675 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004676 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004677 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004678 case OperatorInfo::OfIdOp: {
4679 // [sizeof/alignof/typeid] ( <type>|<expr> )
4680 Node *Arg =
4681 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4682 if (!Arg)
4683 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004684 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004685 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004686 case OperatorInfo::NameOnly: {
4687 // Not valid as an expression operand.
4688 return nullptr;
4689 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004690 }
4691 DEMANGLE_UNREACHABLE;
4692 }
4693
4694 if (numLeft() < 2)
4695 return nullptr;
4696
4697 if (look() == 'L')
4698 return getDerived().parseExprPrimary();
4699 if (look() == 'T')
4700 return getDerived().parseTemplateParam();
4701 if (look() == 'f') {
4702 // Disambiguate a fold expression from a <function-param>.
4703 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4704 return getDerived().parseFunctionParam();
4705 return getDerived().parseFoldExpr();
4706 }
4707 if (consumeIf("il")) {
4708 size_t InitsBegin = Names.size();
4709 while (!consumeIf('E')) {
4710 Node *E = getDerived().parseBracedExpr();
4711 if (E == nullptr)
4712 return nullptr;
4713 Names.push_back(E);
4714 }
4715 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4716 }
4717 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004718 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004719 if (consumeIf("nx")) {
4720 Node *Ex = getDerived().parseExpr();
4721 if (Ex == nullptr)
4722 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004723 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004724 }
4725 if (consumeIf("so"))
4726 return parseSubobjectExpr();
4727 if (consumeIf("sp")) {
4728 Node *Child = getDerived().parseExpr();
4729 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004730 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004731 return make<ParameterPackExpansion>(Child);
4732 }
4733 if (consumeIf("sZ")) {
4734 if (look() == 'T') {
4735 Node *R = getDerived().parseTemplateParam();
4736 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004737 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004738 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004739 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004740 Node *FP = getDerived().parseFunctionParam();
4741 if (FP == nullptr)
4742 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004743 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004744 }
4745 if (consumeIf("sP")) {
4746 size_t ArgsBegin = Names.size();
4747 while (!consumeIf('E')) {
4748 Node *Arg = getDerived().parseTemplateArg();
4749 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004750 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004751 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004752 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004753 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4754 if (!Pack)
4755 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004756 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004757 }
4758 if (consumeIf("tl")) {
4759 Node *Ty = getDerived().parseType();
4760 if (Ty == nullptr)
4761 return nullptr;
4762 size_t InitsBegin = Names.size();
4763 while (!consumeIf('E')) {
4764 Node *E = getDerived().parseBracedExpr();
4765 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004766 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004767 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004768 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004769 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4770 }
4771 if (consumeIf("tr"))
4772 return make<NameType>("throw");
4773 if (consumeIf("tw")) {
4774 Node *Ex = getDerived().parseExpr();
4775 if (Ex == nullptr)
4776 return nullptr;
4777 return make<ThrowExpr>(Ex);
4778 }
4779 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004780 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4781 if (!Name)
4782 return nullptr;
4783 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4784 // standard encoding expects a <template-arg>, and would be otherwise be
4785 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4786 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4787 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004788 bool IsUUID = false;
4789 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004790 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004791 if (consumeIf('t')) {
4792 UUID = getDerived().parseType();
4793 IsUUID = true;
4794 } else if (consumeIf('z')) {
4795 UUID = getDerived().parseExpr();
4796 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004797 }
4798 }
4799 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004800 if (IsUUID) {
4801 if (UUID == nullptr)
4802 return nullptr;
4803 Names.push_back(UUID);
4804 } else {
4805 while (!consumeIf('E')) {
4806 Node *E = getDerived().parseTemplateArg();
4807 if (E == nullptr)
4808 return E;
4809 Names.push_back(E);
4810 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004811 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004812 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4813 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004814 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004815
4816 // Only unresolved names remain.
4817 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004818}
4819
4820// <call-offset> ::= h <nv-offset> _
4821// ::= v <v-offset> _
4822//
4823// <nv-offset> ::= <offset number>
4824// # non-virtual base override
4825//
4826// <v-offset> ::= <offset number> _ <virtual offset number>
4827// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004828template <typename Alloc, typename Derived>
4829bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004830 // Just scan through the call offset, we never add this information into the
4831 // output.
4832 if (consumeIf('h'))
4833 return parseNumber(true).empty() || !consumeIf('_');
4834 if (consumeIf('v'))
4835 return parseNumber(true).empty() || !consumeIf('_') ||
4836 parseNumber(true).empty() || !consumeIf('_');
4837 return true;
4838}
4839
4840// <special-name> ::= TV <type> # virtual table
4841// ::= TT <type> # VTT structure (construction vtable index)
4842// ::= TI <type> # typeinfo structure
4843// ::= TS <type> # typeinfo name (null-terminated byte string)
4844// ::= Tc <call-offset> <call-offset> <base encoding>
4845// # base is the nominal target function of thunk
4846// # first call-offset is 'this' adjustment
4847// # second call-offset is result adjustment
4848// ::= T <call-offset> <base encoding>
4849// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004850// # Guard variable for one-time initialization
4851// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004852// # No <type>
4853// ::= TW <object name> # Thread-local wrapper
4854// ::= TH <object name> # Thread-local initialization
4855// ::= GR <object name> _ # First temporary
4856// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004857// # construction vtable for second-in-first
4858// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004859// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004860// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004861template <typename Derived, typename Alloc>
4862Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004863 switch (look()) {
4864 case 'T':
4865 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004866 // TA <template-arg> # template parameter object
4867 //
4868 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4869 case 'A': {
4870 First += 2;
4871 Node *Arg = getDerived().parseTemplateArg();
4872 if (Arg == nullptr)
4873 return nullptr;
4874 return make<SpecialName>("template parameter object for ", Arg);
4875 }
Richard Smithc20d1442018-08-20 20:14:49 +00004876 // TV <type> # virtual table
4877 case 'V': {
4878 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004879 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004880 if (Ty == nullptr)
4881 return nullptr;
4882 return make<SpecialName>("vtable for ", Ty);
4883 }
4884 // TT <type> # VTT structure (construction vtable index)
4885 case 'T': {
4886 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004887 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004888 if (Ty == nullptr)
4889 return nullptr;
4890 return make<SpecialName>("VTT for ", Ty);
4891 }
4892 // TI <type> # typeinfo structure
4893 case 'I': {
4894 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004895 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004896 if (Ty == nullptr)
4897 return nullptr;
4898 return make<SpecialName>("typeinfo for ", Ty);
4899 }
4900 // TS <type> # typeinfo name (null-terminated byte string)
4901 case 'S': {
4902 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004903 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004904 if (Ty == nullptr)
4905 return nullptr;
4906 return make<SpecialName>("typeinfo name for ", Ty);
4907 }
4908 // Tc <call-offset> <call-offset> <base encoding>
4909 case 'c': {
4910 First += 2;
4911 if (parseCallOffset() || parseCallOffset())
4912 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004913 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004914 if (Encoding == nullptr)
4915 return nullptr;
4916 return make<SpecialName>("covariant return thunk to ", Encoding);
4917 }
4918 // extension ::= TC <first type> <number> _ <second type>
4919 // # construction vtable for second-in-first
4920 case 'C': {
4921 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004922 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004923 if (FirstType == nullptr)
4924 return nullptr;
4925 if (parseNumber(true).empty() || !consumeIf('_'))
4926 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004927 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004928 if (SecondType == nullptr)
4929 return nullptr;
4930 return make<CtorVtableSpecialName>(SecondType, FirstType);
4931 }
4932 // TW <object name> # Thread-local wrapper
4933 case 'W': {
4934 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004935 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004936 if (Name == nullptr)
4937 return nullptr;
4938 return make<SpecialName>("thread-local wrapper routine for ", Name);
4939 }
4940 // TH <object name> # Thread-local initialization
4941 case 'H': {
4942 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004943 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004944 if (Name == nullptr)
4945 return nullptr;
4946 return make<SpecialName>("thread-local initialization routine for ", Name);
4947 }
4948 // T <call-offset> <base encoding>
4949 default: {
4950 ++First;
4951 bool IsVirt = look() == 'v';
4952 if (parseCallOffset())
4953 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004954 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004955 if (BaseEncoding == nullptr)
4956 return nullptr;
4957 if (IsVirt)
4958 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4959 else
4960 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4961 }
4962 }
4963 case 'G':
4964 switch (look(1)) {
4965 // GV <object name> # Guard variable for one-time initialization
4966 case 'V': {
4967 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004968 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004969 if (Name == nullptr)
4970 return nullptr;
4971 return make<SpecialName>("guard variable for ", Name);
4972 }
4973 // GR <object name> # reference temporary for object
4974 // GR <object name> _ # First temporary
4975 // GR <object name> <seq-id> _ # Subsequent temporaries
4976 case 'R': {
4977 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004978 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004979 if (Name == nullptr)
4980 return nullptr;
4981 size_t Count;
4982 bool ParsedSeqId = !parseSeqId(&Count);
4983 if (!consumeIf('_') && ParsedSeqId)
4984 return nullptr;
4985 return make<SpecialName>("reference temporary for ", Name);
4986 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004987 // GI <module-name> v
4988 case 'I': {
4989 First += 2;
4990 ModuleName *Module = nullptr;
4991 if (getDerived().parseModuleNameOpt(Module))
4992 return nullptr;
4993 if (Module == nullptr)
4994 return nullptr;
4995 return make<SpecialName>("initializer for module ", Module);
4996 }
Richard Smithc20d1442018-08-20 20:14:49 +00004997 }
4998 }
4999 return nullptr;
5000}
5001
5002// <encoding> ::= <function name> <bare-function-type>
5003// ::= <data name>
5004// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005005template <typename Derived, typename Alloc>
5006Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005007 // The template parameters of an encoding are unrelated to those of the
5008 // enclosing context.
5009 class SaveTemplateParams {
5010 AbstractManglingParser *Parser;
5011 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005012 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005013
5014 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005015 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005016 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005017 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005018 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005019 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005020 }
5021 ~SaveTemplateParams() {
5022 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005023 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005024 }
5025 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005026
Richard Smithc20d1442018-08-20 20:14:49 +00005027 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005028 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005029
5030 auto IsEndOfEncoding = [&] {
5031 // The set of chars that can potentially follow an <encoding> (none of which
5032 // can start a <type>). Enumerating these allows us to avoid speculative
5033 // parsing.
5034 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5035 };
5036
5037 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005038 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005039 if (Name == nullptr)
5040 return nullptr;
5041
5042 if (resolveForwardTemplateRefs(NameInfo))
5043 return nullptr;
5044
5045 if (IsEndOfEncoding())
5046 return Name;
5047
5048 Node *Attrs = nullptr;
5049 if (consumeIf("Ua9enable_ifI")) {
5050 size_t BeforeArgs = Names.size();
5051 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005052 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005053 if (Arg == nullptr)
5054 return nullptr;
5055 Names.push_back(Arg);
5056 }
5057 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005058 if (!Attrs)
5059 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005060 }
5061
5062 Node *ReturnType = nullptr;
5063 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005064 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005065 if (ReturnType == nullptr)
5066 return nullptr;
5067 }
5068
5069 if (consumeIf('v'))
5070 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5071 Attrs, NameInfo.CVQualifiers,
5072 NameInfo.ReferenceQualifier);
5073
5074 size_t ParamsBegin = Names.size();
5075 do {
Pavel Labathba825192018-10-16 14:29:14 +00005076 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005077 if (Ty == nullptr)
5078 return nullptr;
5079 Names.push_back(Ty);
5080 } while (!IsEndOfEncoding());
5081
5082 return make<FunctionEncoding>(ReturnType, Name,
5083 popTrailingNodeArray(ParamsBegin),
5084 Attrs, NameInfo.CVQualifiers,
5085 NameInfo.ReferenceQualifier);
5086}
5087
5088template <class Float>
5089struct FloatData;
5090
5091template <>
5092struct FloatData<float>
5093{
5094 static const size_t mangled_size = 8;
5095 static const size_t max_demangled_size = 24;
5096 static constexpr const char* spec = "%af";
5097};
5098
5099template <>
5100struct FloatData<double>
5101{
5102 static const size_t mangled_size = 16;
5103 static const size_t max_demangled_size = 32;
5104 static constexpr const char* spec = "%a";
5105};
5106
5107template <>
5108struct FloatData<long double>
5109{
5110#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5111 defined(__wasm__)
5112 static const size_t mangled_size = 32;
5113#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5114 static const size_t mangled_size = 16;
5115#else
5116 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5117#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005118 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5119 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5120 // Negatives are one character longer than positives.
5121 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5122 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5123 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005124 static constexpr const char *spec = "%LaL";
5125};
5126
Pavel Labathba825192018-10-16 14:29:14 +00005127template <typename Alloc, typename Derived>
5128template <class Float>
5129Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005130 const size_t N = FloatData<Float>::mangled_size;
5131 if (numLeft() <= N)
5132 return nullptr;
5133 StringView Data(First, First + N);
5134 for (char C : Data)
5135 if (!std::isxdigit(C))
5136 return nullptr;
5137 First += N;
5138 if (!consumeIf('E'))
5139 return nullptr;
5140 return make<FloatLiteralImpl<Float>>(Data);
5141}
5142
5143// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005144template <typename Alloc, typename Derived>
5145bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005146 if (!(look() >= '0' && look() <= '9') &&
5147 !(look() >= 'A' && look() <= 'Z'))
5148 return true;
5149
5150 size_t Id = 0;
5151 while (true) {
5152 if (look() >= '0' && look() <= '9') {
5153 Id *= 36;
5154 Id += static_cast<size_t>(look() - '0');
5155 } else if (look() >= 'A' && look() <= 'Z') {
5156 Id *= 36;
5157 Id += static_cast<size_t>(look() - 'A') + 10;
5158 } else {
5159 *Out = Id;
5160 return false;
5161 }
5162 ++First;
5163 }
5164}
5165
5166// <substitution> ::= S <seq-id> _
5167// ::= S_
5168// <substitution> ::= Sa # ::std::allocator
5169// <substitution> ::= Sb # ::std::basic_string
5170// <substitution> ::= Ss # ::std::basic_string < char,
5171// ::std::char_traits<char>,
5172// ::std::allocator<char> >
5173// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5174// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5175// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005176// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005177template <typename Derived, typename Alloc>
5178Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005179 if (!consumeIf('S'))
5180 return nullptr;
5181
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005182 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005183 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005184 switch (look()) {
5185 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005186 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005187 break;
5188 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005189 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005190 break;
5191 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005192 Kind = SpecialSubKind::iostream;
5193 break;
5194 case 'i':
5195 Kind = SpecialSubKind::istream;
5196 break;
5197 case 'o':
5198 Kind = SpecialSubKind::ostream;
5199 break;
5200 case 's':
5201 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005202 break;
5203 default:
5204 return nullptr;
5205 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005206 ++First;
5207 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005208 if (!SpecialSub)
5209 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005210
Richard Smithc20d1442018-08-20 20:14:49 +00005211 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5212 // has ABI tags, the tags are appended to the substitution; the result is a
5213 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005214 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005215 if (WithTags != SpecialSub) {
5216 Subs.push_back(WithTags);
5217 SpecialSub = WithTags;
5218 }
5219 return SpecialSub;
5220 }
5221
5222 // ::= S_
5223 if (consumeIf('_')) {
5224 if (Subs.empty())
5225 return nullptr;
5226 return Subs[0];
5227 }
5228
5229 // ::= S <seq-id> _
5230 size_t Index = 0;
5231 if (parseSeqId(&Index))
5232 return nullptr;
5233 ++Index;
5234 if (!consumeIf('_') || Index >= Subs.size())
5235 return nullptr;
5236 return Subs[Index];
5237}
5238
5239// <template-param> ::= T_ # first template parameter
5240// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005241// ::= TL <level-1> __
5242// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005243template <typename Derived, typename Alloc>
5244Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005245 if (!consumeIf('T'))
5246 return nullptr;
5247
Richard Smithdf1c14c2019-09-06 23:53:21 +00005248 size_t Level = 0;
5249 if (consumeIf('L')) {
5250 if (parsePositiveInteger(&Level))
5251 return nullptr;
5252 ++Level;
5253 if (!consumeIf('_'))
5254 return nullptr;
5255 }
5256
Richard Smithc20d1442018-08-20 20:14:49 +00005257 size_t Index = 0;
5258 if (!consumeIf('_')) {
5259 if (parsePositiveInteger(&Index))
5260 return nullptr;
5261 ++Index;
5262 if (!consumeIf('_'))
5263 return nullptr;
5264 }
5265
Richard Smithc20d1442018-08-20 20:14:49 +00005266 // If we're in a context where this <template-param> refers to a
5267 // <template-arg> further ahead in the mangled name (currently just conversion
5268 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005269 // This can only happen at the outermost level.
5270 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005271 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5272 if (!ForwardRef)
5273 return nullptr;
5274 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5275 ForwardTemplateRefs.push_back(
5276 static_cast<ForwardTemplateReference *>(ForwardRef));
5277 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005278 }
5279
Richard Smithdf1c14c2019-09-06 23:53:21 +00005280 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5281 Index >= TemplateParams[Level]->size()) {
5282 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5283 // list are mangled as the corresponding artificial template type parameter.
5284 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5285 // This will be popped by the ScopedTemplateParamList in
5286 // parseUnnamedTypeName.
5287 if (Level == TemplateParams.size())
5288 TemplateParams.push_back(nullptr);
5289 return make<NameType>("auto");
5290 }
5291
Richard Smithc20d1442018-08-20 20:14:49 +00005292 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005293 }
5294
5295 return (*TemplateParams[Level])[Index];
5296}
5297
5298// <template-param-decl> ::= Ty # type parameter
5299// ::= Tn <type> # non-type parameter
5300// ::= Tt <template-param-decl>* E # template parameter
5301// ::= Tp <template-param-decl> # parameter pack
5302template <typename Derived, typename Alloc>
5303Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5304 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5305 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5306 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5307 if (N) TemplateParams.back()->push_back(N);
5308 return N;
5309 };
5310
5311 if (consumeIf("Ty")) {
5312 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5313 if (!Name)
5314 return nullptr;
5315 return make<TypeTemplateParamDecl>(Name);
5316 }
5317
5318 if (consumeIf("Tn")) {
5319 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5320 if (!Name)
5321 return nullptr;
5322 Node *Type = parseType();
5323 if (!Type)
5324 return nullptr;
5325 return make<NonTypeTemplateParamDecl>(Name, Type);
5326 }
5327
5328 if (consumeIf("Tt")) {
5329 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5330 if (!Name)
5331 return nullptr;
5332 size_t ParamsBegin = Names.size();
5333 ScopedTemplateParamList TemplateTemplateParamParams(this);
5334 while (!consumeIf("E")) {
5335 Node *P = parseTemplateParamDecl();
5336 if (!P)
5337 return nullptr;
5338 Names.push_back(P);
5339 }
5340 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5341 return make<TemplateTemplateParamDecl>(Name, Params);
5342 }
5343
5344 if (consumeIf("Tp")) {
5345 Node *P = parseTemplateParamDecl();
5346 if (!P)
5347 return nullptr;
5348 return make<TemplateParamPackDecl>(P);
5349 }
5350
5351 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005352}
5353
5354// <template-arg> ::= <type> # type or template
5355// ::= X <expression> E # expression
5356// ::= <expr-primary> # simple expressions
5357// ::= J <template-arg>* E # argument pack
5358// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005359template <typename Derived, typename Alloc>
5360Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005361 switch (look()) {
5362 case 'X': {
5363 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005364 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005365 if (Arg == nullptr || !consumeIf('E'))
5366 return nullptr;
5367 return Arg;
5368 }
5369 case 'J': {
5370 ++First;
5371 size_t ArgsBegin = Names.size();
5372 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005373 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005374 if (Arg == nullptr)
5375 return nullptr;
5376 Names.push_back(Arg);
5377 }
5378 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5379 return make<TemplateArgumentPack>(Args);
5380 }
5381 case 'L': {
5382 // ::= LZ <encoding> E # extension
5383 if (look(1) == 'Z') {
5384 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005385 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005386 if (Arg == nullptr || !consumeIf('E'))
5387 return nullptr;
5388 return Arg;
5389 }
5390 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005391 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005392 }
5393 default:
Pavel Labathba825192018-10-16 14:29:14 +00005394 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005395 }
5396}
5397
5398// <template-args> ::= I <template-arg>* E
5399// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005400template <typename Derived, typename Alloc>
5401Node *
5402AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005403 if (!consumeIf('I'))
5404 return nullptr;
5405
5406 // <template-params> refer to the innermost <template-args>. Clear out any
5407 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005408 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005409 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005410 TemplateParams.push_back(&OuterTemplateParams);
5411 OuterTemplateParams.clear();
5412 }
Richard Smithc20d1442018-08-20 20:14:49 +00005413
5414 size_t ArgsBegin = Names.size();
5415 while (!consumeIf('E')) {
5416 if (TagTemplates) {
5417 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005418 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005419 TemplateParams = std::move(OldParams);
5420 if (Arg == nullptr)
5421 return nullptr;
5422 Names.push_back(Arg);
5423 Node *TableEntry = Arg;
5424 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5425 TableEntry = make<ParameterPack>(
5426 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005427 if (!TableEntry)
5428 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005429 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005430 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005431 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005432 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005433 if (Arg == nullptr)
5434 return nullptr;
5435 Names.push_back(Arg);
5436 }
5437 }
5438 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5439}
5440
5441// <mangled-name> ::= _Z <encoding>
5442// ::= <type>
5443// extension ::= ___Z <encoding> _block_invoke
5444// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5445// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005446template <typename Derived, typename Alloc>
5447Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005448 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005449 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005450 if (Encoding == nullptr)
5451 return nullptr;
5452 if (look() == '.') {
5453 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5454 First = Last;
5455 }
5456 if (numLeft() != 0)
5457 return nullptr;
5458 return Encoding;
5459 }
5460
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005461 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005462 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005463 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5464 return nullptr;
5465 bool RequireNumber = consumeIf('_');
5466 if (parseNumber().empty() && RequireNumber)
5467 return nullptr;
5468 if (look() == '.')
5469 First = Last;
5470 if (numLeft() != 0)
5471 return nullptr;
5472 return make<SpecialName>("invocation function for block in ", Encoding);
5473 }
5474
Pavel Labathba825192018-10-16 14:29:14 +00005475 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005476 if (numLeft() != 0)
5477 return nullptr;
5478 return Ty;
5479}
5480
Pavel Labathba825192018-10-16 14:29:14 +00005481template <typename Alloc>
5482struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5483 using AbstractManglingParser<ManglingParser<Alloc>,
5484 Alloc>::AbstractManglingParser;
5485};
5486
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005487DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005488
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005489#endif // DEMANGLE_ITANIUMDEMANGLE_H