blob: fd6835ab9aba49de6417725210ee6a6e0b92ad51 [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 Sidwellac492da2022-04-05 09:25:47 -07002732// <unscoped-name> ::= <unqualified-name>
2733// ::= St <unqualified-name> # ::std::
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08002734// [*] 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 Sidwelle4cc3532022-01-24 04:28:09 -08002746
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002747 Node *Res = nullptr;
2748 ModuleName *Module = nullptr;
2749 if (look() == 'S') {
2750 Node *S = getDerived().parseSubstitution();
2751 if (!S)
2752 return nullptr;
2753 if (S->getKind() == Node::KModuleName)
2754 Module = static_cast<ModuleName *>(S);
2755 else if (IsSubst && Std == nullptr) {
2756 Res = S;
2757 *IsSubst = true;
2758 } else {
2759 return nullptr;
2760 }
2761 }
2762
Nathan Sidwellac492da2022-04-05 09:25:47 -07002763 if (Res == nullptr || Std != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002764 Res = getDerived().parseUnqualifiedName(State, Std, Module);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002765 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002766
2767 return Res;
Richard Smithc20d1442018-08-20 20:14:49 +00002768}
2769
Nathan Sidwellac492da2022-04-05 09:25:47 -07002770// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002771// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
Nathan Sidwellac492da2022-04-05 09:25:47 -07002772// ::= [<module-name>] L? <source-name> [<abi-tags>]
2773// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002774// # structured binding declaration
Nathan Sidwellac492da2022-04-05 09:25:47 -07002775// ::= [<module-name>] L? 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
Nathan Sidwellac492da2022-04-05 09:25:47 -07002782 consumeIf('L');
2783
Richard Smithc20d1442018-08-20 20:14:49 +00002784 Node *Result;
Nathan Sidwellac492da2022-04-05 09:25:47 -07002785 if (look() >= '1' && look() <= '9') {
Pavel Labathba825192018-10-16 14:29:14 +00002786 Result = getDerived().parseSourceName(State);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002787 } else if (look() == 'U') {
2788 Result = getDerived().parseUnnamedTypeName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002789 } else if (consumeIf("DC")) {
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002790 // Structured binding
Richard Smithc20d1442018-08-20 20:14:49 +00002791 size_t BindingsBegin = Names.size();
2792 do {
Pavel Labathba825192018-10-16 14:29:14 +00002793 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002794 if (Binding == nullptr)
2795 return nullptr;
2796 Names.push_back(Binding);
2797 } while (!consumeIf('E'));
2798 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002799 } else if (look() == 'C' || look() == 'D') {
2800 // A <ctor-dtor-name>.
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002801 if (Scope == nullptr || Module != nullptr)
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002802 return nullptr;
2803 Result = getDerived().parseCtorDtorName(Scope, State);
2804 } else {
Pavel Labathba825192018-10-16 14:29:14 +00002805 Result = getDerived().parseOperatorName(State);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002806 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002807
David Blaikie019fb1b2022-03-30 20:18:40 +00002808 if (Result != nullptr && Module != nullptr)
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002809 Result = make<ModuleEntity>(Module, Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002810 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002811 Result = getDerived().parseAbiTags(Result);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002812 if (Result != nullptr && Scope != nullptr)
2813 Result = make<NestedName>(Scope, Result);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002814
Richard Smithc20d1442018-08-20 20:14:49 +00002815 return Result;
2816}
2817
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002818// <module-name> ::= <module-subname>
2819// ::= <module-name> <module-subname>
2820// ::= <substitution> # passed in by caller
2821// <module-subname> ::= W <source-name>
2822// ::= W P <source-name>
2823template <typename Derived, typename Alloc>
2824bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2825 ModuleName *&Module) {
2826 while (consumeIf('W')) {
2827 bool IsPartition = consumeIf('P');
2828 Node *Sub = getDerived().parseSourceName(nullptr);
2829 if (!Sub)
2830 return true;
2831 Module =
2832 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2833 Subs.push_back(Module);
2834 }
2835
2836 return false;
2837}
2838
Richard Smithc20d1442018-08-20 20:14:49 +00002839// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2840// ::= <closure-type-name>
2841//
2842// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2843//
2844// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002845template <typename Derived, typename Alloc>
2846Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002847AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2848 // <template-params> refer to the innermost <template-args>. Clear out any
2849 // outer args that we may have inserted into TemplateParams.
2850 if (State != nullptr)
2851 TemplateParams.clear();
2852
Richard Smithc20d1442018-08-20 20:14:49 +00002853 if (consumeIf("Ut")) {
2854 StringView Count = parseNumber();
2855 if (!consumeIf('_'))
2856 return nullptr;
2857 return make<UnnamedTypeName>(Count);
2858 }
2859 if (consumeIf("Ul")) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002860 SwapAndRestore<size_t> SwapParams(ParsingLambdaParamsAtLevel,
2861 TemplateParams.size());
2862 ScopedTemplateParamList LambdaTemplateParams(this);
2863
2864 size_t ParamsBegin = Names.size();
2865 while (look() == 'T' &&
2866 StringView("yptn").find(look(1)) != StringView::npos) {
2867 Node *T = parseTemplateParamDecl();
2868 if (!T)
2869 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002870 Names.push_back(T);
2871 }
2872 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2873
2874 // FIXME: If TempParams is empty and none of the function parameters
2875 // includes 'auto', we should remove LambdaTemplateParams from the
2876 // TemplateParams list. Unfortunately, we don't find out whether there are
2877 // any 'auto' parameters until too late in an example such as:
2878 //
2879 // template<typename T> void f(
2880 // decltype([](decltype([]<typename T>(T v) {}),
2881 // auto) {})) {}
2882 // template<typename T> void f(
2883 // decltype([](decltype([]<typename T>(T w) {}),
2884 // int) {})) {}
2885 //
2886 // Here, the type of v is at level 2 but the type of w is at level 1. We
2887 // don't find this out until we encounter the type of the next parameter.
2888 //
2889 // However, compilers can't actually cope with the former example in
2890 // practice, and it's likely to be made ill-formed in future, so we don't
2891 // need to support it here.
2892 //
2893 // If we encounter an 'auto' in the function parameter types, we will
2894 // recreate a template parameter scope for it, but any intervening lambdas
2895 // will be parsed in the 'wrong' template parameter depth.
2896 if (TempParams.empty())
2897 TemplateParams.pop_back();
2898
Richard Smithc20d1442018-08-20 20:14:49 +00002899 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002900 do {
Pavel Labathba825192018-10-16 14:29:14 +00002901 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002902 if (P == nullptr)
2903 return nullptr;
2904 Names.push_back(P);
2905 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002906 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002907 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2908
Richard Smithc20d1442018-08-20 20:14:49 +00002909 StringView Count = parseNumber();
2910 if (!consumeIf('_'))
2911 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002912 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002913 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002914 if (consumeIf("Ub")) {
2915 (void)parseNumber();
2916 if (!consumeIf('_'))
2917 return nullptr;
2918 return make<NameType>("'block-literal'");
2919 }
Richard Smithc20d1442018-08-20 20:14:49 +00002920 return nullptr;
2921}
2922
2923// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002924template <typename Derived, typename Alloc>
2925Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002926 size_t Length = 0;
2927 if (parsePositiveInteger(&Length))
2928 return nullptr;
2929 if (numLeft() < Length || Length == 0)
2930 return nullptr;
2931 StringView Name(First, First + Length);
2932 First += Length;
2933 if (Name.startsWith("_GLOBAL__N"))
2934 return make<NameType>("(anonymous namespace)");
2935 return make<NameType>(Name);
2936}
2937
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002938// If the next 2 chars are an operator encoding, consume them and return their
2939// OperatorInfo. Otherwise return nullptr.
2940template <typename Derived, typename Alloc>
2941const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
2942AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
2943 static const OperatorInfo Ops[] = {
2944 // Keep ordered by encoding
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002945 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
2946 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
2947 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
2948 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
2949 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
2950 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary,
2951 "alignof "},
2952 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
2953 "operator co_await"},
2954 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
2955 "alignof "},
2956 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
2957 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
2958 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
2959 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
2960 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast,
2961 "operator"}, // C Cast
2962 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
2963 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
2964 "operator delete[]"},
2965 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
2966 "dynamic_cast"},
2967 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
2968 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
2969 "operator delete"},
2970 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2971 "operator.*"},
2972 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
2973 "operator."},
2974 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
2975 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
2976 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
2977 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
2978 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
2979 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
2980 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
2981 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
2982 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
2983 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
2984 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
2985 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
2986 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
2987 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
2988 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
2989 "operator*"},
2990 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
2991 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
2992 "operator new[]"},
2993 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
2994 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
2995 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
2996 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary,
2997 "operator new"},
2998 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
2999 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
3000 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
3001 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
3002 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
3003 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3004 "operator->*"},
3005 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
3006 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
3007 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
3008 "operator->"},
3009 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
3010 "operator?"},
3011 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
3012 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
3013 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3014 "reinterpret_cast"},
3015 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3016 "operator%"},
3017 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3018 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3019 "static_cast"},
3020 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3021 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3022 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
3023 "sizeof "},
3024 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3025 "typeid "},
3026 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix,
3027 "typeid "},
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003028 };
3029 const auto NumOps = sizeof(Ops) / sizeof(Ops[0]);
3030
3031#ifndef NDEBUG
3032 {
3033 // Verify table order.
3034 static bool Done;
3035 if (!Done) {
3036 Done = true;
3037 for (const auto *Op = &Ops[0]; Op != &Ops[NumOps - 1]; Op++)
3038 assert(Op[0] < Op[1] && "Operator table is not ordered");
3039 }
3040 }
3041#endif
3042
3043 if (numLeft() < 2)
3044 return nullptr;
3045
3046 auto Op = std::lower_bound(
3047 &Ops[0], &Ops[NumOps], First,
3048 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3049 if (Op == &Ops[NumOps] || *Op != First)
3050 return nullptr;
3051
3052 First += 2;
3053 return Op;
3054}
3055
3056// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003057// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003058// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003059template <typename Derived, typename Alloc>
3060Node *
3061AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003062 if (const auto *Op = parseOperatorEncoding()) {
3063 if (Op->getKind() == OperatorInfo::CCast) {
3064 // ::= cv <type> # (cast)
Richard Smithc20d1442018-08-20 20:14:49 +00003065 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
3066 // If we're parsing an encoding, State != nullptr and the conversion
3067 // operators' <type> could have a <template-param> that refers to some
3068 // <template-arg>s further ahead in the mangled name.
3069 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
3070 PermitForwardTemplateReferences ||
3071 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003072 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003073 if (Ty == nullptr)
3074 return nullptr;
3075 if (State) State->CtorDtorConversion = true;
3076 return make<ConversionOperatorType>(Ty);
3077 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003078
3079 if (Op->getKind() >= OperatorInfo::Unnameable)
3080 /* Not a nameable operator. */
3081 return nullptr;
3082 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3083 /* Not a nameable MemberExpr */
3084 return nullptr;
3085
3086 return make<NameType>(Op->getName());
3087 }
3088
3089 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003090 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003091 Node *SN = getDerived().parseSourceName(State);
3092 if (SN == nullptr)
3093 return nullptr;
3094 return make<LiteralOperator>(SN);
3095 }
3096
3097 if (consumeIf('v')) {
3098 // ::= v <digit> <source-name> # vendor extended operator
3099 if (look() >= '0' && look() <= '9') {
3100 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003101 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003102 if (SN == nullptr)
3103 return nullptr;
3104 return make<ConversionOperatorType>(SN);
3105 }
3106 return nullptr;
3107 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003108
Richard Smithc20d1442018-08-20 20:14:49 +00003109 return nullptr;
3110}
3111
3112// <ctor-dtor-name> ::= C1 # complete object constructor
3113// ::= C2 # base object constructor
3114// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003115// extension ::= C4 # gcc old-style "[unified]" constructor
3116// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003117// ::= D0 # deleting destructor
3118// ::= D1 # complete object destructor
3119// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003120// extension ::= D4 # gcc old-style "[unified]" destructor
3121// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003122template <typename Derived, typename Alloc>
3123Node *
3124AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3125 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003126 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3127 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3128 switch (SSK) {
3129 case SpecialSubKind::string:
3130 case SpecialSubKind::istream:
3131 case SpecialSubKind::ostream:
3132 case SpecialSubKind::iostream:
3133 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00003134 if (!SoFar)
3135 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00003136 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003137 default:
3138 break;
3139 }
3140 }
3141
3142 if (consumeIf('C')) {
3143 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003144 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3145 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003146 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003147 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003148 ++First;
3149 if (State) State->CtorDtorConversion = true;
3150 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003151 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003152 return nullptr;
3153 }
Nico Weber29294792019-04-03 23:14:33 +00003154 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003155 }
3156
Nico Weber29294792019-04-03 23:14:33 +00003157 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3158 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003159 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003160 First += 2;
3161 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003162 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003163 }
3164
3165 return nullptr;
3166}
3167
Nathan Sidwellac492da2022-04-05 09:25:47 -07003168// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3169// <unqualified-name> E
3170// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3171// <template-args> E
Richard Smithc20d1442018-08-20 20:14:49 +00003172//
Nathan Sidwellac492da2022-04-05 09:25:47 -07003173// <prefix> ::= <prefix> <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003174// ::= <template-prefix> <template-args>
3175// ::= <template-param>
3176// ::= <decltype>
3177// ::= # empty
3178// ::= <substitution>
3179// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003180// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003181//
3182// <data-member-prefix> := <member source-name> [<template-args>] M
3183//
3184// <template-prefix> ::= <prefix> <template unqualified-name>
3185// ::= <template-param>
3186// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003187template <typename Derived, typename Alloc>
3188Node *
3189AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003190 if (!consumeIf('N'))
3191 return nullptr;
3192
3193 Qualifiers CVTmp = parseCVQualifiers();
3194 if (State) State->CVQualifiers = CVTmp;
3195
3196 if (consumeIf('O')) {
3197 if (State) State->ReferenceQualifier = FrefQualRValue;
3198 } else if (consumeIf('R')) {
3199 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003200 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003201 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003202 }
Richard Smithc20d1442018-08-20 20:14:49 +00003203
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003204 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003205 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003206 if (State)
3207 // Only set end-with-template on the case that does that.
3208 State->EndsWithTemplateArgs = false;
3209
Richard Smithc20d1442018-08-20 20:14:49 +00003210 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003211 // ::= <template-param>
3212 if (SoFar != nullptr)
3213 return nullptr; // Cannot have a prefix.
3214 SoFar = getDerived().parseTemplateParam();
3215 } else if (look() == 'I') {
3216 // ::= <template-prefix> <template-args>
3217 if (SoFar == nullptr)
3218 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003219 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003220 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003221 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003222 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3223 // Semantically <template-args> <template-args> cannot be generated by a
3224 // C++ entity. There will always be [something like] a name between
3225 // them.
3226 return nullptr;
3227 if (State)
3228 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003229 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003230 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3231 // ::= <decltype>
3232 if (SoFar != nullptr)
3233 return nullptr; // Cannot have a prefix.
3234 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003235 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003236 ModuleName *Module = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003237
3238 if (look() == 'S') {
3239 // ::= <substitution>
3240 Node *S = nullptr;
3241 if (look(1) == 't') {
3242 First += 2;
3243 S = make<NameType>("std");
3244 } else {
3245 S = getDerived().parseSubstitution();
3246 }
3247 if (!S)
3248 return nullptr;
3249 if (S->getKind() == Node::KModuleName) {
3250 Module = static_cast<ModuleName *>(S);
Nathan Sidwellac492da2022-04-05 09:25:47 -07003251 } else if (SoFar != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003252 return nullptr; // Cannot have a prefix.
3253 } else {
3254 SoFar = S;
3255 continue; // Do not push a new substitution.
3256 }
3257 }
3258
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003259 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003260 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003261 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003262
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003263 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003264 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003265 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003266
3267 // No longer used.
3268 // <data-member-prefix> := <member source-name> [<template-args>] M
3269 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003270 }
3271
3272 if (SoFar == nullptr || Subs.empty())
3273 return nullptr;
3274
3275 Subs.pop_back();
3276 return SoFar;
3277}
3278
3279// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003280template <typename Derived, typename Alloc>
3281Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3282 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003283 if (SN == nullptr)
3284 return nullptr;
3285 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003286 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003287 if (TA == nullptr)
3288 return nullptr;
3289 return make<NameWithTemplateArgs>(SN, TA);
3290 }
3291 return SN;
3292}
3293
3294// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3295// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003296template <typename Derived, typename Alloc>
3297Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003298 Node *Result;
3299 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003300 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003301 else
Pavel Labathba825192018-10-16 14:29:14 +00003302 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003303 if (Result == nullptr)
3304 return nullptr;
3305 return make<DtorName>(Result);
3306}
3307
3308// <unresolved-type> ::= <template-param>
3309// ::= <decltype>
3310// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003311template <typename Derived, typename Alloc>
3312Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003313 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003314 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003315 if (TP == nullptr)
3316 return nullptr;
3317 Subs.push_back(TP);
3318 return TP;
3319 }
3320 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003321 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003322 if (DT == nullptr)
3323 return nullptr;
3324 Subs.push_back(DT);
3325 return DT;
3326 }
Pavel Labathba825192018-10-16 14:29:14 +00003327 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003328}
3329
3330// <base-unresolved-name> ::= <simple-id> # unresolved name
3331// extension ::= <operator-name> # unresolved operator-function-id
3332// extension ::= <operator-name> <template-args> # unresolved operator template-id
3333// ::= on <operator-name> # unresolved operator-function-id
3334// ::= on <operator-name> <template-args> # unresolved operator template-id
3335// ::= dn <destructor-name> # destructor or pseudo-destructor;
3336// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003337template <typename Derived, typename Alloc>
3338Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003339 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003340 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003341
3342 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003343 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003344
3345 consumeIf("on");
3346
Pavel Labathba825192018-10-16 14:29:14 +00003347 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003348 if (Oper == nullptr)
3349 return nullptr;
3350 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003351 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003352 if (TA == nullptr)
3353 return nullptr;
3354 return make<NameWithTemplateArgs>(Oper, TA);
3355 }
3356 return Oper;
3357}
3358
3359// <unresolved-name>
3360// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3361// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3362// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3363// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003364// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003365// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3366// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3367// # T::N::x /decltype(p)::N::x
3368// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3369//
3370// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003371template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003372Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003373 Node *SoFar = nullptr;
3374
3375 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3376 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3377 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003378 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003379 if (SoFar == nullptr)
3380 return nullptr;
3381
3382 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003383 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003384 if (TA == nullptr)
3385 return nullptr;
3386 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003387 if (!SoFar)
3388 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003389 }
3390
3391 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003392 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003393 if (Qual == nullptr)
3394 return nullptr;
3395 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003396 if (!SoFar)
3397 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003398 }
3399
Pavel Labathba825192018-10-16 14:29:14 +00003400 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003401 if (Base == nullptr)
3402 return nullptr;
3403 return make<QualifiedName>(SoFar, Base);
3404 }
3405
Richard Smithc20d1442018-08-20 20:14:49 +00003406 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3407 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003408 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003409 if (SoFar == nullptr)
3410 return nullptr;
3411 if (Global)
3412 SoFar = make<GlobalQualifiedName>(SoFar);
3413 return SoFar;
3414 }
3415
3416 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3417 if (std::isdigit(look())) {
3418 do {
Pavel Labathba825192018-10-16 14:29:14 +00003419 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003420 if (Qual == nullptr)
3421 return nullptr;
3422 if (SoFar)
3423 SoFar = make<QualifiedName>(SoFar, Qual);
3424 else if (Global)
3425 SoFar = make<GlobalQualifiedName>(Qual);
3426 else
3427 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003428 if (!SoFar)
3429 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003430 } while (!consumeIf('E'));
3431 }
3432 // sr <unresolved-type> <base-unresolved-name>
3433 // sr <unresolved-type> <template-args> <base-unresolved-name>
3434 else {
Pavel Labathba825192018-10-16 14:29:14 +00003435 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003436 if (SoFar == nullptr)
3437 return nullptr;
3438
3439 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003440 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003441 if (TA == nullptr)
3442 return nullptr;
3443 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003444 if (!SoFar)
3445 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003446 }
3447 }
3448
3449 assert(SoFar != nullptr);
3450
Pavel Labathba825192018-10-16 14:29:14 +00003451 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003452 if (Base == nullptr)
3453 return nullptr;
3454 return make<QualifiedName>(SoFar, Base);
3455}
3456
3457// <abi-tags> ::= <abi-tag> [<abi-tags>]
3458// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003459template <typename Derived, typename Alloc>
3460Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003461 while (consumeIf('B')) {
3462 StringView SN = parseBareSourceName();
3463 if (SN.empty())
3464 return nullptr;
3465 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003466 if (!N)
3467 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003468 }
3469 return N;
3470}
3471
3472// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003473template <typename Alloc, typename Derived>
3474StringView
3475AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003476 const char *Tmp = First;
3477 if (AllowNegative)
3478 consumeIf('n');
3479 if (numLeft() == 0 || !std::isdigit(*First))
3480 return StringView();
3481 while (numLeft() != 0 && std::isdigit(*First))
3482 ++First;
3483 return StringView(Tmp, First);
3484}
3485
3486// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003487template <typename Alloc, typename Derived>
3488bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003489 *Out = 0;
3490 if (look() < '0' || look() > '9')
3491 return true;
3492 while (look() >= '0' && look() <= '9') {
3493 *Out *= 10;
3494 *Out += static_cast<size_t>(consume() - '0');
3495 }
3496 return false;
3497}
3498
Pavel Labathba825192018-10-16 14:29:14 +00003499template <typename Alloc, typename Derived>
3500StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003501 size_t Int = 0;
3502 if (parsePositiveInteger(&Int) || numLeft() < Int)
3503 return StringView();
3504 StringView R(First, First + Int);
3505 First += Int;
3506 return R;
3507}
3508
3509// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3510//
3511// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3512// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3513// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3514//
3515// <ref-qualifier> ::= R # & ref-qualifier
3516// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003517template <typename Derived, typename Alloc>
3518Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003519 Qualifiers CVQuals = parseCVQualifiers();
3520
3521 Node *ExceptionSpec = nullptr;
3522 if (consumeIf("Do")) {
3523 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003524 if (!ExceptionSpec)
3525 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003526 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003527 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003528 if (E == nullptr || !consumeIf('E'))
3529 return nullptr;
3530 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003531 if (!ExceptionSpec)
3532 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003533 } else if (consumeIf("Dw")) {
3534 size_t SpecsBegin = Names.size();
3535 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003536 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003537 if (T == nullptr)
3538 return nullptr;
3539 Names.push_back(T);
3540 }
3541 ExceptionSpec =
3542 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003543 if (!ExceptionSpec)
3544 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003545 }
3546
3547 consumeIf("Dx"); // transaction safe
3548
3549 if (!consumeIf('F'))
3550 return nullptr;
3551 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003552 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003553 if (ReturnType == nullptr)
3554 return nullptr;
3555
3556 FunctionRefQual ReferenceQualifier = FrefQualNone;
3557 size_t ParamsBegin = Names.size();
3558 while (true) {
3559 if (consumeIf('E'))
3560 break;
3561 if (consumeIf('v'))
3562 continue;
3563 if (consumeIf("RE")) {
3564 ReferenceQualifier = FrefQualLValue;
3565 break;
3566 }
3567 if (consumeIf("OE")) {
3568 ReferenceQualifier = FrefQualRValue;
3569 break;
3570 }
Pavel Labathba825192018-10-16 14:29:14 +00003571 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003572 if (T == nullptr)
3573 return nullptr;
3574 Names.push_back(T);
3575 }
3576
3577 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3578 return make<FunctionType>(ReturnType, Params, CVQuals,
3579 ReferenceQualifier, ExceptionSpec);
3580}
3581
3582// extension:
3583// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3584// ::= Dv [<dimension expression>] _ <element type>
3585// <extended element type> ::= <element type>
3586// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003587template <typename Derived, typename Alloc>
3588Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003589 if (!consumeIf("Dv"))
3590 return nullptr;
3591 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003592 Node *DimensionNumber = make<NameType>(parseNumber());
3593 if (!DimensionNumber)
3594 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003595 if (!consumeIf('_'))
3596 return nullptr;
3597 if (consumeIf('p'))
3598 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003599 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003600 if (ElemType == nullptr)
3601 return nullptr;
3602 return make<VectorType>(ElemType, DimensionNumber);
3603 }
3604
3605 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003606 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003607 if (!DimExpr)
3608 return nullptr;
3609 if (!consumeIf('_'))
3610 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003611 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003612 if (!ElemType)
3613 return nullptr;
3614 return make<VectorType>(ElemType, DimExpr);
3615 }
Pavel Labathba825192018-10-16 14:29:14 +00003616 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003617 if (!ElemType)
3618 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003619 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003620}
3621
3622// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3623// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003624template <typename Derived, typename Alloc>
3625Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003626 if (!consumeIf('D'))
3627 return nullptr;
3628 if (!consumeIf('t') && !consumeIf('T'))
3629 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003630 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003631 if (E == nullptr)
3632 return nullptr;
3633 if (!consumeIf('E'))
3634 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003635 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003636}
3637
3638// <array-type> ::= A <positive dimension number> _ <element type>
3639// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003640template <typename Derived, typename Alloc>
3641Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003642 if (!consumeIf('A'))
3643 return nullptr;
3644
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003645 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003646
Richard Smithc20d1442018-08-20 20:14:49 +00003647 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003648 Dimension = make<NameType>(parseNumber());
3649 if (!Dimension)
3650 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003651 if (!consumeIf('_'))
3652 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003653 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003654 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003655 if (DimExpr == nullptr)
3656 return nullptr;
3657 if (!consumeIf('_'))
3658 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003659 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003660 }
3661
Pavel Labathba825192018-10-16 14:29:14 +00003662 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003663 if (Ty == nullptr)
3664 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003665 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003666}
3667
3668// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003669template <typename Derived, typename Alloc>
3670Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003671 if (!consumeIf('M'))
3672 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003673 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003674 if (ClassType == nullptr)
3675 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003676 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003677 if (MemberType == nullptr)
3678 return nullptr;
3679 return make<PointerToMemberType>(ClassType, MemberType);
3680}
3681
3682// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3683// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3684// ::= Tu <name> # dependent elaborated type specifier using 'union'
3685// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003686template <typename Derived, typename Alloc>
3687Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003688 StringView ElabSpef;
3689 if (consumeIf("Ts"))
3690 ElabSpef = "struct";
3691 else if (consumeIf("Tu"))
3692 ElabSpef = "union";
3693 else if (consumeIf("Te"))
3694 ElabSpef = "enum";
3695
Pavel Labathba825192018-10-16 14:29:14 +00003696 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003697 if (Name == nullptr)
3698 return nullptr;
3699
3700 if (!ElabSpef.empty())
3701 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3702
3703 return Name;
3704}
3705
3706// <qualified-type> ::= <qualifiers> <type>
3707// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3708// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003709template <typename Derived, typename Alloc>
3710Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003711 if (consumeIf('U')) {
3712 StringView Qual = parseBareSourceName();
3713 if (Qual.empty())
3714 return nullptr;
3715
Richard Smithc20d1442018-08-20 20:14:49 +00003716 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3717 if (Qual.startsWith("objcproto")) {
3718 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3719 StringView Proto;
3720 {
3721 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3722 SaveLast(Last, ProtoSourceName.end());
3723 Proto = parseBareSourceName();
3724 }
3725 if (Proto.empty())
3726 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003727 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003728 if (Child == nullptr)
3729 return nullptr;
3730 return make<ObjCProtoName>(Child, Proto);
3731 }
3732
Alex Orlovf50df922021-03-24 10:21:32 +04003733 Node *TA = nullptr;
3734 if (look() == 'I') {
3735 TA = getDerived().parseTemplateArgs();
3736 if (TA == nullptr)
3737 return nullptr;
3738 }
3739
Pavel Labathba825192018-10-16 14:29:14 +00003740 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003741 if (Child == nullptr)
3742 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003743 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003744 }
3745
3746 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003747 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003748 if (Ty == nullptr)
3749 return nullptr;
3750 if (Quals != QualNone)
3751 Ty = make<QualType>(Ty, Quals);
3752 return Ty;
3753}
3754
3755// <type> ::= <builtin-type>
3756// ::= <qualified-type>
3757// ::= <function-type>
3758// ::= <class-enum-type>
3759// ::= <array-type>
3760// ::= <pointer-to-member-type>
3761// ::= <template-param>
3762// ::= <template-template-param> <template-args>
3763// ::= <decltype>
3764// ::= P <type> # pointer
3765// ::= R <type> # l-value reference
3766// ::= O <type> # r-value reference (C++11)
3767// ::= C <type> # complex pair (C99)
3768// ::= G <type> # imaginary (C99)
3769// ::= <substitution> # See Compression below
3770// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3771// extension ::= <vector-type> # <vector-type> starts with Dv
3772//
3773// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3774// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003775template <typename Derived, typename Alloc>
3776Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003777 Node *Result = nullptr;
3778
Richard Smithc20d1442018-08-20 20:14:49 +00003779 switch (look()) {
3780 // ::= <qualified-type>
3781 case 'r':
3782 case 'V':
3783 case 'K': {
3784 unsigned AfterQuals = 0;
3785 if (look(AfterQuals) == 'r') ++AfterQuals;
3786 if (look(AfterQuals) == 'V') ++AfterQuals;
3787 if (look(AfterQuals) == 'K') ++AfterQuals;
3788
3789 if (look(AfterQuals) == 'F' ||
3790 (look(AfterQuals) == 'D' &&
3791 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3792 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003793 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003794 break;
3795 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003796 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003797 }
3798 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003799 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003800 break;
3801 }
3802 // <builtin-type> ::= v # void
3803 case 'v':
3804 ++First;
3805 return make<NameType>("void");
3806 // ::= w # wchar_t
3807 case 'w':
3808 ++First;
3809 return make<NameType>("wchar_t");
3810 // ::= b # bool
3811 case 'b':
3812 ++First;
3813 return make<NameType>("bool");
3814 // ::= c # char
3815 case 'c':
3816 ++First;
3817 return make<NameType>("char");
3818 // ::= a # signed char
3819 case 'a':
3820 ++First;
3821 return make<NameType>("signed char");
3822 // ::= h # unsigned char
3823 case 'h':
3824 ++First;
3825 return make<NameType>("unsigned char");
3826 // ::= s # short
3827 case 's':
3828 ++First;
3829 return make<NameType>("short");
3830 // ::= t # unsigned short
3831 case 't':
3832 ++First;
3833 return make<NameType>("unsigned short");
3834 // ::= i # int
3835 case 'i':
3836 ++First;
3837 return make<NameType>("int");
3838 // ::= j # unsigned int
3839 case 'j':
3840 ++First;
3841 return make<NameType>("unsigned int");
3842 // ::= l # long
3843 case 'l':
3844 ++First;
3845 return make<NameType>("long");
3846 // ::= m # unsigned long
3847 case 'm':
3848 ++First;
3849 return make<NameType>("unsigned long");
3850 // ::= x # long long, __int64
3851 case 'x':
3852 ++First;
3853 return make<NameType>("long long");
3854 // ::= y # unsigned long long, __int64
3855 case 'y':
3856 ++First;
3857 return make<NameType>("unsigned long long");
3858 // ::= n # __int128
3859 case 'n':
3860 ++First;
3861 return make<NameType>("__int128");
3862 // ::= o # unsigned __int128
3863 case 'o':
3864 ++First;
3865 return make<NameType>("unsigned __int128");
3866 // ::= f # float
3867 case 'f':
3868 ++First;
3869 return make<NameType>("float");
3870 // ::= d # double
3871 case 'd':
3872 ++First;
3873 return make<NameType>("double");
3874 // ::= e # long double, __float80
3875 case 'e':
3876 ++First;
3877 return make<NameType>("long double");
3878 // ::= g # __float128
3879 case 'g':
3880 ++First;
3881 return make<NameType>("__float128");
3882 // ::= z # ellipsis
3883 case 'z':
3884 ++First;
3885 return make<NameType>("...");
3886
3887 // <builtin-type> ::= u <source-name> # vendor extended type
3888 case 'u': {
3889 ++First;
3890 StringView Res = parseBareSourceName();
3891 if (Res.empty())
3892 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003893 // Typically, <builtin-type>s are not considered substitution candidates,
3894 // but the exception to that exception is vendor extended types (Itanium C++
3895 // ABI 5.9.1).
3896 Result = make<NameType>(Res);
3897 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003898 }
3899 case 'D':
3900 switch (look(1)) {
3901 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3902 case 'd':
3903 First += 2;
3904 return make<NameType>("decimal64");
3905 // ::= De # IEEE 754r decimal floating point (128 bits)
3906 case 'e':
3907 First += 2;
3908 return make<NameType>("decimal128");
3909 // ::= Df # IEEE 754r decimal floating point (32 bits)
3910 case 'f':
3911 First += 2;
3912 return make<NameType>("decimal32");
3913 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3914 case 'h':
3915 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003916 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003917 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3918 case 'F': {
3919 First += 2;
3920 Node *DimensionNumber = make<NameType>(parseNumber());
3921 if (!DimensionNumber)
3922 return nullptr;
3923 if (!consumeIf('_'))
3924 return nullptr;
3925 return make<BinaryFPType>(DimensionNumber);
3926 }
Richard Smithc20d1442018-08-20 20:14:49 +00003927 // ::= Di # char32_t
3928 case 'i':
3929 First += 2;
3930 return make<NameType>("char32_t");
3931 // ::= Ds # char16_t
3932 case 's':
3933 First += 2;
3934 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003935 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3936 case 'u':
3937 First += 2;
3938 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003939 // ::= Da # auto (in dependent new-expressions)
3940 case 'a':
3941 First += 2;
3942 return make<NameType>("auto");
3943 // ::= Dc # decltype(auto)
3944 case 'c':
3945 First += 2;
3946 return make<NameType>("decltype(auto)");
3947 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3948 case 'n':
3949 First += 2;
3950 return make<NameType>("std::nullptr_t");
3951
3952 // ::= <decltype>
3953 case 't':
3954 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003955 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003956 break;
3957 }
3958 // extension ::= <vector-type> # <vector-type> starts with Dv
3959 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003960 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003961 break;
3962 }
3963 // ::= Dp <type> # pack expansion (C++0x)
3964 case 'p': {
3965 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003966 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003967 if (!Child)
3968 return nullptr;
3969 Result = make<ParameterPackExpansion>(Child);
3970 break;
3971 }
3972 // Exception specifier on a function type.
3973 case 'o':
3974 case 'O':
3975 case 'w':
3976 // Transaction safe function type.
3977 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003978 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003979 break;
3980 }
3981 break;
3982 // ::= <function-type>
3983 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003984 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003985 break;
3986 }
3987 // ::= <array-type>
3988 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003989 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003990 break;
3991 }
3992 // ::= <pointer-to-member-type>
3993 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003994 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003995 break;
3996 }
3997 // ::= <template-param>
3998 case 'T': {
3999 // This could be an elaborate type specifier on a <class-enum-type>.
4000 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00004001 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004002 break;
4003 }
4004
Pavel Labathba825192018-10-16 14:29:14 +00004005 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004006 if (Result == nullptr)
4007 return nullptr;
4008
4009 // Result could be either of:
4010 // <type> ::= <template-param>
4011 // <type> ::= <template-template-param> <template-args>
4012 //
4013 // <template-template-param> ::= <template-param>
4014 // ::= <substitution>
4015 //
4016 // If this is followed by some <template-args>, and we're permitted to
4017 // parse them, take the second production.
4018
4019 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004020 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004021 if (TA == nullptr)
4022 return nullptr;
4023 Result = make<NameWithTemplateArgs>(Result, TA);
4024 }
4025 break;
4026 }
4027 // ::= P <type> # pointer
4028 case 'P': {
4029 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004030 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004031 if (Ptr == nullptr)
4032 return nullptr;
4033 Result = make<PointerType>(Ptr);
4034 break;
4035 }
4036 // ::= R <type> # l-value reference
4037 case 'R': {
4038 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004039 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004040 if (Ref == nullptr)
4041 return nullptr;
4042 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4043 break;
4044 }
4045 // ::= O <type> # r-value reference (C++11)
4046 case 'O': {
4047 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004048 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004049 if (Ref == nullptr)
4050 return nullptr;
4051 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4052 break;
4053 }
4054 // ::= C <type> # complex pair (C99)
4055 case 'C': {
4056 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004057 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004058 if (P == nullptr)
4059 return nullptr;
4060 Result = make<PostfixQualifiedType>(P, " complex");
4061 break;
4062 }
4063 // ::= G <type> # imaginary (C99)
4064 case 'G': {
4065 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004066 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004067 if (P == nullptr)
4068 return P;
4069 Result = make<PostfixQualifiedType>(P, " imaginary");
4070 break;
4071 }
4072 // ::= <substitution> # See Compression below
4073 case 'S': {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004074 if (look(1) != 't') {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004075 bool IsSubst = false;
4076 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4077 if (!Result)
Richard Smithc20d1442018-08-20 20:14:49 +00004078 return nullptr;
4079
4080 // Sub could be either of:
4081 // <type> ::= <substitution>
4082 // <type> ::= <template-template-param> <template-args>
4083 //
4084 // <template-template-param> ::= <template-param>
4085 // ::= <substitution>
4086 //
4087 // If this is followed by some <template-args>, and we're permitted to
4088 // parse them, take the second production.
4089
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004090 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4091 if (!IsSubst)
4092 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00004093 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004094 if (TA == nullptr)
4095 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004096 Result = make<NameWithTemplateArgs>(Result, TA);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004097 } else if (IsSubst) {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004098 // If all we parsed was a substitution, don't re-insert into the
4099 // substitution table.
4100 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00004101 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004102 break;
Richard Smithc20d1442018-08-20 20:14:49 +00004103 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004104 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004105 }
4106 // ::= <class-enum-type>
4107 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004108 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004109 break;
4110 }
4111 }
4112
4113 // If we parsed a type, insert it into the substitution table. Note that all
4114 // <builtin-type>s and <substitution>s have already bailed out, because they
4115 // don't get substitutions.
4116 if (Result != nullptr)
4117 Subs.push_back(Result);
4118 return Result;
4119}
4120
Pavel Labathba825192018-10-16 14:29:14 +00004121template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004122Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4123 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004124 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004125 if (E == nullptr)
4126 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004127 return make<PrefixExpr>(Kind, E, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004128}
4129
Pavel Labathba825192018-10-16 14:29:14 +00004130template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004131Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4132 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004133 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004134 if (LHS == nullptr)
4135 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004136 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004137 if (RHS == nullptr)
4138 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004139 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004140}
4141
Pavel Labathba825192018-10-16 14:29:14 +00004142template <typename Derived, typename Alloc>
4143Node *
4144AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004145 StringView Tmp = parseNumber(true);
4146 if (!Tmp.empty() && consumeIf('E'))
4147 return make<IntegerLiteral>(Lit, Tmp);
4148 return nullptr;
4149}
4150
4151// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004152template <typename Alloc, typename Derived>
4153Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004154 Qualifiers CVR = QualNone;
4155 if (consumeIf('r'))
4156 CVR |= QualRestrict;
4157 if (consumeIf('V'))
4158 CVR |= QualVolatile;
4159 if (consumeIf('K'))
4160 CVR |= QualConst;
4161 return CVR;
4162}
4163
4164// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4165// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4166// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4167// ::= 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 -04004168// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004169template <typename Derived, typename Alloc>
4170Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004171 if (consumeIf("fpT"))
4172 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004173 if (consumeIf("fp")) {
4174 parseCVQualifiers();
4175 StringView Num = parseNumber();
4176 if (!consumeIf('_'))
4177 return nullptr;
4178 return make<FunctionParam>(Num);
4179 }
4180 if (consumeIf("fL")) {
4181 if (parseNumber().empty())
4182 return nullptr;
4183 if (!consumeIf('p'))
4184 return nullptr;
4185 parseCVQualifiers();
4186 StringView Num = parseNumber();
4187 if (!consumeIf('_'))
4188 return nullptr;
4189 return make<FunctionParam>(Num);
4190 }
4191 return nullptr;
4192}
4193
Richard Smithc20d1442018-08-20 20:14:49 +00004194// cv <type> <expression> # conversion with one argument
4195// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004196template <typename Derived, typename Alloc>
4197Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004198 if (!consumeIf("cv"))
4199 return nullptr;
4200 Node *Ty;
4201 {
4202 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004203 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004204 }
4205
4206 if (Ty == nullptr)
4207 return nullptr;
4208
4209 if (consumeIf('_')) {
4210 size_t ExprsBegin = Names.size();
4211 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004212 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004213 if (E == nullptr)
4214 return E;
4215 Names.push_back(E);
4216 }
4217 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4218 return make<ConversionExpr>(Ty, Exprs);
4219 }
4220
Pavel Labathba825192018-10-16 14:29:14 +00004221 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004222 if (E[0] == nullptr)
4223 return nullptr;
4224 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4225}
4226
4227// <expr-primary> ::= L <type> <value number> E # integer literal
4228// ::= L <type> <value float> E # floating literal
4229// ::= L <string type> E # string literal
4230// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004231// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004232// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4233// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004234template <typename Derived, typename Alloc>
4235Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004236 if (!consumeIf('L'))
4237 return nullptr;
4238 switch (look()) {
4239 case 'w':
4240 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004241 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004242 case 'b':
4243 if (consumeIf("b0E"))
4244 return make<BoolExpr>(0);
4245 if (consumeIf("b1E"))
4246 return make<BoolExpr>(1);
4247 return nullptr;
4248 case 'c':
4249 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004250 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004251 case 'a':
4252 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004253 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004254 case 'h':
4255 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004256 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004257 case 's':
4258 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004259 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004260 case 't':
4261 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004262 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004263 case 'i':
4264 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004265 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004266 case 'j':
4267 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004268 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004269 case 'l':
4270 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004271 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004272 case 'm':
4273 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004274 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004275 case 'x':
4276 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004277 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004278 case 'y':
4279 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004280 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004281 case 'n':
4282 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004283 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004284 case 'o':
4285 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004286 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004287 case 'f':
4288 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004289 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004290 case 'd':
4291 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004292 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004293 case 'e':
4294 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004295#if defined(__powerpc__) || defined(__s390__)
4296 // Handle cases where long doubles encoded with e have the same size
4297 // and representation as doubles.
4298 return getDerived().template parseFloatingLiteral<double>();
4299#else
Pavel Labathba825192018-10-16 14:29:14 +00004300 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004301#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004302 case '_':
4303 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004304 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004305 if (R != nullptr && consumeIf('E'))
4306 return R;
4307 }
4308 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004309 case 'A': {
4310 Node *T = getDerived().parseType();
4311 if (T == nullptr)
4312 return nullptr;
4313 // FIXME: We need to include the string contents in the mangling.
4314 if (consumeIf('E'))
4315 return make<StringLiteral>(T);
4316 return nullptr;
4317 }
4318 case 'D':
4319 if (consumeIf("DnE"))
4320 return make<NameType>("nullptr");
4321 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004322 case 'T':
4323 // Invalid mangled name per
4324 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4325 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004326 case 'U': {
4327 // FIXME: Should we support LUb... for block literals?
4328 if (look(1) != 'l')
4329 return nullptr;
4330 Node *T = parseUnnamedTypeName(nullptr);
4331 if (!T || !consumeIf('E'))
4332 return nullptr;
4333 return make<LambdaExpr>(T);
4334 }
Richard Smithc20d1442018-08-20 20:14:49 +00004335 default: {
4336 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004337 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004338 if (T == nullptr)
4339 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004340 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004341 if (N.empty())
4342 return nullptr;
4343 if (!consumeIf('E'))
4344 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004345 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004346 }
4347 }
4348}
4349
4350// <braced-expression> ::= <expression>
4351// ::= di <field source-name> <braced-expression> # .name = expr
4352// ::= dx <index expression> <braced-expression> # [expr] = expr
4353// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004354template <typename Derived, typename Alloc>
4355Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004356 if (look() == 'd') {
4357 switch (look(1)) {
4358 case 'i': {
4359 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004360 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004361 if (Field == nullptr)
4362 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004363 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004364 if (Init == nullptr)
4365 return nullptr;
4366 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4367 }
4368 case 'x': {
4369 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004370 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004371 if (Index == nullptr)
4372 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004373 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004374 if (Init == nullptr)
4375 return nullptr;
4376 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4377 }
4378 case 'X': {
4379 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004380 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004381 if (RangeBegin == nullptr)
4382 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004383 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004384 if (RangeEnd == nullptr)
4385 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004386 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004387 if (Init == nullptr)
4388 return nullptr;
4389 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4390 }
4391 }
4392 }
Pavel Labathba825192018-10-16 14:29:14 +00004393 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004394}
4395
4396// (not yet in the spec)
4397// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4398// ::= fR <binary-operator-name> <expression> <expression>
4399// ::= fl <binary-operator-name> <expression>
4400// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004401template <typename Derived, typename Alloc>
4402Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004403 if (!consumeIf('f'))
4404 return nullptr;
4405
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004406 bool IsLeftFold = false, HasInitializer = false;
4407 switch (look()) {
4408 default:
Richard Smithc20d1442018-08-20 20:14:49 +00004409 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004410 case 'L':
4411 IsLeftFold = true;
4412 HasInitializer = true;
4413 break;
4414 case 'R':
4415 HasInitializer = true;
4416 break;
4417 case 'l':
4418 IsLeftFold = true;
4419 break;
4420 case 'r':
4421 break;
4422 }
Richard Smithc20d1442018-08-20 20:14:49 +00004423 ++First;
4424
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004425 const auto *Op = parseOperatorEncoding();
4426 if (!Op || Op->getKind() != OperatorInfo::Binary)
4427 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004428
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004429 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004430 if (Pack == nullptr)
4431 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004432
4433 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004434 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004435 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004436 if (Init == nullptr)
4437 return nullptr;
4438 }
4439
4440 if (IsLeftFold && Init)
4441 std::swap(Pack, Init);
4442
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004443 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004444}
4445
Richard Smith1865d2f2020-10-22 19:29:36 -07004446// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4447//
4448// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4449template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004450Node *
4451AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4452 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004453 Node *Ty = getDerived().parseType();
4454 if (!Ty)
4455 return nullptr;
4456 Node *Expr = getDerived().parseExpr();
4457 if (!Expr)
4458 return nullptr;
4459 StringView Offset = getDerived().parseNumber(true);
4460 if (!consumeIf('E'))
4461 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004462 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004463}
4464
4465// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4466// <union-selector> ::= _ [<number>]
4467//
4468// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4469template <typename Derived, typename Alloc>
4470Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4471 Node *Ty = getDerived().parseType();
4472 if (!Ty)
4473 return nullptr;
4474 Node *Expr = getDerived().parseExpr();
4475 if (!Expr)
4476 return nullptr;
4477 StringView Offset = getDerived().parseNumber(true);
4478 size_t SelectorsBegin = Names.size();
4479 while (consumeIf('_')) {
4480 Node *Selector = make<NameType>(parseNumber());
4481 if (!Selector)
4482 return nullptr;
4483 Names.push_back(Selector);
4484 }
4485 bool OnePastTheEnd = consumeIf('p');
4486 if (!consumeIf('E'))
4487 return nullptr;
4488 return make<SubobjectExpr>(
4489 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4490}
4491
Richard Smithc20d1442018-08-20 20:14:49 +00004492// <expression> ::= <unary operator-name> <expression>
4493// ::= <binary operator-name> <expression> <expression>
4494// ::= <ternary operator-name> <expression> <expression> <expression>
4495// ::= cl <expression>+ E # call
4496// ::= cv <type> <expression> # conversion with one argument
4497// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4498// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4499// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4500// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4501// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4502// ::= [gs] dl <expression> # delete expression
4503// ::= [gs] da <expression> # delete[] expression
4504// ::= pp_ <expression> # prefix ++
4505// ::= mm_ <expression> # prefix --
4506// ::= ti <type> # typeid (type)
4507// ::= te <expression> # typeid (expression)
4508// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4509// ::= sc <type> <expression> # static_cast<type> (expression)
4510// ::= cc <type> <expression> # const_cast<type> (expression)
4511// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4512// ::= st <type> # sizeof (a type)
4513// ::= sz <expression> # sizeof (an expression)
4514// ::= at <type> # alignof (a type)
4515// ::= az <expression> # alignof (an expression)
4516// ::= nx <expression> # noexcept (expression)
4517// ::= <template-param>
4518// ::= <function-param>
4519// ::= dt <expression> <unresolved-name> # expr.name
4520// ::= pt <expression> <unresolved-name> # expr->name
4521// ::= ds <expression> <expression> # expr.*expr
4522// ::= sZ <template-param> # size of a parameter pack
4523// ::= sZ <function-param> # size of a function parameter pack
4524// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4525// ::= sp <expression> # pack expansion
4526// ::= tw <expression> # throw expression
4527// ::= tr # throw with no operand (rethrow)
4528// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4529// # freestanding dependent name (e.g., T::x),
4530// # objectless nonstatic member reference
4531// ::= fL <binary-operator-name> <expression> <expression>
4532// ::= fR <binary-operator-name> <expression> <expression>
4533// ::= fl <binary-operator-name> <expression>
4534// ::= fr <binary-operator-name> <expression>
4535// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004536template <typename Derived, typename Alloc>
4537Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004538 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004539
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004540 const auto *Op = parseOperatorEncoding();
4541 if (Op) {
4542 auto Sym = Op->getSymbol();
4543 switch (Op->getKind()) {
4544 case OperatorInfo::Binary:
4545 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004546 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004547 case OperatorInfo::Prefix:
4548 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004549 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004550 case OperatorInfo::Postfix: {
4551 // Postfix unary operator: expr @
4552 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004553 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004554 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004555 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004556 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004557 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004558 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004559 case OperatorInfo::Array: {
4560 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004561 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004562 if (Base == nullptr)
4563 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004564 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004565 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004566 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004567 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004568 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004569 case OperatorInfo::Member: {
4570 // Member access lhs @ rhs
4571 Node *LHS = getDerived().parseExpr();
4572 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004573 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004574 Node *RHS = getDerived().parseExpr();
4575 if (RHS == nullptr)
4576 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004577 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004578 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004579 case OperatorInfo::New: {
4580 // New
4581 // # new (expr-list) type [(init)]
4582 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4583 // # new[] (expr-list) type [(init)]
4584 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004585 size_t Exprs = Names.size();
4586 while (!consumeIf('_')) {
4587 Node *Ex = getDerived().parseExpr();
4588 if (Ex == nullptr)
4589 return nullptr;
4590 Names.push_back(Ex);
4591 }
4592 NodeArray ExprList = popTrailingNodeArray(Exprs);
4593 Node *Ty = getDerived().parseType();
4594 if (Ty == nullptr)
4595 return nullptr;
4596 bool HaveInits = consumeIf("pi");
4597 size_t InitsBegin = Names.size();
4598 while (!consumeIf('E')) {
4599 if (!HaveInits)
4600 return nullptr;
4601 Node *Init = getDerived().parseExpr();
4602 if (Init == nullptr)
4603 return Init;
4604 Names.push_back(Init);
4605 }
4606 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004607 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004608 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004609 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004610 case OperatorInfo::Del: {
4611 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004612 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004613 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004614 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004615 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4616 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004617 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004618 case OperatorInfo::Call: {
4619 // Function Call
4620 Node *Callee = getDerived().parseExpr();
4621 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004622 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004623 size_t ExprsBegin = Names.size();
4624 while (!consumeIf('E')) {
4625 Node *E = getDerived().parseExpr();
4626 if (E == nullptr)
4627 return nullptr;
4628 Names.push_back(E);
4629 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004630 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4631 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004632 }
4633 case OperatorInfo::CCast: {
4634 // C Cast: (type)expr
4635 Node *Ty;
4636 {
4637 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
4638 Ty = getDerived().parseType();
4639 }
4640 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004641 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004642
4643 size_t ExprsBegin = Names.size();
4644 bool IsMany = consumeIf('_');
4645 while (!consumeIf('E')) {
4646 Node *E = getDerived().parseExpr();
4647 if (E == nullptr)
4648 return E;
4649 Names.push_back(E);
4650 if (!IsMany)
4651 break;
4652 }
4653 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4654 if (!IsMany && Exprs.size() != 1)
4655 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004656 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004657 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004658 case OperatorInfo::Conditional: {
4659 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004660 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004661 if (Cond == nullptr)
4662 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004663 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004664 if (LHS == nullptr)
4665 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004666 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004667 if (RHS == nullptr)
4668 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004669 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004670 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004671 case OperatorInfo::NamedCast: {
4672 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004673 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004674 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004675 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004676 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004677 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004678 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004679 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004680 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004681 case OperatorInfo::OfIdOp: {
4682 // [sizeof/alignof/typeid] ( <type>|<expr> )
4683 Node *Arg =
4684 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4685 if (!Arg)
4686 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004687 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004688 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004689 case OperatorInfo::NameOnly: {
4690 // Not valid as an expression operand.
4691 return nullptr;
4692 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004693 }
4694 DEMANGLE_UNREACHABLE;
4695 }
4696
4697 if (numLeft() < 2)
4698 return nullptr;
4699
4700 if (look() == 'L')
4701 return getDerived().parseExprPrimary();
4702 if (look() == 'T')
4703 return getDerived().parseTemplateParam();
4704 if (look() == 'f') {
4705 // Disambiguate a fold expression from a <function-param>.
4706 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4707 return getDerived().parseFunctionParam();
4708 return getDerived().parseFoldExpr();
4709 }
4710 if (consumeIf("il")) {
4711 size_t InitsBegin = Names.size();
4712 while (!consumeIf('E')) {
4713 Node *E = getDerived().parseBracedExpr();
4714 if (E == nullptr)
4715 return nullptr;
4716 Names.push_back(E);
4717 }
4718 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4719 }
4720 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004721 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004722 if (consumeIf("nx")) {
4723 Node *Ex = getDerived().parseExpr();
4724 if (Ex == nullptr)
4725 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004726 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004727 }
4728 if (consumeIf("so"))
4729 return parseSubobjectExpr();
4730 if (consumeIf("sp")) {
4731 Node *Child = getDerived().parseExpr();
4732 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004733 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004734 return make<ParameterPackExpansion>(Child);
4735 }
4736 if (consumeIf("sZ")) {
4737 if (look() == 'T') {
4738 Node *R = getDerived().parseTemplateParam();
4739 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004740 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004741 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004742 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004743 Node *FP = getDerived().parseFunctionParam();
4744 if (FP == nullptr)
4745 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004746 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004747 }
4748 if (consumeIf("sP")) {
4749 size_t ArgsBegin = Names.size();
4750 while (!consumeIf('E')) {
4751 Node *Arg = getDerived().parseTemplateArg();
4752 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004753 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004754 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004755 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004756 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4757 if (!Pack)
4758 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004759 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004760 }
4761 if (consumeIf("tl")) {
4762 Node *Ty = getDerived().parseType();
4763 if (Ty == nullptr)
4764 return nullptr;
4765 size_t InitsBegin = Names.size();
4766 while (!consumeIf('E')) {
4767 Node *E = getDerived().parseBracedExpr();
4768 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004769 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004770 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004771 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004772 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4773 }
4774 if (consumeIf("tr"))
4775 return make<NameType>("throw");
4776 if (consumeIf("tw")) {
4777 Node *Ex = getDerived().parseExpr();
4778 if (Ex == nullptr)
4779 return nullptr;
4780 return make<ThrowExpr>(Ex);
4781 }
4782 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004783 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4784 if (!Name)
4785 return nullptr;
4786 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4787 // standard encoding expects a <template-arg>, and would be otherwise be
4788 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4789 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4790 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004791 bool IsUUID = false;
4792 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004793 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004794 if (consumeIf('t')) {
4795 UUID = getDerived().parseType();
4796 IsUUID = true;
4797 } else if (consumeIf('z')) {
4798 UUID = getDerived().parseExpr();
4799 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004800 }
4801 }
4802 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004803 if (IsUUID) {
4804 if (UUID == nullptr)
4805 return nullptr;
4806 Names.push_back(UUID);
4807 } else {
4808 while (!consumeIf('E')) {
4809 Node *E = getDerived().parseTemplateArg();
4810 if (E == nullptr)
4811 return E;
4812 Names.push_back(E);
4813 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004814 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004815 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4816 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004817 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004818
4819 // Only unresolved names remain.
4820 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004821}
4822
4823// <call-offset> ::= h <nv-offset> _
4824// ::= v <v-offset> _
4825//
4826// <nv-offset> ::= <offset number>
4827// # non-virtual base override
4828//
4829// <v-offset> ::= <offset number> _ <virtual offset number>
4830// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004831template <typename Alloc, typename Derived>
4832bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004833 // Just scan through the call offset, we never add this information into the
4834 // output.
4835 if (consumeIf('h'))
4836 return parseNumber(true).empty() || !consumeIf('_');
4837 if (consumeIf('v'))
4838 return parseNumber(true).empty() || !consumeIf('_') ||
4839 parseNumber(true).empty() || !consumeIf('_');
4840 return true;
4841}
4842
4843// <special-name> ::= TV <type> # virtual table
4844// ::= TT <type> # VTT structure (construction vtable index)
4845// ::= TI <type> # typeinfo structure
4846// ::= TS <type> # typeinfo name (null-terminated byte string)
4847// ::= Tc <call-offset> <call-offset> <base encoding>
4848// # base is the nominal target function of thunk
4849// # first call-offset is 'this' adjustment
4850// # second call-offset is result adjustment
4851// ::= T <call-offset> <base encoding>
4852// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004853// # Guard variable for one-time initialization
4854// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004855// # No <type>
4856// ::= TW <object name> # Thread-local wrapper
4857// ::= TH <object name> # Thread-local initialization
4858// ::= GR <object name> _ # First temporary
4859// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004860// # construction vtable for second-in-first
4861// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004862// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004863// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004864template <typename Derived, typename Alloc>
4865Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004866 switch (look()) {
4867 case 'T':
4868 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004869 // TA <template-arg> # template parameter object
4870 //
4871 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4872 case 'A': {
4873 First += 2;
4874 Node *Arg = getDerived().parseTemplateArg();
4875 if (Arg == nullptr)
4876 return nullptr;
4877 return make<SpecialName>("template parameter object for ", Arg);
4878 }
Richard Smithc20d1442018-08-20 20:14:49 +00004879 // TV <type> # virtual table
4880 case 'V': {
4881 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004882 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004883 if (Ty == nullptr)
4884 return nullptr;
4885 return make<SpecialName>("vtable for ", Ty);
4886 }
4887 // TT <type> # VTT structure (construction vtable index)
4888 case 'T': {
4889 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004890 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004891 if (Ty == nullptr)
4892 return nullptr;
4893 return make<SpecialName>("VTT for ", Ty);
4894 }
4895 // TI <type> # typeinfo structure
4896 case 'I': {
4897 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004898 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004899 if (Ty == nullptr)
4900 return nullptr;
4901 return make<SpecialName>("typeinfo for ", Ty);
4902 }
4903 // TS <type> # typeinfo name (null-terminated byte string)
4904 case 'S': {
4905 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004906 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004907 if (Ty == nullptr)
4908 return nullptr;
4909 return make<SpecialName>("typeinfo name for ", Ty);
4910 }
4911 // Tc <call-offset> <call-offset> <base encoding>
4912 case 'c': {
4913 First += 2;
4914 if (parseCallOffset() || parseCallOffset())
4915 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004916 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004917 if (Encoding == nullptr)
4918 return nullptr;
4919 return make<SpecialName>("covariant return thunk to ", Encoding);
4920 }
4921 // extension ::= TC <first type> <number> _ <second type>
4922 // # construction vtable for second-in-first
4923 case 'C': {
4924 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004925 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004926 if (FirstType == nullptr)
4927 return nullptr;
4928 if (parseNumber(true).empty() || !consumeIf('_'))
4929 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004930 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004931 if (SecondType == nullptr)
4932 return nullptr;
4933 return make<CtorVtableSpecialName>(SecondType, FirstType);
4934 }
4935 // TW <object name> # Thread-local wrapper
4936 case 'W': {
4937 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004938 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004939 if (Name == nullptr)
4940 return nullptr;
4941 return make<SpecialName>("thread-local wrapper routine for ", Name);
4942 }
4943 // TH <object name> # Thread-local initialization
4944 case 'H': {
4945 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004946 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004947 if (Name == nullptr)
4948 return nullptr;
4949 return make<SpecialName>("thread-local initialization routine for ", Name);
4950 }
4951 // T <call-offset> <base encoding>
4952 default: {
4953 ++First;
4954 bool IsVirt = look() == 'v';
4955 if (parseCallOffset())
4956 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004957 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004958 if (BaseEncoding == nullptr)
4959 return nullptr;
4960 if (IsVirt)
4961 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4962 else
4963 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4964 }
4965 }
4966 case 'G':
4967 switch (look(1)) {
4968 // GV <object name> # Guard variable for one-time initialization
4969 case 'V': {
4970 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004971 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004972 if (Name == nullptr)
4973 return nullptr;
4974 return make<SpecialName>("guard variable for ", Name);
4975 }
4976 // GR <object name> # reference temporary for object
4977 // GR <object name> _ # First temporary
4978 // GR <object name> <seq-id> _ # Subsequent temporaries
4979 case 'R': {
4980 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004981 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004982 if (Name == nullptr)
4983 return nullptr;
4984 size_t Count;
4985 bool ParsedSeqId = !parseSeqId(&Count);
4986 if (!consumeIf('_') && ParsedSeqId)
4987 return nullptr;
4988 return make<SpecialName>("reference temporary for ", Name);
4989 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004990 // GI <module-name> v
4991 case 'I': {
4992 First += 2;
4993 ModuleName *Module = nullptr;
4994 if (getDerived().parseModuleNameOpt(Module))
4995 return nullptr;
4996 if (Module == nullptr)
4997 return nullptr;
4998 return make<SpecialName>("initializer for module ", Module);
4999 }
Richard Smithc20d1442018-08-20 20:14:49 +00005000 }
5001 }
5002 return nullptr;
5003}
5004
5005// <encoding> ::= <function name> <bare-function-type>
5006// ::= <data name>
5007// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005008template <typename Derived, typename Alloc>
5009Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005010 // The template parameters of an encoding are unrelated to those of the
5011 // enclosing context.
5012 class SaveTemplateParams {
5013 AbstractManglingParser *Parser;
5014 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005015 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005016
5017 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005018 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005019 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005020 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005021 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005022 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005023 }
5024 ~SaveTemplateParams() {
5025 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005026 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005027 }
5028 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005029
Richard Smithc20d1442018-08-20 20:14:49 +00005030 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005031 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005032
5033 auto IsEndOfEncoding = [&] {
5034 // The set of chars that can potentially follow an <encoding> (none of which
5035 // can start a <type>). Enumerating these allows us to avoid speculative
5036 // parsing.
5037 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5038 };
5039
5040 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005041 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005042 if (Name == nullptr)
5043 return nullptr;
5044
5045 if (resolveForwardTemplateRefs(NameInfo))
5046 return nullptr;
5047
5048 if (IsEndOfEncoding())
5049 return Name;
5050
5051 Node *Attrs = nullptr;
5052 if (consumeIf("Ua9enable_ifI")) {
5053 size_t BeforeArgs = Names.size();
5054 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005055 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005056 if (Arg == nullptr)
5057 return nullptr;
5058 Names.push_back(Arg);
5059 }
5060 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005061 if (!Attrs)
5062 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005063 }
5064
5065 Node *ReturnType = nullptr;
5066 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005067 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005068 if (ReturnType == nullptr)
5069 return nullptr;
5070 }
5071
5072 if (consumeIf('v'))
5073 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5074 Attrs, NameInfo.CVQualifiers,
5075 NameInfo.ReferenceQualifier);
5076
5077 size_t ParamsBegin = Names.size();
5078 do {
Pavel Labathba825192018-10-16 14:29:14 +00005079 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005080 if (Ty == nullptr)
5081 return nullptr;
5082 Names.push_back(Ty);
5083 } while (!IsEndOfEncoding());
5084
5085 return make<FunctionEncoding>(ReturnType, Name,
5086 popTrailingNodeArray(ParamsBegin),
5087 Attrs, NameInfo.CVQualifiers,
5088 NameInfo.ReferenceQualifier);
5089}
5090
5091template <class Float>
5092struct FloatData;
5093
5094template <>
5095struct FloatData<float>
5096{
5097 static const size_t mangled_size = 8;
5098 static const size_t max_demangled_size = 24;
5099 static constexpr const char* spec = "%af";
5100};
5101
5102template <>
5103struct FloatData<double>
5104{
5105 static const size_t mangled_size = 16;
5106 static const size_t max_demangled_size = 32;
5107 static constexpr const char* spec = "%a";
5108};
5109
5110template <>
5111struct FloatData<long double>
5112{
5113#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5114 defined(__wasm__)
5115 static const size_t mangled_size = 32;
5116#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5117 static const size_t mangled_size = 16;
5118#else
5119 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5120#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005121 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5122 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5123 // Negatives are one character longer than positives.
5124 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5125 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5126 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005127 static constexpr const char *spec = "%LaL";
5128};
5129
Pavel Labathba825192018-10-16 14:29:14 +00005130template <typename Alloc, typename Derived>
5131template <class Float>
5132Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005133 const size_t N = FloatData<Float>::mangled_size;
5134 if (numLeft() <= N)
5135 return nullptr;
5136 StringView Data(First, First + N);
5137 for (char C : Data)
5138 if (!std::isxdigit(C))
5139 return nullptr;
5140 First += N;
5141 if (!consumeIf('E'))
5142 return nullptr;
5143 return make<FloatLiteralImpl<Float>>(Data);
5144}
5145
5146// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005147template <typename Alloc, typename Derived>
5148bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005149 if (!(look() >= '0' && look() <= '9') &&
5150 !(look() >= 'A' && look() <= 'Z'))
5151 return true;
5152
5153 size_t Id = 0;
5154 while (true) {
5155 if (look() >= '0' && look() <= '9') {
5156 Id *= 36;
5157 Id += static_cast<size_t>(look() - '0');
5158 } else if (look() >= 'A' && look() <= 'Z') {
5159 Id *= 36;
5160 Id += static_cast<size_t>(look() - 'A') + 10;
5161 } else {
5162 *Out = Id;
5163 return false;
5164 }
5165 ++First;
5166 }
5167}
5168
5169// <substitution> ::= S <seq-id> _
5170// ::= S_
5171// <substitution> ::= Sa # ::std::allocator
5172// <substitution> ::= Sb # ::std::basic_string
5173// <substitution> ::= Ss # ::std::basic_string < char,
5174// ::std::char_traits<char>,
5175// ::std::allocator<char> >
5176// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5177// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5178// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005179// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005180template <typename Derived, typename Alloc>
5181Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005182 if (!consumeIf('S'))
5183 return nullptr;
5184
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005185 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005186 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005187 switch (look()) {
5188 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005189 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005190 break;
5191 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005192 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005193 break;
5194 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005195 Kind = SpecialSubKind::iostream;
5196 break;
5197 case 'i':
5198 Kind = SpecialSubKind::istream;
5199 break;
5200 case 'o':
5201 Kind = SpecialSubKind::ostream;
5202 break;
5203 case 's':
5204 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005205 break;
5206 default:
5207 return nullptr;
5208 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005209 ++First;
5210 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005211 if (!SpecialSub)
5212 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005213
Richard Smithc20d1442018-08-20 20:14:49 +00005214 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5215 // has ABI tags, the tags are appended to the substitution; the result is a
5216 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005217 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005218 if (WithTags != SpecialSub) {
5219 Subs.push_back(WithTags);
5220 SpecialSub = WithTags;
5221 }
5222 return SpecialSub;
5223 }
5224
5225 // ::= S_
5226 if (consumeIf('_')) {
5227 if (Subs.empty())
5228 return nullptr;
5229 return Subs[0];
5230 }
5231
5232 // ::= S <seq-id> _
5233 size_t Index = 0;
5234 if (parseSeqId(&Index))
5235 return nullptr;
5236 ++Index;
5237 if (!consumeIf('_') || Index >= Subs.size())
5238 return nullptr;
5239 return Subs[Index];
5240}
5241
5242// <template-param> ::= T_ # first template parameter
5243// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005244// ::= TL <level-1> __
5245// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005246template <typename Derived, typename Alloc>
5247Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005248 if (!consumeIf('T'))
5249 return nullptr;
5250
Richard Smithdf1c14c2019-09-06 23:53:21 +00005251 size_t Level = 0;
5252 if (consumeIf('L')) {
5253 if (parsePositiveInteger(&Level))
5254 return nullptr;
5255 ++Level;
5256 if (!consumeIf('_'))
5257 return nullptr;
5258 }
5259
Richard Smithc20d1442018-08-20 20:14:49 +00005260 size_t Index = 0;
5261 if (!consumeIf('_')) {
5262 if (parsePositiveInteger(&Index))
5263 return nullptr;
5264 ++Index;
5265 if (!consumeIf('_'))
5266 return nullptr;
5267 }
5268
Richard Smithc20d1442018-08-20 20:14:49 +00005269 // If we're in a context where this <template-param> refers to a
5270 // <template-arg> further ahead in the mangled name (currently just conversion
5271 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005272 // This can only happen at the outermost level.
5273 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005274 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5275 if (!ForwardRef)
5276 return nullptr;
5277 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5278 ForwardTemplateRefs.push_back(
5279 static_cast<ForwardTemplateReference *>(ForwardRef));
5280 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005281 }
5282
Richard Smithdf1c14c2019-09-06 23:53:21 +00005283 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5284 Index >= TemplateParams[Level]->size()) {
5285 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5286 // list are mangled as the corresponding artificial template type parameter.
5287 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5288 // This will be popped by the ScopedTemplateParamList in
5289 // parseUnnamedTypeName.
5290 if (Level == TemplateParams.size())
5291 TemplateParams.push_back(nullptr);
5292 return make<NameType>("auto");
5293 }
5294
Richard Smithc20d1442018-08-20 20:14:49 +00005295 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005296 }
5297
5298 return (*TemplateParams[Level])[Index];
5299}
5300
5301// <template-param-decl> ::= Ty # type parameter
5302// ::= Tn <type> # non-type parameter
5303// ::= Tt <template-param-decl>* E # template parameter
5304// ::= Tp <template-param-decl> # parameter pack
5305template <typename Derived, typename Alloc>
5306Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5307 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5308 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5309 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5310 if (N) TemplateParams.back()->push_back(N);
5311 return N;
5312 };
5313
5314 if (consumeIf("Ty")) {
5315 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5316 if (!Name)
5317 return nullptr;
5318 return make<TypeTemplateParamDecl>(Name);
5319 }
5320
5321 if (consumeIf("Tn")) {
5322 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5323 if (!Name)
5324 return nullptr;
5325 Node *Type = parseType();
5326 if (!Type)
5327 return nullptr;
5328 return make<NonTypeTemplateParamDecl>(Name, Type);
5329 }
5330
5331 if (consumeIf("Tt")) {
5332 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5333 if (!Name)
5334 return nullptr;
5335 size_t ParamsBegin = Names.size();
5336 ScopedTemplateParamList TemplateTemplateParamParams(this);
5337 while (!consumeIf("E")) {
5338 Node *P = parseTemplateParamDecl();
5339 if (!P)
5340 return nullptr;
5341 Names.push_back(P);
5342 }
5343 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5344 return make<TemplateTemplateParamDecl>(Name, Params);
5345 }
5346
5347 if (consumeIf("Tp")) {
5348 Node *P = parseTemplateParamDecl();
5349 if (!P)
5350 return nullptr;
5351 return make<TemplateParamPackDecl>(P);
5352 }
5353
5354 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005355}
5356
5357// <template-arg> ::= <type> # type or template
5358// ::= X <expression> E # expression
5359// ::= <expr-primary> # simple expressions
5360// ::= J <template-arg>* E # argument pack
5361// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005362template <typename Derived, typename Alloc>
5363Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005364 switch (look()) {
5365 case 'X': {
5366 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005367 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005368 if (Arg == nullptr || !consumeIf('E'))
5369 return nullptr;
5370 return Arg;
5371 }
5372 case 'J': {
5373 ++First;
5374 size_t ArgsBegin = Names.size();
5375 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005376 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005377 if (Arg == nullptr)
5378 return nullptr;
5379 Names.push_back(Arg);
5380 }
5381 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5382 return make<TemplateArgumentPack>(Args);
5383 }
5384 case 'L': {
5385 // ::= LZ <encoding> E # extension
5386 if (look(1) == 'Z') {
5387 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005388 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005389 if (Arg == nullptr || !consumeIf('E'))
5390 return nullptr;
5391 return Arg;
5392 }
5393 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005394 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005395 }
5396 default:
Pavel Labathba825192018-10-16 14:29:14 +00005397 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005398 }
5399}
5400
5401// <template-args> ::= I <template-arg>* E
5402// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005403template <typename Derived, typename Alloc>
5404Node *
5405AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005406 if (!consumeIf('I'))
5407 return nullptr;
5408
5409 // <template-params> refer to the innermost <template-args>. Clear out any
5410 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005411 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005412 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005413 TemplateParams.push_back(&OuterTemplateParams);
5414 OuterTemplateParams.clear();
5415 }
Richard Smithc20d1442018-08-20 20:14:49 +00005416
5417 size_t ArgsBegin = Names.size();
5418 while (!consumeIf('E')) {
5419 if (TagTemplates) {
5420 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005421 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005422 TemplateParams = std::move(OldParams);
5423 if (Arg == nullptr)
5424 return nullptr;
5425 Names.push_back(Arg);
5426 Node *TableEntry = Arg;
5427 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5428 TableEntry = make<ParameterPack>(
5429 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005430 if (!TableEntry)
5431 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005432 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005433 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005434 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005435 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005436 if (Arg == nullptr)
5437 return nullptr;
5438 Names.push_back(Arg);
5439 }
5440 }
5441 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5442}
5443
5444// <mangled-name> ::= _Z <encoding>
5445// ::= <type>
5446// extension ::= ___Z <encoding> _block_invoke
5447// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5448// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005449template <typename Derived, typename Alloc>
5450Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005451 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005452 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005453 if (Encoding == nullptr)
5454 return nullptr;
5455 if (look() == '.') {
5456 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5457 First = Last;
5458 }
5459 if (numLeft() != 0)
5460 return nullptr;
5461 return Encoding;
5462 }
5463
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005464 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005465 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005466 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5467 return nullptr;
5468 bool RequireNumber = consumeIf('_');
5469 if (parseNumber().empty() && RequireNumber)
5470 return nullptr;
5471 if (look() == '.')
5472 First = Last;
5473 if (numLeft() != 0)
5474 return nullptr;
5475 return make<SpecialName>("invocation function for block in ", Encoding);
5476 }
5477
Pavel Labathba825192018-10-16 14:29:14 +00005478 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005479 if (numLeft() != 0)
5480 return nullptr;
5481 return Ty;
5482}
5483
Pavel Labathba825192018-10-16 14:29:14 +00005484template <typename Alloc>
5485struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5486 using AbstractManglingParser<ManglingParser<Alloc>,
5487 Alloc>::AbstractManglingParser;
5488};
5489
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005490DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005491
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005492#endif // DEMANGLE_ITANIUMDEMANGLE_H