blob: 46b390bcd996abf79bf0d303b8243b6a137ef008 [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 Sidwell458a94f2022-02-04 11:45:23 -08001710 bool ParenAll = OB.isGtInsideTemplateArgs() && InfixOperator == ">";
1711 if (ParenAll)
1712 OB.printOpen();
1713 // Assignment is right associative, with special LHS precedence.
1714 bool IsAssign = getPrecedence() == Prec::Assign;
1715 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1716 // No space before comma operator
1717 if (!(InfixOperator == ","))
1718 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001719 OB += InfixOperator;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001720 OB += " ";
1721 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1722 if (ParenAll)
1723 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001724 }
1725};
1726
1727class ArraySubscriptExpr : public Node {
1728 const Node *Op1;
1729 const Node *Op2;
1730
1731public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001732 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1733 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001734
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001735 template <typename Fn> void match(Fn F) const {
1736 F(Op1, Op2, getPrecedence());
1737 }
Richard Smithc20d1442018-08-20 20:14:49 +00001738
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001739 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001740 Op1->printAsOperand(OB, getPrecedence());
1741 OB.printOpen('[');
1742 Op2->printAsOperand(OB);
1743 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001744 }
1745};
1746
1747class PostfixExpr : public Node {
1748 const Node *Child;
1749 const StringView Operator;
1750
1751public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001752 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
1753 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001754
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001755 template <typename Fn> void match(Fn F) const {
1756 F(Child, Operator, getPrecedence());
1757 }
Richard Smithc20d1442018-08-20 20:14:49 +00001758
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001759 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001760 Child->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001761 OB += Operator;
Richard Smithc20d1442018-08-20 20:14:49 +00001762 }
1763};
1764
1765class ConditionalExpr : public Node {
1766 const Node *Cond;
1767 const Node *Then;
1768 const Node *Else;
1769
1770public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001771 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1772 Prec Prec_)
1773 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001774
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001775 template <typename Fn> void match(Fn F) const {
1776 F(Cond, Then, Else, getPrecedence());
1777 }
Richard Smithc20d1442018-08-20 20:14:49 +00001778
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001779 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001780 Cond->printAsOperand(OB, getPrecedence());
1781 OB += " ? ";
1782 Then->printAsOperand(OB);
1783 OB += " : ";
1784 Else->printAsOperand(OB, Prec::Assign, true);
Richard Smithc20d1442018-08-20 20:14:49 +00001785 }
1786};
1787
1788class MemberExpr : public Node {
1789 const Node *LHS;
1790 const StringView Kind;
1791 const Node *RHS;
1792
1793public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001794 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
1795 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001796
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001797 template <typename Fn> void match(Fn F) const {
1798 F(LHS, Kind, RHS, getPrecedence());
1799 }
Richard Smithc20d1442018-08-20 20:14:49 +00001800
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001801 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001802 LHS->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001803 OB += Kind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001804 RHS->printAsOperand(OB, getPrecedence(), false);
Richard Smithc20d1442018-08-20 20:14:49 +00001805 }
1806};
1807
Richard Smith1865d2f2020-10-22 19:29:36 -07001808class SubobjectExpr : public Node {
1809 const Node *Type;
1810 const Node *SubExpr;
1811 StringView Offset;
1812 NodeArray UnionSelectors;
1813 bool OnePastTheEnd;
1814
1815public:
1816 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1817 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1818 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1819 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1820
1821 template<typename Fn> void match(Fn F) const {
1822 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1823 }
1824
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001825 void printLeft(OutputBuffer &OB) const override {
1826 SubExpr->print(OB);
1827 OB += ".<";
1828 Type->print(OB);
1829 OB += " at offset ";
Richard Smith1865d2f2020-10-22 19:29:36 -07001830 if (Offset.empty()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001831 OB += "0";
Richard Smith1865d2f2020-10-22 19:29:36 -07001832 } else if (Offset[0] == 'n') {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001833 OB += "-";
1834 OB += Offset.dropFront();
Richard Smith1865d2f2020-10-22 19:29:36 -07001835 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001836 OB += Offset;
Richard Smith1865d2f2020-10-22 19:29:36 -07001837 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001838 OB += ">";
Richard Smith1865d2f2020-10-22 19:29:36 -07001839 }
1840};
1841
Richard Smithc20d1442018-08-20 20:14:49 +00001842class EnclosingExpr : public Node {
1843 const StringView Prefix;
1844 const Node *Infix;
1845 const StringView Postfix;
1846
1847public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001848 EnclosingExpr(StringView Prefix_, const Node *Infix_,
1849 Prec Prec_ = Prec::Primary)
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001850 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001851
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001852 template <typename Fn> void match(Fn F) const {
1853 F(Prefix, Infix, getPrecedence());
1854 }
Richard Smithc20d1442018-08-20 20:14:49 +00001855
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001856 void printLeft(OutputBuffer &OB) const override {
1857 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001858 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001859 Infix->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001860 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001861 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +00001862 }
1863};
1864
1865class CastExpr : public Node {
1866 // cast_kind<to>(from)
1867 const StringView CastKind;
1868 const Node *To;
1869 const Node *From;
1870
1871public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001872 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
1873 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001874
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001875 template <typename Fn> void match(Fn F) const {
1876 F(CastKind, To, From, getPrecedence());
1877 }
Richard Smithc20d1442018-08-20 20:14:49 +00001878
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001879 void printLeft(OutputBuffer &OB) const override {
1880 OB += CastKind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001881 {
1882 SwapAndRestore<unsigned> LT(OB.GtIsGt, 0);
1883 OB += "<";
1884 To->printLeft(OB);
1885 if (OB.back() == '>')
1886 OB += " ";
1887 OB += ">";
1888 }
1889 OB.printOpen();
1890 From->printAsOperand(OB);
1891 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001892 }
1893};
1894
1895class SizeofParamPackExpr : public Node {
1896 const Node *Pack;
1897
1898public:
1899 SizeofParamPackExpr(const Node *Pack_)
1900 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1901
1902 template<typename Fn> void match(Fn F) const { F(Pack); }
1903
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001904 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001905 OB += "sizeof...";
1906 OB.printOpen();
Richard Smithc20d1442018-08-20 20:14:49 +00001907 ParameterPackExpansion PPE(Pack);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001908 PPE.printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001909 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001910 }
1911};
1912
1913class CallExpr : public Node {
1914 const Node *Callee;
1915 NodeArray Args;
1916
1917public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001918 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
1919 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001920
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001921 template <typename Fn> void match(Fn F) const {
1922 F(Callee, Args, getPrecedence());
1923 }
Richard Smithc20d1442018-08-20 20:14:49 +00001924
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001925 void printLeft(OutputBuffer &OB) const override {
1926 Callee->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001927 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001928 Args.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001929 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001930 }
1931};
1932
1933class NewExpr : public Node {
1934 // new (expr_list) type(init_list)
1935 NodeArray ExprList;
1936 Node *Type;
1937 NodeArray InitList;
1938 bool IsGlobal; // ::operator new ?
1939 bool IsArray; // new[] ?
1940public:
1941 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001942 bool IsArray_, Prec Prec_)
1943 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
1944 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001945
1946 template<typename Fn> void match(Fn F) const {
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001947 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00001948 }
1949
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001950 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001951 if (IsGlobal)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001952 OB += "::";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001953 OB += "new";
Richard Smithc20d1442018-08-20 20:14:49 +00001954 if (IsArray)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001955 OB += "[]";
Richard Smithc20d1442018-08-20 20:14:49 +00001956 if (!ExprList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001957 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001958 ExprList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001959 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001960 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001961 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001962 Type->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001963 if (!InitList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001964 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001965 InitList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001966 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001967 }
Richard Smithc20d1442018-08-20 20:14:49 +00001968 }
1969};
1970
1971class DeleteExpr : public Node {
1972 Node *Op;
1973 bool IsGlobal;
1974 bool IsArray;
1975
1976public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001977 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
1978 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
1979 IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001980
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001981 template <typename Fn> void match(Fn F) const {
1982 F(Op, IsGlobal, IsArray, getPrecedence());
1983 }
Richard Smithc20d1442018-08-20 20:14:49 +00001984
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001985 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001986 if (IsGlobal)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001987 OB += "::";
1988 OB += "delete";
Richard Smithc20d1442018-08-20 20:14:49 +00001989 if (IsArray)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001990 OB += "[]";
1991 OB += ' ';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001992 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001993 }
1994};
1995
1996class PrefixExpr : public Node {
1997 StringView Prefix;
1998 Node *Child;
1999
2000public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002001 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
2002 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002003
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002004 template <typename Fn> void match(Fn F) const {
2005 F(Prefix, Child, getPrecedence());
2006 }
Richard Smithc20d1442018-08-20 20:14:49 +00002007
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002008 void printLeft(OutputBuffer &OB) const override {
2009 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002010 Child->printAsOperand(OB, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00002011 }
2012};
2013
2014class FunctionParam : public Node {
2015 StringView Number;
2016
2017public:
2018 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
2019
2020 template<typename Fn> void match(Fn F) const { F(Number); }
2021
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002022 void printLeft(OutputBuffer &OB) const override {
2023 OB += "fp";
2024 OB += Number;
Richard Smithc20d1442018-08-20 20:14:49 +00002025 }
2026};
2027
2028class ConversionExpr : public Node {
2029 const Node *Type;
2030 NodeArray Expressions;
2031
2032public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002033 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2034 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002035
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002036 template <typename Fn> void match(Fn F) const {
2037 F(Type, Expressions, getPrecedence());
2038 }
Richard Smithc20d1442018-08-20 20:14:49 +00002039
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002040 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002041 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002042 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002043 OB.printClose();
2044 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002045 Expressions.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002046 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002047 }
2048};
2049
Richard Smith1865d2f2020-10-22 19:29:36 -07002050class PointerToMemberConversionExpr : public Node {
2051 const Node *Type;
2052 const Node *SubExpr;
2053 StringView Offset;
2054
2055public:
2056 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002057 StringView Offset_, Prec Prec_)
2058 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2059 SubExpr(SubExpr_), Offset(Offset_) {}
Richard Smith1865d2f2020-10-22 19:29:36 -07002060
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002061 template <typename Fn> void match(Fn F) const {
2062 F(Type, SubExpr, Offset, getPrecedence());
2063 }
Richard Smith1865d2f2020-10-22 19:29:36 -07002064
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002065 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002066 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002067 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002068 OB.printClose();
2069 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002070 SubExpr->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002071 OB.printClose();
Richard Smith1865d2f2020-10-22 19:29:36 -07002072 }
2073};
2074
Richard Smithc20d1442018-08-20 20:14:49 +00002075class InitListExpr : public Node {
2076 const Node *Ty;
2077 NodeArray Inits;
2078public:
2079 InitListExpr(const Node *Ty_, NodeArray Inits_)
2080 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2081
2082 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2083
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002084 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002085 if (Ty)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002086 Ty->print(OB);
2087 OB += '{';
2088 Inits.printWithComma(OB);
2089 OB += '}';
Richard Smithc20d1442018-08-20 20:14:49 +00002090 }
2091};
2092
2093class BracedExpr : public Node {
2094 const Node *Elem;
2095 const Node *Init;
2096 bool IsArray;
2097public:
2098 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2099 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2100
2101 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
2102
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002103 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002104 if (IsArray) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002105 OB += '[';
2106 Elem->print(OB);
2107 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002108 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002109 OB += '.';
2110 Elem->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002111 }
2112 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002113 OB += " = ";
2114 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002115 }
2116};
2117
2118class BracedRangeExpr : public Node {
2119 const Node *First;
2120 const Node *Last;
2121 const Node *Init;
2122public:
2123 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2124 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2125
2126 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2127
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002128 void printLeft(OutputBuffer &OB) const override {
2129 OB += '[';
2130 First->print(OB);
2131 OB += " ... ";
2132 Last->print(OB);
2133 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002134 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002135 OB += " = ";
2136 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002137 }
2138};
2139
2140class FoldExpr : public Node {
2141 const Node *Pack, *Init;
2142 StringView OperatorName;
2143 bool IsLeftFold;
2144
2145public:
2146 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
2147 const Node *Init_)
2148 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2149 IsLeftFold(IsLeftFold_) {}
2150
2151 template<typename Fn> void match(Fn F) const {
2152 F(IsLeftFold, OperatorName, Pack, Init);
2153 }
2154
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002155 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002156 auto PrintPack = [&] {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002157 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002158 ParameterPackExpansion(Pack).print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002159 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002160 };
2161
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002162 OB.printOpen();
2163 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2164 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2165 // Fold expr operands are cast-expressions
2166 if (!IsLeftFold || Init != nullptr) {
2167 // '(init|pack) op '
2168 if (IsLeftFold)
2169 Init->printAsOperand(OB, Prec::Cast, true);
2170 else
2171 PrintPack();
2172 OB << " " << OperatorName << " ";
Richard Smithc20d1442018-08-20 20:14:49 +00002173 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002174 OB << "...";
2175 if (IsLeftFold || Init != nullptr) {
2176 // ' op (init|pack)'
2177 OB << " " << OperatorName << " ";
2178 if (IsLeftFold)
2179 PrintPack();
2180 else
2181 Init->printAsOperand(OB, Prec::Cast, true);
2182 }
2183 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002184 }
2185};
2186
2187class ThrowExpr : public Node {
2188 const Node *Op;
2189
2190public:
2191 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2192
2193 template<typename Fn> void match(Fn F) const { F(Op); }
2194
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002195 void printLeft(OutputBuffer &OB) const override {
2196 OB += "throw ";
2197 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002198 }
2199};
2200
2201class BoolExpr : public Node {
2202 bool Value;
2203
2204public:
2205 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2206
2207 template<typename Fn> void match(Fn F) const { F(Value); }
2208
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002209 void printLeft(OutputBuffer &OB) const override {
2210 OB += Value ? StringView("true") : StringView("false");
Richard Smithc20d1442018-08-20 20:14:49 +00002211 }
2212};
2213
Richard Smithdf1c14c2019-09-06 23:53:21 +00002214class StringLiteral : public Node {
2215 const Node *Type;
2216
2217public:
2218 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2219
2220 template<typename Fn> void match(Fn F) const { F(Type); }
2221
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002222 void printLeft(OutputBuffer &OB) const override {
2223 OB += "\"<";
2224 Type->print(OB);
2225 OB += ">\"";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002226 }
2227};
2228
2229class LambdaExpr : public Node {
2230 const Node *Type;
2231
Richard Smithdf1c14c2019-09-06 23:53:21 +00002232public:
2233 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2234
2235 template<typename Fn> void match(Fn F) const { F(Type); }
2236
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002237 void printLeft(OutputBuffer &OB) const override {
2238 OB += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002239 if (Type->getKind() == KClosureTypeName)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002240 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2241 OB += "{...}";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002242 }
2243};
2244
Erik Pilkington0a170f12020-05-13 14:13:37 -04002245class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002246 // ty(integer)
2247 const Node *Ty;
2248 StringView Integer;
2249
2250public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002251 EnumLiteral(const Node *Ty_, StringView Integer_)
2252 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002253
2254 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2255
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002256 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002257 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002258 Ty->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002259 OB.printClose();
Erik Pilkington0a170f12020-05-13 14:13:37 -04002260
2261 if (Integer[0] == 'n')
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002262 OB << "-" << Integer.dropFront(1);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002263 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002264 OB << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002265 }
2266};
2267
2268class IntegerLiteral : public Node {
2269 StringView Type;
2270 StringView Value;
2271
2272public:
2273 IntegerLiteral(StringView Type_, StringView Value_)
2274 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2275
2276 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2277
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002278 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002279 if (Type.size() > 3) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002280 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002281 OB += Type;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002282 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002283 }
2284
2285 if (Value[0] == 'n') {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002286 OB += '-';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002287 OB += Value.dropFront(1);
Richard Smithc20d1442018-08-20 20:14:49 +00002288 } else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002289 OB += Value;
Richard Smithc20d1442018-08-20 20:14:49 +00002290
2291 if (Type.size() <= 3)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002292 OB += Type;
Richard Smithc20d1442018-08-20 20:14:49 +00002293 }
2294};
2295
2296template <class Float> struct FloatData;
2297
2298namespace float_literal_impl {
2299constexpr Node::Kind getFloatLiteralKind(float *) {
2300 return Node::KFloatLiteral;
2301}
2302constexpr Node::Kind getFloatLiteralKind(double *) {
2303 return Node::KDoubleLiteral;
2304}
2305constexpr Node::Kind getFloatLiteralKind(long double *) {
2306 return Node::KLongDoubleLiteral;
2307}
2308}
2309
2310template <class Float> class FloatLiteralImpl : public Node {
2311 const StringView Contents;
2312
2313 static constexpr Kind KindForClass =
2314 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2315
2316public:
2317 FloatLiteralImpl(StringView Contents_)
2318 : Node(KindForClass), Contents(Contents_) {}
2319
2320 template<typename Fn> void match(Fn F) const { F(Contents); }
2321
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002322 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002323 const char *first = Contents.begin();
2324 const char *last = Contents.end() + 1;
2325
2326 const size_t N = FloatData<Float>::mangled_size;
2327 if (static_cast<std::size_t>(last - first) > N) {
2328 last = first + N;
2329 union {
2330 Float value;
2331 char buf[sizeof(Float)];
2332 };
2333 const char *t = first;
2334 char *e = buf;
2335 for (; t != last; ++t, ++e) {
2336 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2337 : static_cast<unsigned>(*t - 'a' + 10);
2338 ++t;
2339 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2340 : static_cast<unsigned>(*t - 'a' + 10);
2341 *e = static_cast<char>((d1 << 4) + d0);
2342 }
2343#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2344 std::reverse(buf, e);
2345#endif
2346 char num[FloatData<Float>::max_demangled_size] = {0};
2347 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002348 OB += StringView(num, num + n);
Richard Smithc20d1442018-08-20 20:14:49 +00002349 }
2350 }
2351};
2352
2353using FloatLiteral = FloatLiteralImpl<float>;
2354using DoubleLiteral = FloatLiteralImpl<double>;
2355using LongDoubleLiteral = FloatLiteralImpl<long double>;
2356
2357/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2358/// appropriate derived class.
2359template<typename Fn>
2360void Node::visit(Fn F) const {
2361 switch (K) {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002362#define NODE(X) \
2363 case K##X: \
2364 return F(static_cast<const X *>(this));
2365#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002366 }
2367 assert(0 && "unknown mangling node kind");
2368}
2369
2370/// Determine the kind of a node from its type.
2371template<typename NodeT> struct NodeKind;
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002372#define NODE(X) \
2373 template <> struct NodeKind<X> { \
2374 static constexpr Node::Kind Kind = Node::K##X; \
2375 static constexpr const char *name() { return #X; } \
Richard Smithc20d1442018-08-20 20:14:49 +00002376 };
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002377#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002378
Pavel Labathba825192018-10-16 14:29:14 +00002379template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002380 const char *First;
2381 const char *Last;
2382
2383 // Name stack, this is used by the parser to hold temporary names that were
2384 // parsed. The parser collapses multiple names into new nodes to construct
2385 // the AST. Once the parser is finished, names.size() == 1.
2386 PODSmallVector<Node *, 32> Names;
2387
2388 // Substitution table. Itanium supports name substitutions as a means of
2389 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2390 // table.
2391 PODSmallVector<Node *, 32> Subs;
2392
Richard Smithdf1c14c2019-09-06 23:53:21 +00002393 using TemplateParamList = PODSmallVector<Node *, 8>;
2394
2395 class ScopedTemplateParamList {
2396 AbstractManglingParser *Parser;
2397 size_t OldNumTemplateParamLists;
2398 TemplateParamList Params;
2399
2400 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002401 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2402 : Parser(TheParser),
2403 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002404 Parser->TemplateParams.push_back(&Params);
2405 }
2406 ~ScopedTemplateParamList() {
2407 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2408 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2409 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002410 };
2411
Richard Smithc20d1442018-08-20 20:14:49 +00002412 // Template parameter table. Like the above, but referenced like "T42_".
2413 // This has a smaller size compared to Subs and Names because it can be
2414 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002415 TemplateParamList OuterTemplateParams;
2416
2417 // Lists of template parameters indexed by template parameter depth,
2418 // referenced like "TL2_4_". If nonempty, element 0 is always
2419 // OuterTemplateParams; inner elements are always template parameter lists of
2420 // lambda expressions. For a generic lambda with no explicit template
2421 // parameter list, the corresponding parameter list pointer will be null.
2422 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002423
2424 // Set of unresolved forward <template-param> references. These can occur in a
2425 // conversion operator's type, and are resolved in the enclosing <encoding>.
2426 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2427
Richard Smithc20d1442018-08-20 20:14:49 +00002428 bool TryToParseTemplateArgs = true;
2429 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002430 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2431
2432 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002433
2434 Alloc ASTAllocator;
2435
Pavel Labathba825192018-10-16 14:29:14 +00002436 AbstractManglingParser(const char *First_, const char *Last_)
2437 : First(First_), Last(Last_) {}
2438
2439 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002440
2441 void reset(const char *First_, const char *Last_) {
2442 First = First_;
2443 Last = Last_;
2444 Names.clear();
2445 Subs.clear();
2446 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002447 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002448 TryToParseTemplateArgs = true;
2449 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002450 for (int I = 0; I != 3; ++I)
2451 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002452 ASTAllocator.reset();
2453 }
2454
Richard Smithb485b352018-08-24 23:30:26 +00002455 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002456 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2457 }
2458
2459 template <class It> NodeArray makeNodeArray(It begin, It end) {
2460 size_t sz = static_cast<size_t>(end - begin);
2461 void *mem = ASTAllocator.allocateNodeArray(sz);
2462 Node **data = new (mem) Node *[sz];
2463 std::copy(begin, end, data);
2464 return NodeArray(data, sz);
2465 }
2466
2467 NodeArray popTrailingNodeArray(size_t FromPosition) {
2468 assert(FromPosition <= Names.size());
2469 NodeArray res =
2470 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2471 Names.dropBack(FromPosition);
2472 return res;
2473 }
2474
2475 bool consumeIf(StringView S) {
2476 if (StringView(First, Last).startsWith(S)) {
2477 First += S.size();
2478 return true;
2479 }
2480 return false;
2481 }
2482
2483 bool consumeIf(char C) {
2484 if (First != Last && *First == C) {
2485 ++First;
2486 return true;
2487 }
2488 return false;
2489 }
2490
2491 char consume() { return First != Last ? *First++ : '\0'; }
2492
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08002493 char look(unsigned Lookahead = 0) const {
Richard Smithc20d1442018-08-20 20:14:49 +00002494 if (static_cast<size_t>(Last - First) <= Lookahead)
2495 return '\0';
2496 return First[Lookahead];
2497 }
2498
2499 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2500
2501 StringView parseNumber(bool AllowNegative = false);
2502 Qualifiers parseCVQualifiers();
2503 bool parsePositiveInteger(size_t *Out);
2504 StringView parseBareSourceName();
2505
2506 bool parseSeqId(size_t *Out);
2507 Node *parseSubstitution();
2508 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002509 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002510 Node *parseTemplateArgs(bool TagTemplates = false);
2511 Node *parseTemplateArg();
2512
2513 /// Parse the <expr> production.
2514 Node *parseExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002515 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2516 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00002517 Node *parseIntegerLiteral(StringView Lit);
2518 Node *parseExprPrimary();
2519 template <class Float> Node *parseFloatingLiteral();
2520 Node *parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00002521 Node *parseConversionExpr();
2522 Node *parseBracedExpr();
2523 Node *parseFoldExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002524 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07002525 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002526
2527 /// Parse the <type> production.
2528 Node *parseType();
2529 Node *parseFunctionType();
2530 Node *parseVectorType();
2531 Node *parseDecltype();
2532 Node *parseArrayType();
2533 Node *parsePointerToMemberType();
2534 Node *parseClassEnumType();
2535 Node *parseQualifiedType();
2536
2537 Node *parseEncoding();
2538 bool parseCallOffset();
2539 Node *parseSpecialName();
2540
2541 /// Holds some extra information about a <name> that is being parsed. This
2542 /// information is only pertinent if the <name> refers to an <encoding>.
2543 struct NameState {
2544 bool CtorDtorConversion = false;
2545 bool EndsWithTemplateArgs = false;
2546 Qualifiers CVQualifiers = QualNone;
2547 FunctionRefQual ReferenceQualifier = FrefQualNone;
2548 size_t ForwardTemplateRefsBegin;
2549
Pavel Labathba825192018-10-16 14:29:14 +00002550 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002551 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2552 };
2553
2554 bool resolveForwardTemplateRefs(NameState &State) {
2555 size_t I = State.ForwardTemplateRefsBegin;
2556 size_t E = ForwardTemplateRefs.size();
2557 for (; I < E; ++I) {
2558 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002559 if (TemplateParams.empty() || !TemplateParams[0] ||
2560 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002561 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002562 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002563 }
2564 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2565 return false;
2566 }
2567
2568 /// Parse the <name> production>
2569 Node *parseName(NameState *State = nullptr);
2570 Node *parseLocalName(NameState *State);
2571 Node *parseOperatorName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002572 bool parseModuleNameOpt(ModuleName *&Module);
2573 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
Richard Smithc20d1442018-08-20 20:14:49 +00002574 Node *parseUnnamedTypeName(NameState *State);
2575 Node *parseSourceName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002576 Node *parseUnscopedName(NameState *State, bool *isSubstName);
Richard Smithc20d1442018-08-20 20:14:49 +00002577 Node *parseNestedName(NameState *State);
2578 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2579
2580 Node *parseAbiTags(Node *N);
2581
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002582 struct OperatorInfo {
2583 enum OIKind : unsigned char {
2584 Prefix, // Prefix unary: @ expr
2585 Postfix, // Postfix unary: expr @
2586 Binary, // Binary: lhs @ rhs
2587 Array, // Array index: lhs [ rhs ]
2588 Member, // Member access: lhs @ rhs
2589 New, // New
2590 Del, // Delete
2591 Call, // Function call: expr (expr*)
2592 CCast, // C cast: (type)expr
2593 Conditional, // Conditional: expr ? expr : expr
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08002594 NameOnly, // Overload only, not allowed in expression.
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002595 // Below do not have operator names
2596 NamedCast, // Named cast, @<type>(expr)
2597 OfIdOp, // alignof, sizeof, typeid
2598
2599 Unnameable = NamedCast,
2600 };
2601 char Enc[2]; // Encoding
2602 OIKind Kind; // Kind of operator
2603 bool Flag : 1; // Entry-specific flag
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002604 Node::Prec Prec : 7; // Precedence
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002605 const char *Name; // Spelling
2606
2607 public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002608 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2609 const char *N)
2610 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002611
2612 public:
2613 bool operator<(const OperatorInfo &Other) const {
2614 return *this < Other.Enc;
2615 }
2616 bool operator<(const char *Peek) const {
2617 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2618 }
2619 bool operator==(const char *Peek) const {
2620 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2621 }
2622 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2623
2624 public:
2625 StringView getSymbol() const {
2626 StringView Res = Name;
2627 if (Kind < Unnameable) {
2628 assert(Res.startsWith("operator") &&
2629 "operator name does not start with 'operator'");
2630 Res = Res.dropFront(sizeof("operator") - 1);
2631 Res.consumeFront(' ');
2632 }
2633 return Res;
2634 }
2635 StringView getName() const { return Name; }
2636 OIKind getKind() const { return Kind; }
2637 bool getFlag() const { return Flag; }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002638 Node::Prec getPrecedence() const { return Prec; }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002639 };
2640 const OperatorInfo *parseOperatorEncoding();
2641
Richard Smithc20d1442018-08-20 20:14:49 +00002642 /// Parse the <unresolved-name> production.
Nathan Sidwell77c52e22022-01-28 11:59:03 -08002643 Node *parseUnresolvedName(bool Global);
Richard Smithc20d1442018-08-20 20:14:49 +00002644 Node *parseSimpleId();
2645 Node *parseBaseUnresolvedName();
2646 Node *parseUnresolvedType();
2647 Node *parseDestructorName();
2648
2649 /// Top-level entry point into the parser.
2650 Node *parse();
2651};
2652
2653const char* parse_discriminator(const char* first, const char* last);
2654
2655// <name> ::= <nested-name> // N
2656// ::= <local-name> # See Scope Encoding below // Z
2657// ::= <unscoped-template-name> <template-args>
2658// ::= <unscoped-name>
2659//
2660// <unscoped-template-name> ::= <unscoped-name>
2661// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002662template <typename Derived, typename Alloc>
2663Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002664 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002665 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002666 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002667 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002668
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002669 Node *Result = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002670 bool IsSubst = false;
2671
2672 Result = getDerived().parseUnscopedName(State, &IsSubst);
2673 if (!Result)
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002674 return nullptr;
2675
2676 if (look() == 'I') {
2677 // ::= <unscoped-template-name> <template-args>
2678 if (!IsSubst)
2679 // An unscoped-template-name is substitutable.
2680 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00002681 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002682 if (TA == nullptr)
2683 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002684 if (State)
2685 State->EndsWithTemplateArgs = true;
2686 Result = make<NameWithTemplateArgs>(Result, TA);
2687 } else if (IsSubst) {
2688 // The substitution case must be followed by <template-args>.
2689 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002690 }
2691
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002692 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00002693}
2694
2695// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2696// := Z <function encoding> E s [<discriminator>]
2697// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002698template <typename Derived, typename Alloc>
2699Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002700 if (!consumeIf('Z'))
2701 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002702 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002703 if (Encoding == nullptr || !consumeIf('E'))
2704 return nullptr;
2705
2706 if (consumeIf('s')) {
2707 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002708 auto *StringLitName = make<NameType>("string literal");
2709 if (!StringLitName)
2710 return nullptr;
2711 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002712 }
2713
2714 if (consumeIf('d')) {
2715 parseNumber(true);
2716 if (!consumeIf('_'))
2717 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002718 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002719 if (N == nullptr)
2720 return nullptr;
2721 return make<LocalName>(Encoding, N);
2722 }
2723
Pavel Labathba825192018-10-16 14:29:14 +00002724 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002725 if (Entity == nullptr)
2726 return nullptr;
2727 First = parse_discriminator(First, Last);
2728 return make<LocalName>(Encoding, Entity);
2729}
2730
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08002731// <unscoped-name> ::= [L]* <unqualified-name>
2732// ::= St [L]* <unqualified-name> # ::std::
2733// [*] extension
Pavel Labathba825192018-10-16 14:29:14 +00002734template <typename Derived, typename Alloc>
2735Node *
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002736AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2737 bool *IsSubst) {
2738
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002739 Node *Std = nullptr;
2740 if (consumeIf("St")) {
2741 Std = make<NameType>("std");
2742 if (Std == nullptr)
Nathan Sidwell200e97c2022-01-21 11:37:01 -08002743 return nullptr;
2744 }
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002745 consumeIf('L');
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
2763 if (Res == nullptr)
2764 Res = getDerived().parseUnqualifiedName(State, Std, Module);
2765
2766 return Res;
Richard Smithc20d1442018-08-20 20:14:49 +00002767}
2768
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002769// <unqualified-name> ::= [<module-name>] <operator-name> [<abi-tags>]
2770// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
2771// ::= [<module-name>] <source-name> [<abi-tags>]
2772// ::= [<module-name>] <unnamed-type-name> [<abi-tags>]
2773// # structured binding declaration
2774// ::= [<module-name>] DC <source-name>+ E
Pavel Labathba825192018-10-16 14:29:14 +00002775template <typename Derived, typename Alloc>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002776Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2777 NameState *State, Node *Scope, ModuleName *Module) {
2778 if (getDerived().parseModuleNameOpt(Module))
2779 return nullptr;
2780
Richard Smithc20d1442018-08-20 20:14:49 +00002781 Node *Result;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002782 if (look() == 'U') {
Pavel Labathba825192018-10-16 14:29:14 +00002783 Result = getDerived().parseUnnamedTypeName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002784 } else if (look() >= '1' && look() <= '9') {
Pavel Labathba825192018-10-16 14:29:14 +00002785 Result = getDerived().parseSourceName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002786 } else if (consumeIf("DC")) {
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002787 // Structured binding
Richard Smithc20d1442018-08-20 20:14:49 +00002788 size_t BindingsBegin = Names.size();
2789 do {
Pavel Labathba825192018-10-16 14:29:14 +00002790 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002791 if (Binding == nullptr)
2792 return nullptr;
2793 Names.push_back(Binding);
2794 } while (!consumeIf('E'));
2795 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002796 } else if (look() == 'C' || look() == 'D') {
2797 // A <ctor-dtor-name>.
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002798 if (Scope == nullptr || Module != nullptr)
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002799 return nullptr;
2800 Result = getDerived().parseCtorDtorName(Scope, State);
2801 } else {
Pavel Labathba825192018-10-16 14:29:14 +00002802 Result = getDerived().parseOperatorName(State);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002803 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002804
David Blaikie019fb1b2022-03-30 20:18:40 +00002805 if (Result != nullptr && Module != nullptr)
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002806 Result = make<ModuleEntity>(Module, Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002807 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002808 Result = getDerived().parseAbiTags(Result);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002809 if (Result != nullptr && Scope != nullptr)
2810 Result = make<NestedName>(Scope, Result);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002811
Richard Smithc20d1442018-08-20 20:14:49 +00002812 return Result;
2813}
2814
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002815// <module-name> ::= <module-subname>
2816// ::= <module-name> <module-subname>
2817// ::= <substitution> # passed in by caller
2818// <module-subname> ::= W <source-name>
2819// ::= W P <source-name>
2820template <typename Derived, typename Alloc>
2821bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2822 ModuleName *&Module) {
2823 while (consumeIf('W')) {
2824 bool IsPartition = consumeIf('P');
2825 Node *Sub = getDerived().parseSourceName(nullptr);
2826 if (!Sub)
2827 return true;
2828 Module =
2829 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2830 Subs.push_back(Module);
2831 }
2832
2833 return false;
2834}
2835
Richard Smithc20d1442018-08-20 20:14:49 +00002836// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2837// ::= <closure-type-name>
2838//
2839// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2840//
2841// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002842template <typename Derived, typename Alloc>
2843Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002844AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2845 // <template-params> refer to the innermost <template-args>. Clear out any
2846 // outer args that we may have inserted into TemplateParams.
2847 if (State != nullptr)
2848 TemplateParams.clear();
2849
Richard Smithc20d1442018-08-20 20:14:49 +00002850 if (consumeIf("Ut")) {
2851 StringView Count = parseNumber();
2852 if (!consumeIf('_'))
2853 return nullptr;
2854 return make<UnnamedTypeName>(Count);
2855 }
2856 if (consumeIf("Ul")) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002857 SwapAndRestore<size_t> SwapParams(ParsingLambdaParamsAtLevel,
2858 TemplateParams.size());
2859 ScopedTemplateParamList LambdaTemplateParams(this);
2860
2861 size_t ParamsBegin = Names.size();
2862 while (look() == 'T' &&
2863 StringView("yptn").find(look(1)) != StringView::npos) {
2864 Node *T = parseTemplateParamDecl();
2865 if (!T)
2866 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002867 Names.push_back(T);
2868 }
2869 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2870
2871 // FIXME: If TempParams is empty and none of the function parameters
2872 // includes 'auto', we should remove LambdaTemplateParams from the
2873 // TemplateParams list. Unfortunately, we don't find out whether there are
2874 // any 'auto' parameters until too late in an example such as:
2875 //
2876 // template<typename T> void f(
2877 // decltype([](decltype([]<typename T>(T v) {}),
2878 // auto) {})) {}
2879 // template<typename T> void f(
2880 // decltype([](decltype([]<typename T>(T w) {}),
2881 // int) {})) {}
2882 //
2883 // Here, the type of v is at level 2 but the type of w is at level 1. We
2884 // don't find this out until we encounter the type of the next parameter.
2885 //
2886 // However, compilers can't actually cope with the former example in
2887 // practice, and it's likely to be made ill-formed in future, so we don't
2888 // need to support it here.
2889 //
2890 // If we encounter an 'auto' in the function parameter types, we will
2891 // recreate a template parameter scope for it, but any intervening lambdas
2892 // will be parsed in the 'wrong' template parameter depth.
2893 if (TempParams.empty())
2894 TemplateParams.pop_back();
2895
Richard Smithc20d1442018-08-20 20:14:49 +00002896 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002897 do {
Pavel Labathba825192018-10-16 14:29:14 +00002898 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002899 if (P == nullptr)
2900 return nullptr;
2901 Names.push_back(P);
2902 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002903 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002904 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2905
Richard Smithc20d1442018-08-20 20:14:49 +00002906 StringView Count = parseNumber();
2907 if (!consumeIf('_'))
2908 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002909 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002910 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002911 if (consumeIf("Ub")) {
2912 (void)parseNumber();
2913 if (!consumeIf('_'))
2914 return nullptr;
2915 return make<NameType>("'block-literal'");
2916 }
Richard Smithc20d1442018-08-20 20:14:49 +00002917 return nullptr;
2918}
2919
2920// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002921template <typename Derived, typename Alloc>
2922Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002923 size_t Length = 0;
2924 if (parsePositiveInteger(&Length))
2925 return nullptr;
2926 if (numLeft() < Length || Length == 0)
2927 return nullptr;
2928 StringView Name(First, First + Length);
2929 First += Length;
2930 if (Name.startsWith("_GLOBAL__N"))
2931 return make<NameType>("(anonymous namespace)");
2932 return make<NameType>(Name);
2933}
2934
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002935// If the next 2 chars are an operator encoding, consume them and return their
2936// OperatorInfo. Otherwise return nullptr.
2937template <typename Derived, typename Alloc>
2938const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
2939AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
2940 static const OperatorInfo Ops[] = {
2941 // Keep ordered by encoding
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002942 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
2943 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
2944 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
2945 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
2946 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
2947 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary,
2948 "alignof "},
2949 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
2950 "operator co_await"},
2951 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
2952 "alignof "},
2953 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
2954 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
2955 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
2956 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
2957 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast,
2958 "operator"}, // C Cast
2959 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
2960 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
2961 "operator delete[]"},
2962 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
2963 "dynamic_cast"},
2964 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
2965 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
2966 "operator delete"},
2967 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2968 "operator.*"},
2969 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
2970 "operator."},
2971 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
2972 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
2973 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
2974 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
2975 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
2976 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
2977 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
2978 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
2979 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
2980 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
2981 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
2982 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
2983 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
2984 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
2985 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
2986 "operator*"},
2987 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
2988 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
2989 "operator new[]"},
2990 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
2991 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
2992 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
2993 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary,
2994 "operator new"},
2995 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
2996 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
2997 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
2998 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
2999 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
3000 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
3001 "operator->*"},
3002 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
3003 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
3004 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
3005 "operator->"},
3006 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
3007 "operator?"},
3008 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
3009 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
3010 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3011 "reinterpret_cast"},
3012 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3013 "operator%"},
3014 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3015 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
3016 "static_cast"},
3017 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3018 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3019 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary,
3020 "sizeof "},
3021 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3022 "typeid "},
3023 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix,
3024 "typeid "},
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003025 };
3026 const auto NumOps = sizeof(Ops) / sizeof(Ops[0]);
3027
3028#ifndef NDEBUG
3029 {
3030 // Verify table order.
3031 static bool Done;
3032 if (!Done) {
3033 Done = true;
3034 for (const auto *Op = &Ops[0]; Op != &Ops[NumOps - 1]; Op++)
3035 assert(Op[0] < Op[1] && "Operator table is not ordered");
3036 }
3037 }
3038#endif
3039
3040 if (numLeft() < 2)
3041 return nullptr;
3042
3043 auto Op = std::lower_bound(
3044 &Ops[0], &Ops[NumOps], First,
3045 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3046 if (Op == &Ops[NumOps] || *Op != First)
3047 return nullptr;
3048
3049 First += 2;
3050 return Op;
3051}
3052
3053// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003054// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003055// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003056template <typename Derived, typename Alloc>
3057Node *
3058AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003059 if (const auto *Op = parseOperatorEncoding()) {
3060 if (Op->getKind() == OperatorInfo::CCast) {
3061 // ::= cv <type> # (cast)
Richard Smithc20d1442018-08-20 20:14:49 +00003062 SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
3063 // If we're parsing an encoding, State != nullptr and the conversion
3064 // operators' <type> could have a <template-param> that refers to some
3065 // <template-arg>s further ahead in the mangled name.
3066 SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
3067 PermitForwardTemplateReferences ||
3068 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003069 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003070 if (Ty == nullptr)
3071 return nullptr;
3072 if (State) State->CtorDtorConversion = true;
3073 return make<ConversionOperatorType>(Ty);
3074 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003075
3076 if (Op->getKind() >= OperatorInfo::Unnameable)
3077 /* Not a nameable operator. */
3078 return nullptr;
3079 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3080 /* Not a nameable MemberExpr */
3081 return nullptr;
3082
3083 return make<NameType>(Op->getName());
3084 }
3085
3086 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003087 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003088 Node *SN = getDerived().parseSourceName(State);
3089 if (SN == nullptr)
3090 return nullptr;
3091 return make<LiteralOperator>(SN);
3092 }
3093
3094 if (consumeIf('v')) {
3095 // ::= v <digit> <source-name> # vendor extended operator
3096 if (look() >= '0' && look() <= '9') {
3097 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003098 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003099 if (SN == nullptr)
3100 return nullptr;
3101 return make<ConversionOperatorType>(SN);
3102 }
3103 return nullptr;
3104 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003105
Richard Smithc20d1442018-08-20 20:14:49 +00003106 return nullptr;
3107}
3108
3109// <ctor-dtor-name> ::= C1 # complete object constructor
3110// ::= C2 # base object constructor
3111// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003112// extension ::= C4 # gcc old-style "[unified]" constructor
3113// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003114// ::= D0 # deleting destructor
3115// ::= D1 # complete object destructor
3116// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003117// extension ::= D4 # gcc old-style "[unified]" destructor
3118// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003119template <typename Derived, typename Alloc>
3120Node *
3121AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3122 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003123 if (SoFar->getKind() == Node::KSpecialSubstitution) {
3124 auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;
3125 switch (SSK) {
3126 case SpecialSubKind::string:
3127 case SpecialSubKind::istream:
3128 case SpecialSubKind::ostream:
3129 case SpecialSubKind::iostream:
3130 SoFar = make<ExpandedSpecialSubstitution>(SSK);
Richard Smithb485b352018-08-24 23:30:26 +00003131 if (!SoFar)
3132 return nullptr;
Reid Klecknere76aabe2018-11-01 18:24:03 +00003133 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003134 default:
3135 break;
3136 }
3137 }
3138
3139 if (consumeIf('C')) {
3140 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003141 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3142 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003143 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003144 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003145 ++First;
3146 if (State) State->CtorDtorConversion = true;
3147 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003148 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003149 return nullptr;
3150 }
Nico Weber29294792019-04-03 23:14:33 +00003151 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003152 }
3153
Nico Weber29294792019-04-03 23:14:33 +00003154 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3155 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003156 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003157 First += 2;
3158 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003159 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003160 }
3161
3162 return nullptr;
3163}
3164
3165// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
3166// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
3167//
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003168// <prefix> ::= <prefix> [L]* <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003169// ::= <template-prefix> <template-args>
3170// ::= <template-param>
3171// ::= <decltype>
3172// ::= # empty
3173// ::= <substitution>
3174// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003175// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003176//
3177// <data-member-prefix> := <member source-name> [<template-args>] M
3178//
3179// <template-prefix> ::= <prefix> <template unqualified-name>
3180// ::= <template-param>
3181// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003182template <typename Derived, typename Alloc>
3183Node *
3184AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003185 if (!consumeIf('N'))
3186 return nullptr;
3187
3188 Qualifiers CVTmp = parseCVQualifiers();
3189 if (State) State->CVQualifiers = CVTmp;
3190
3191 if (consumeIf('O')) {
3192 if (State) State->ReferenceQualifier = FrefQualRValue;
3193 } else if (consumeIf('R')) {
3194 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003195 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003196 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003197 }
Richard Smithc20d1442018-08-20 20:14:49 +00003198
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003199 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003200 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003201 if (State)
3202 // Only set end-with-template on the case that does that.
3203 State->EndsWithTemplateArgs = false;
3204
Richard Smithc20d1442018-08-20 20:14:49 +00003205 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003206 // ::= <template-param>
3207 if (SoFar != nullptr)
3208 return nullptr; // Cannot have a prefix.
3209 SoFar = getDerived().parseTemplateParam();
3210 } else if (look() == 'I') {
3211 // ::= <template-prefix> <template-args>
3212 if (SoFar == nullptr)
3213 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003214 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003215 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003216 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003217 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3218 // Semantically <template-args> <template-args> cannot be generated by a
3219 // C++ entity. There will always be [something like] a name between
3220 // them.
3221 return nullptr;
3222 if (State)
3223 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003224 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003225 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3226 // ::= <decltype>
3227 if (SoFar != nullptr)
3228 return nullptr; // Cannot have a prefix.
3229 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003230 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003231 ModuleName *Module = nullptr;
3232 bool IsLocal = consumeIf('L'); // extension
3233
3234 if (look() == 'S') {
3235 // ::= <substitution>
3236 Node *S = nullptr;
3237 if (look(1) == 't') {
3238 First += 2;
3239 S = make<NameType>("std");
3240 } else {
3241 S = getDerived().parseSubstitution();
3242 }
3243 if (!S)
3244 return nullptr;
3245 if (S->getKind() == Node::KModuleName) {
3246 Module = static_cast<ModuleName *>(S);
3247 } else if (SoFar != nullptr || IsLocal) {
3248 return nullptr; // Cannot have a prefix.
3249 } else {
3250 SoFar = S;
3251 continue; // Do not push a new substitution.
3252 }
3253 }
3254
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003255 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003256 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003257 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003258
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003259 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003260 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003261 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003262
3263 // No longer used.
3264 // <data-member-prefix> := <member source-name> [<template-args>] M
3265 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003266 }
3267
3268 if (SoFar == nullptr || Subs.empty())
3269 return nullptr;
3270
3271 Subs.pop_back();
3272 return SoFar;
3273}
3274
3275// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003276template <typename Derived, typename Alloc>
3277Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3278 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003279 if (SN == nullptr)
3280 return nullptr;
3281 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003282 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003283 if (TA == nullptr)
3284 return nullptr;
3285 return make<NameWithTemplateArgs>(SN, TA);
3286 }
3287 return SN;
3288}
3289
3290// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3291// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003292template <typename Derived, typename Alloc>
3293Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003294 Node *Result;
3295 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003296 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003297 else
Pavel Labathba825192018-10-16 14:29:14 +00003298 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003299 if (Result == nullptr)
3300 return nullptr;
3301 return make<DtorName>(Result);
3302}
3303
3304// <unresolved-type> ::= <template-param>
3305// ::= <decltype>
3306// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003307template <typename Derived, typename Alloc>
3308Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003309 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003310 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003311 if (TP == nullptr)
3312 return nullptr;
3313 Subs.push_back(TP);
3314 return TP;
3315 }
3316 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003317 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003318 if (DT == nullptr)
3319 return nullptr;
3320 Subs.push_back(DT);
3321 return DT;
3322 }
Pavel Labathba825192018-10-16 14:29:14 +00003323 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003324}
3325
3326// <base-unresolved-name> ::= <simple-id> # unresolved name
3327// extension ::= <operator-name> # unresolved operator-function-id
3328// extension ::= <operator-name> <template-args> # unresolved operator template-id
3329// ::= on <operator-name> # unresolved operator-function-id
3330// ::= on <operator-name> <template-args> # unresolved operator template-id
3331// ::= dn <destructor-name> # destructor or pseudo-destructor;
3332// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003333template <typename Derived, typename Alloc>
3334Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003335 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003336 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003337
3338 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003339 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003340
3341 consumeIf("on");
3342
Pavel Labathba825192018-10-16 14:29:14 +00003343 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003344 if (Oper == nullptr)
3345 return nullptr;
3346 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003347 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003348 if (TA == nullptr)
3349 return nullptr;
3350 return make<NameWithTemplateArgs>(Oper, TA);
3351 }
3352 return Oper;
3353}
3354
3355// <unresolved-name>
3356// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3357// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3358// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3359// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003360// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003361// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3362// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3363// # T::N::x /decltype(p)::N::x
3364// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3365//
3366// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003367template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003368Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003369 Node *SoFar = nullptr;
3370
3371 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3372 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3373 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003374 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003375 if (SoFar == nullptr)
3376 return nullptr;
3377
3378 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003379 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003380 if (TA == nullptr)
3381 return nullptr;
3382 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003383 if (!SoFar)
3384 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003385 }
3386
3387 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003388 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003389 if (Qual == nullptr)
3390 return nullptr;
3391 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003392 if (!SoFar)
3393 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003394 }
3395
Pavel Labathba825192018-10-16 14:29:14 +00003396 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003397 if (Base == nullptr)
3398 return nullptr;
3399 return make<QualifiedName>(SoFar, Base);
3400 }
3401
Richard Smithc20d1442018-08-20 20:14:49 +00003402 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3403 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003404 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003405 if (SoFar == nullptr)
3406 return nullptr;
3407 if (Global)
3408 SoFar = make<GlobalQualifiedName>(SoFar);
3409 return SoFar;
3410 }
3411
3412 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3413 if (std::isdigit(look())) {
3414 do {
Pavel Labathba825192018-10-16 14:29:14 +00003415 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003416 if (Qual == nullptr)
3417 return nullptr;
3418 if (SoFar)
3419 SoFar = make<QualifiedName>(SoFar, Qual);
3420 else if (Global)
3421 SoFar = make<GlobalQualifiedName>(Qual);
3422 else
3423 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003424 if (!SoFar)
3425 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003426 } while (!consumeIf('E'));
3427 }
3428 // sr <unresolved-type> <base-unresolved-name>
3429 // sr <unresolved-type> <template-args> <base-unresolved-name>
3430 else {
Pavel Labathba825192018-10-16 14:29:14 +00003431 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003432 if (SoFar == nullptr)
3433 return nullptr;
3434
3435 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003436 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003437 if (TA == nullptr)
3438 return nullptr;
3439 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003440 if (!SoFar)
3441 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003442 }
3443 }
3444
3445 assert(SoFar != nullptr);
3446
Pavel Labathba825192018-10-16 14:29:14 +00003447 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003448 if (Base == nullptr)
3449 return nullptr;
3450 return make<QualifiedName>(SoFar, Base);
3451}
3452
3453// <abi-tags> ::= <abi-tag> [<abi-tags>]
3454// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003455template <typename Derived, typename Alloc>
3456Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003457 while (consumeIf('B')) {
3458 StringView SN = parseBareSourceName();
3459 if (SN.empty())
3460 return nullptr;
3461 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003462 if (!N)
3463 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003464 }
3465 return N;
3466}
3467
3468// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003469template <typename Alloc, typename Derived>
3470StringView
3471AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003472 const char *Tmp = First;
3473 if (AllowNegative)
3474 consumeIf('n');
3475 if (numLeft() == 0 || !std::isdigit(*First))
3476 return StringView();
3477 while (numLeft() != 0 && std::isdigit(*First))
3478 ++First;
3479 return StringView(Tmp, First);
3480}
3481
3482// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003483template <typename Alloc, typename Derived>
3484bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003485 *Out = 0;
3486 if (look() < '0' || look() > '9')
3487 return true;
3488 while (look() >= '0' && look() <= '9') {
3489 *Out *= 10;
3490 *Out += static_cast<size_t>(consume() - '0');
3491 }
3492 return false;
3493}
3494
Pavel Labathba825192018-10-16 14:29:14 +00003495template <typename Alloc, typename Derived>
3496StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003497 size_t Int = 0;
3498 if (parsePositiveInteger(&Int) || numLeft() < Int)
3499 return StringView();
3500 StringView R(First, First + Int);
3501 First += Int;
3502 return R;
3503}
3504
3505// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3506//
3507// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3508// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3509// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3510//
3511// <ref-qualifier> ::= R # & ref-qualifier
3512// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003513template <typename Derived, typename Alloc>
3514Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003515 Qualifiers CVQuals = parseCVQualifiers();
3516
3517 Node *ExceptionSpec = nullptr;
3518 if (consumeIf("Do")) {
3519 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003520 if (!ExceptionSpec)
3521 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003522 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003523 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003524 if (E == nullptr || !consumeIf('E'))
3525 return nullptr;
3526 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003527 if (!ExceptionSpec)
3528 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003529 } else if (consumeIf("Dw")) {
3530 size_t SpecsBegin = Names.size();
3531 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003532 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003533 if (T == nullptr)
3534 return nullptr;
3535 Names.push_back(T);
3536 }
3537 ExceptionSpec =
3538 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003539 if (!ExceptionSpec)
3540 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003541 }
3542
3543 consumeIf("Dx"); // transaction safe
3544
3545 if (!consumeIf('F'))
3546 return nullptr;
3547 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003548 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003549 if (ReturnType == nullptr)
3550 return nullptr;
3551
3552 FunctionRefQual ReferenceQualifier = FrefQualNone;
3553 size_t ParamsBegin = Names.size();
3554 while (true) {
3555 if (consumeIf('E'))
3556 break;
3557 if (consumeIf('v'))
3558 continue;
3559 if (consumeIf("RE")) {
3560 ReferenceQualifier = FrefQualLValue;
3561 break;
3562 }
3563 if (consumeIf("OE")) {
3564 ReferenceQualifier = FrefQualRValue;
3565 break;
3566 }
Pavel Labathba825192018-10-16 14:29:14 +00003567 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003568 if (T == nullptr)
3569 return nullptr;
3570 Names.push_back(T);
3571 }
3572
3573 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3574 return make<FunctionType>(ReturnType, Params, CVQuals,
3575 ReferenceQualifier, ExceptionSpec);
3576}
3577
3578// extension:
3579// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3580// ::= Dv [<dimension expression>] _ <element type>
3581// <extended element type> ::= <element type>
3582// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003583template <typename Derived, typename Alloc>
3584Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003585 if (!consumeIf("Dv"))
3586 return nullptr;
3587 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003588 Node *DimensionNumber = make<NameType>(parseNumber());
3589 if (!DimensionNumber)
3590 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003591 if (!consumeIf('_'))
3592 return nullptr;
3593 if (consumeIf('p'))
3594 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003595 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003596 if (ElemType == nullptr)
3597 return nullptr;
3598 return make<VectorType>(ElemType, DimensionNumber);
3599 }
3600
3601 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003602 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003603 if (!DimExpr)
3604 return nullptr;
3605 if (!consumeIf('_'))
3606 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003607 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003608 if (!ElemType)
3609 return nullptr;
3610 return make<VectorType>(ElemType, DimExpr);
3611 }
Pavel Labathba825192018-10-16 14:29:14 +00003612 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003613 if (!ElemType)
3614 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003615 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003616}
3617
3618// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3619// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003620template <typename Derived, typename Alloc>
3621Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003622 if (!consumeIf('D'))
3623 return nullptr;
3624 if (!consumeIf('t') && !consumeIf('T'))
3625 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003626 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003627 if (E == nullptr)
3628 return nullptr;
3629 if (!consumeIf('E'))
3630 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003631 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003632}
3633
3634// <array-type> ::= A <positive dimension number> _ <element type>
3635// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003636template <typename Derived, typename Alloc>
3637Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003638 if (!consumeIf('A'))
3639 return nullptr;
3640
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003641 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003642
Richard Smithc20d1442018-08-20 20:14:49 +00003643 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003644 Dimension = make<NameType>(parseNumber());
3645 if (!Dimension)
3646 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003647 if (!consumeIf('_'))
3648 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003649 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003650 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003651 if (DimExpr == nullptr)
3652 return nullptr;
3653 if (!consumeIf('_'))
3654 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003655 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003656 }
3657
Pavel Labathba825192018-10-16 14:29:14 +00003658 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003659 if (Ty == nullptr)
3660 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003661 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003662}
3663
3664// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003665template <typename Derived, typename Alloc>
3666Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003667 if (!consumeIf('M'))
3668 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003669 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003670 if (ClassType == nullptr)
3671 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003672 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003673 if (MemberType == nullptr)
3674 return nullptr;
3675 return make<PointerToMemberType>(ClassType, MemberType);
3676}
3677
3678// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3679// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3680// ::= Tu <name> # dependent elaborated type specifier using 'union'
3681// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003682template <typename Derived, typename Alloc>
3683Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003684 StringView ElabSpef;
3685 if (consumeIf("Ts"))
3686 ElabSpef = "struct";
3687 else if (consumeIf("Tu"))
3688 ElabSpef = "union";
3689 else if (consumeIf("Te"))
3690 ElabSpef = "enum";
3691
Pavel Labathba825192018-10-16 14:29:14 +00003692 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003693 if (Name == nullptr)
3694 return nullptr;
3695
3696 if (!ElabSpef.empty())
3697 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3698
3699 return Name;
3700}
3701
3702// <qualified-type> ::= <qualifiers> <type>
3703// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3704// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003705template <typename Derived, typename Alloc>
3706Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003707 if (consumeIf('U')) {
3708 StringView Qual = parseBareSourceName();
3709 if (Qual.empty())
3710 return nullptr;
3711
Richard Smithc20d1442018-08-20 20:14:49 +00003712 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3713 if (Qual.startsWith("objcproto")) {
3714 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3715 StringView Proto;
3716 {
3717 SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),
3718 SaveLast(Last, ProtoSourceName.end());
3719 Proto = parseBareSourceName();
3720 }
3721 if (Proto.empty())
3722 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003723 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003724 if (Child == nullptr)
3725 return nullptr;
3726 return make<ObjCProtoName>(Child, Proto);
3727 }
3728
Alex Orlovf50df922021-03-24 10:21:32 +04003729 Node *TA = nullptr;
3730 if (look() == 'I') {
3731 TA = getDerived().parseTemplateArgs();
3732 if (TA == nullptr)
3733 return nullptr;
3734 }
3735
Pavel Labathba825192018-10-16 14:29:14 +00003736 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003737 if (Child == nullptr)
3738 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003739 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003740 }
3741
3742 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003743 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003744 if (Ty == nullptr)
3745 return nullptr;
3746 if (Quals != QualNone)
3747 Ty = make<QualType>(Ty, Quals);
3748 return Ty;
3749}
3750
3751// <type> ::= <builtin-type>
3752// ::= <qualified-type>
3753// ::= <function-type>
3754// ::= <class-enum-type>
3755// ::= <array-type>
3756// ::= <pointer-to-member-type>
3757// ::= <template-param>
3758// ::= <template-template-param> <template-args>
3759// ::= <decltype>
3760// ::= P <type> # pointer
3761// ::= R <type> # l-value reference
3762// ::= O <type> # r-value reference (C++11)
3763// ::= C <type> # complex pair (C99)
3764// ::= G <type> # imaginary (C99)
3765// ::= <substitution> # See Compression below
3766// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3767// extension ::= <vector-type> # <vector-type> starts with Dv
3768//
3769// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3770// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003771template <typename Derived, typename Alloc>
3772Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003773 Node *Result = nullptr;
3774
Richard Smithc20d1442018-08-20 20:14:49 +00003775 switch (look()) {
3776 // ::= <qualified-type>
3777 case 'r':
3778 case 'V':
3779 case 'K': {
3780 unsigned AfterQuals = 0;
3781 if (look(AfterQuals) == 'r') ++AfterQuals;
3782 if (look(AfterQuals) == 'V') ++AfterQuals;
3783 if (look(AfterQuals) == 'K') ++AfterQuals;
3784
3785 if (look(AfterQuals) == 'F' ||
3786 (look(AfterQuals) == 'D' &&
3787 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3788 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003789 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003790 break;
3791 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003792 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003793 }
3794 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003795 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003796 break;
3797 }
3798 // <builtin-type> ::= v # void
3799 case 'v':
3800 ++First;
3801 return make<NameType>("void");
3802 // ::= w # wchar_t
3803 case 'w':
3804 ++First;
3805 return make<NameType>("wchar_t");
3806 // ::= b # bool
3807 case 'b':
3808 ++First;
3809 return make<NameType>("bool");
3810 // ::= c # char
3811 case 'c':
3812 ++First;
3813 return make<NameType>("char");
3814 // ::= a # signed char
3815 case 'a':
3816 ++First;
3817 return make<NameType>("signed char");
3818 // ::= h # unsigned char
3819 case 'h':
3820 ++First;
3821 return make<NameType>("unsigned char");
3822 // ::= s # short
3823 case 's':
3824 ++First;
3825 return make<NameType>("short");
3826 // ::= t # unsigned short
3827 case 't':
3828 ++First;
3829 return make<NameType>("unsigned short");
3830 // ::= i # int
3831 case 'i':
3832 ++First;
3833 return make<NameType>("int");
3834 // ::= j # unsigned int
3835 case 'j':
3836 ++First;
3837 return make<NameType>("unsigned int");
3838 // ::= l # long
3839 case 'l':
3840 ++First;
3841 return make<NameType>("long");
3842 // ::= m # unsigned long
3843 case 'm':
3844 ++First;
3845 return make<NameType>("unsigned long");
3846 // ::= x # long long, __int64
3847 case 'x':
3848 ++First;
3849 return make<NameType>("long long");
3850 // ::= y # unsigned long long, __int64
3851 case 'y':
3852 ++First;
3853 return make<NameType>("unsigned long long");
3854 // ::= n # __int128
3855 case 'n':
3856 ++First;
3857 return make<NameType>("__int128");
3858 // ::= o # unsigned __int128
3859 case 'o':
3860 ++First;
3861 return make<NameType>("unsigned __int128");
3862 // ::= f # float
3863 case 'f':
3864 ++First;
3865 return make<NameType>("float");
3866 // ::= d # double
3867 case 'd':
3868 ++First;
3869 return make<NameType>("double");
3870 // ::= e # long double, __float80
3871 case 'e':
3872 ++First;
3873 return make<NameType>("long double");
3874 // ::= g # __float128
3875 case 'g':
3876 ++First;
3877 return make<NameType>("__float128");
3878 // ::= z # ellipsis
3879 case 'z':
3880 ++First;
3881 return make<NameType>("...");
3882
3883 // <builtin-type> ::= u <source-name> # vendor extended type
3884 case 'u': {
3885 ++First;
3886 StringView Res = parseBareSourceName();
3887 if (Res.empty())
3888 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003889 // Typically, <builtin-type>s are not considered substitution candidates,
3890 // but the exception to that exception is vendor extended types (Itanium C++
3891 // ABI 5.9.1).
3892 Result = make<NameType>(Res);
3893 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003894 }
3895 case 'D':
3896 switch (look(1)) {
3897 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3898 case 'd':
3899 First += 2;
3900 return make<NameType>("decimal64");
3901 // ::= De # IEEE 754r decimal floating point (128 bits)
3902 case 'e':
3903 First += 2;
3904 return make<NameType>("decimal128");
3905 // ::= Df # IEEE 754r decimal floating point (32 bits)
3906 case 'f':
3907 First += 2;
3908 return make<NameType>("decimal32");
3909 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3910 case 'h':
3911 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003912 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003913 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3914 case 'F': {
3915 First += 2;
3916 Node *DimensionNumber = make<NameType>(parseNumber());
3917 if (!DimensionNumber)
3918 return nullptr;
3919 if (!consumeIf('_'))
3920 return nullptr;
3921 return make<BinaryFPType>(DimensionNumber);
3922 }
Richard Smithc20d1442018-08-20 20:14:49 +00003923 // ::= Di # char32_t
3924 case 'i':
3925 First += 2;
3926 return make<NameType>("char32_t");
3927 // ::= Ds # char16_t
3928 case 's':
3929 First += 2;
3930 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003931 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3932 case 'u':
3933 First += 2;
3934 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003935 // ::= Da # auto (in dependent new-expressions)
3936 case 'a':
3937 First += 2;
3938 return make<NameType>("auto");
3939 // ::= Dc # decltype(auto)
3940 case 'c':
3941 First += 2;
3942 return make<NameType>("decltype(auto)");
3943 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3944 case 'n':
3945 First += 2;
3946 return make<NameType>("std::nullptr_t");
3947
3948 // ::= <decltype>
3949 case 't':
3950 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003951 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003952 break;
3953 }
3954 // extension ::= <vector-type> # <vector-type> starts with Dv
3955 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003956 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003957 break;
3958 }
3959 // ::= Dp <type> # pack expansion (C++0x)
3960 case 'p': {
3961 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003962 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003963 if (!Child)
3964 return nullptr;
3965 Result = make<ParameterPackExpansion>(Child);
3966 break;
3967 }
3968 // Exception specifier on a function type.
3969 case 'o':
3970 case 'O':
3971 case 'w':
3972 // Transaction safe function type.
3973 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003974 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003975 break;
3976 }
3977 break;
3978 // ::= <function-type>
3979 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003980 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003981 break;
3982 }
3983 // ::= <array-type>
3984 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003985 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003986 break;
3987 }
3988 // ::= <pointer-to-member-type>
3989 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003990 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003991 break;
3992 }
3993 // ::= <template-param>
3994 case 'T': {
3995 // This could be an elaborate type specifier on a <class-enum-type>.
3996 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00003997 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003998 break;
3999 }
4000
Pavel Labathba825192018-10-16 14:29:14 +00004001 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00004002 if (Result == nullptr)
4003 return nullptr;
4004
4005 // Result could be either of:
4006 // <type> ::= <template-param>
4007 // <type> ::= <template-template-param> <template-args>
4008 //
4009 // <template-template-param> ::= <template-param>
4010 // ::= <substitution>
4011 //
4012 // If this is followed by some <template-args>, and we're permitted to
4013 // parse them, take the second production.
4014
4015 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004016 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004017 if (TA == nullptr)
4018 return nullptr;
4019 Result = make<NameWithTemplateArgs>(Result, TA);
4020 }
4021 break;
4022 }
4023 // ::= P <type> # pointer
4024 case 'P': {
4025 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004026 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004027 if (Ptr == nullptr)
4028 return nullptr;
4029 Result = make<PointerType>(Ptr);
4030 break;
4031 }
4032 // ::= R <type> # l-value reference
4033 case 'R': {
4034 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004035 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004036 if (Ref == nullptr)
4037 return nullptr;
4038 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4039 break;
4040 }
4041 // ::= O <type> # r-value reference (C++11)
4042 case 'O': {
4043 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004044 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004045 if (Ref == nullptr)
4046 return nullptr;
4047 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4048 break;
4049 }
4050 // ::= C <type> # complex pair (C99)
4051 case 'C': {
4052 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004053 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004054 if (P == nullptr)
4055 return nullptr;
4056 Result = make<PostfixQualifiedType>(P, " complex");
4057 break;
4058 }
4059 // ::= G <type> # imaginary (C99)
4060 case 'G': {
4061 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004062 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004063 if (P == nullptr)
4064 return P;
4065 Result = make<PostfixQualifiedType>(P, " imaginary");
4066 break;
4067 }
4068 // ::= <substitution> # See Compression below
4069 case 'S': {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004070 if (look(1) != 't') {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004071 bool IsSubst = false;
4072 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4073 if (!Result)
Richard Smithc20d1442018-08-20 20:14:49 +00004074 return nullptr;
4075
4076 // Sub could be either of:
4077 // <type> ::= <substitution>
4078 // <type> ::= <template-template-param> <template-args>
4079 //
4080 // <template-template-param> ::= <template-param>
4081 // ::= <substitution>
4082 //
4083 // If this is followed by some <template-args>, and we're permitted to
4084 // parse them, take the second production.
4085
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004086 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4087 if (!IsSubst)
4088 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00004089 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004090 if (TA == nullptr)
4091 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004092 Result = make<NameWithTemplateArgs>(Result, TA);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004093 } else if (IsSubst) {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004094 // If all we parsed was a substitution, don't re-insert into the
4095 // substitution table.
4096 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00004097 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004098 break;
Richard Smithc20d1442018-08-20 20:14:49 +00004099 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004100 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004101 }
4102 // ::= <class-enum-type>
4103 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004104 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004105 break;
4106 }
4107 }
4108
4109 // If we parsed a type, insert it into the substitution table. Note that all
4110 // <builtin-type>s and <substitution>s have already bailed out, because they
4111 // don't get substitutions.
4112 if (Result != nullptr)
4113 Subs.push_back(Result);
4114 return Result;
4115}
4116
Pavel Labathba825192018-10-16 14:29:14 +00004117template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004118Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4119 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004120 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004121 if (E == nullptr)
4122 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004123 return make<PrefixExpr>(Kind, E, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004124}
4125
Pavel Labathba825192018-10-16 14:29:14 +00004126template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004127Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4128 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004129 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004130 if (LHS == nullptr)
4131 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004132 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004133 if (RHS == nullptr)
4134 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004135 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004136}
4137
Pavel Labathba825192018-10-16 14:29:14 +00004138template <typename Derived, typename Alloc>
4139Node *
4140AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004141 StringView Tmp = parseNumber(true);
4142 if (!Tmp.empty() && consumeIf('E'))
4143 return make<IntegerLiteral>(Lit, Tmp);
4144 return nullptr;
4145}
4146
4147// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004148template <typename Alloc, typename Derived>
4149Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004150 Qualifiers CVR = QualNone;
4151 if (consumeIf('r'))
4152 CVR |= QualRestrict;
4153 if (consumeIf('V'))
4154 CVR |= QualVolatile;
4155 if (consumeIf('K'))
4156 CVR |= QualConst;
4157 return CVR;
4158}
4159
4160// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4161// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4162// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4163// ::= 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 -04004164// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004165template <typename Derived, typename Alloc>
4166Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004167 if (consumeIf("fpT"))
4168 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004169 if (consumeIf("fp")) {
4170 parseCVQualifiers();
4171 StringView Num = parseNumber();
4172 if (!consumeIf('_'))
4173 return nullptr;
4174 return make<FunctionParam>(Num);
4175 }
4176 if (consumeIf("fL")) {
4177 if (parseNumber().empty())
4178 return nullptr;
4179 if (!consumeIf('p'))
4180 return nullptr;
4181 parseCVQualifiers();
4182 StringView Num = parseNumber();
4183 if (!consumeIf('_'))
4184 return nullptr;
4185 return make<FunctionParam>(Num);
4186 }
4187 return nullptr;
4188}
4189
Richard Smithc20d1442018-08-20 20:14:49 +00004190// cv <type> <expression> # conversion with one argument
4191// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004192template <typename Derived, typename Alloc>
4193Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004194 if (!consumeIf("cv"))
4195 return nullptr;
4196 Node *Ty;
4197 {
4198 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004199 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004200 }
4201
4202 if (Ty == nullptr)
4203 return nullptr;
4204
4205 if (consumeIf('_')) {
4206 size_t ExprsBegin = Names.size();
4207 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004208 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004209 if (E == nullptr)
4210 return E;
4211 Names.push_back(E);
4212 }
4213 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4214 return make<ConversionExpr>(Ty, Exprs);
4215 }
4216
Pavel Labathba825192018-10-16 14:29:14 +00004217 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004218 if (E[0] == nullptr)
4219 return nullptr;
4220 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4221}
4222
4223// <expr-primary> ::= L <type> <value number> E # integer literal
4224// ::= L <type> <value float> E # floating literal
4225// ::= L <string type> E # string literal
4226// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004227// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004228// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4229// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004230template <typename Derived, typename Alloc>
4231Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004232 if (!consumeIf('L'))
4233 return nullptr;
4234 switch (look()) {
4235 case 'w':
4236 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004237 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004238 case 'b':
4239 if (consumeIf("b0E"))
4240 return make<BoolExpr>(0);
4241 if (consumeIf("b1E"))
4242 return make<BoolExpr>(1);
4243 return nullptr;
4244 case 'c':
4245 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004246 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004247 case 'a':
4248 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004249 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004250 case 'h':
4251 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004252 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004253 case 's':
4254 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004255 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004256 case 't':
4257 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004258 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004259 case 'i':
4260 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004261 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004262 case 'j':
4263 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004264 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004265 case 'l':
4266 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004267 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004268 case 'm':
4269 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004270 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004271 case 'x':
4272 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004273 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004274 case 'y':
4275 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004276 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004277 case 'n':
4278 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004279 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004280 case 'o':
4281 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004282 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004283 case 'f':
4284 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004285 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004286 case 'd':
4287 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004288 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004289 case 'e':
4290 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004291#if defined(__powerpc__) || defined(__s390__)
4292 // Handle cases where long doubles encoded with e have the same size
4293 // and representation as doubles.
4294 return getDerived().template parseFloatingLiteral<double>();
4295#else
Pavel Labathba825192018-10-16 14:29:14 +00004296 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004297#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004298 case '_':
4299 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004300 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004301 if (R != nullptr && consumeIf('E'))
4302 return R;
4303 }
4304 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004305 case 'A': {
4306 Node *T = getDerived().parseType();
4307 if (T == nullptr)
4308 return nullptr;
4309 // FIXME: We need to include the string contents in the mangling.
4310 if (consumeIf('E'))
4311 return make<StringLiteral>(T);
4312 return nullptr;
4313 }
4314 case 'D':
4315 if (consumeIf("DnE"))
4316 return make<NameType>("nullptr");
4317 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004318 case 'T':
4319 // Invalid mangled name per
4320 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4321 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004322 case 'U': {
4323 // FIXME: Should we support LUb... for block literals?
4324 if (look(1) != 'l')
4325 return nullptr;
4326 Node *T = parseUnnamedTypeName(nullptr);
4327 if (!T || !consumeIf('E'))
4328 return nullptr;
4329 return make<LambdaExpr>(T);
4330 }
Richard Smithc20d1442018-08-20 20:14:49 +00004331 default: {
4332 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004333 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004334 if (T == nullptr)
4335 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004336 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004337 if (N.empty())
4338 return nullptr;
4339 if (!consumeIf('E'))
4340 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004341 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004342 }
4343 }
4344}
4345
4346// <braced-expression> ::= <expression>
4347// ::= di <field source-name> <braced-expression> # .name = expr
4348// ::= dx <index expression> <braced-expression> # [expr] = expr
4349// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004350template <typename Derived, typename Alloc>
4351Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004352 if (look() == 'd') {
4353 switch (look(1)) {
4354 case 'i': {
4355 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004356 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004357 if (Field == nullptr)
4358 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004359 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004360 if (Init == nullptr)
4361 return nullptr;
4362 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4363 }
4364 case 'x': {
4365 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004366 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004367 if (Index == nullptr)
4368 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004369 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004370 if (Init == nullptr)
4371 return nullptr;
4372 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4373 }
4374 case 'X': {
4375 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004376 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004377 if (RangeBegin == nullptr)
4378 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004379 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004380 if (RangeEnd == nullptr)
4381 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004382 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004383 if (Init == nullptr)
4384 return nullptr;
4385 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4386 }
4387 }
4388 }
Pavel Labathba825192018-10-16 14:29:14 +00004389 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004390}
4391
4392// (not yet in the spec)
4393// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4394// ::= fR <binary-operator-name> <expression> <expression>
4395// ::= fl <binary-operator-name> <expression>
4396// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004397template <typename Derived, typename Alloc>
4398Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004399 if (!consumeIf('f'))
4400 return nullptr;
4401
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004402 bool IsLeftFold = false, HasInitializer = false;
4403 switch (look()) {
4404 default:
Richard Smithc20d1442018-08-20 20:14:49 +00004405 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004406 case 'L':
4407 IsLeftFold = true;
4408 HasInitializer = true;
4409 break;
4410 case 'R':
4411 HasInitializer = true;
4412 break;
4413 case 'l':
4414 IsLeftFold = true;
4415 break;
4416 case 'r':
4417 break;
4418 }
Richard Smithc20d1442018-08-20 20:14:49 +00004419 ++First;
4420
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004421 const auto *Op = parseOperatorEncoding();
4422 if (!Op || Op->getKind() != OperatorInfo::Binary)
4423 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004424
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004425 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004426 if (Pack == nullptr)
4427 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004428
4429 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004430 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004431 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004432 if (Init == nullptr)
4433 return nullptr;
4434 }
4435
4436 if (IsLeftFold && Init)
4437 std::swap(Pack, Init);
4438
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004439 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004440}
4441
Richard Smith1865d2f2020-10-22 19:29:36 -07004442// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4443//
4444// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4445template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004446Node *
4447AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4448 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004449 Node *Ty = getDerived().parseType();
4450 if (!Ty)
4451 return nullptr;
4452 Node *Expr = getDerived().parseExpr();
4453 if (!Expr)
4454 return nullptr;
4455 StringView Offset = getDerived().parseNumber(true);
4456 if (!consumeIf('E'))
4457 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004458 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004459}
4460
4461// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4462// <union-selector> ::= _ [<number>]
4463//
4464// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4465template <typename Derived, typename Alloc>
4466Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4467 Node *Ty = getDerived().parseType();
4468 if (!Ty)
4469 return nullptr;
4470 Node *Expr = getDerived().parseExpr();
4471 if (!Expr)
4472 return nullptr;
4473 StringView Offset = getDerived().parseNumber(true);
4474 size_t SelectorsBegin = Names.size();
4475 while (consumeIf('_')) {
4476 Node *Selector = make<NameType>(parseNumber());
4477 if (!Selector)
4478 return nullptr;
4479 Names.push_back(Selector);
4480 }
4481 bool OnePastTheEnd = consumeIf('p');
4482 if (!consumeIf('E'))
4483 return nullptr;
4484 return make<SubobjectExpr>(
4485 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4486}
4487
Richard Smithc20d1442018-08-20 20:14:49 +00004488// <expression> ::= <unary operator-name> <expression>
4489// ::= <binary operator-name> <expression> <expression>
4490// ::= <ternary operator-name> <expression> <expression> <expression>
4491// ::= cl <expression>+ E # call
4492// ::= cv <type> <expression> # conversion with one argument
4493// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4494// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4495// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4496// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4497// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4498// ::= [gs] dl <expression> # delete expression
4499// ::= [gs] da <expression> # delete[] expression
4500// ::= pp_ <expression> # prefix ++
4501// ::= mm_ <expression> # prefix --
4502// ::= ti <type> # typeid (type)
4503// ::= te <expression> # typeid (expression)
4504// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4505// ::= sc <type> <expression> # static_cast<type> (expression)
4506// ::= cc <type> <expression> # const_cast<type> (expression)
4507// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4508// ::= st <type> # sizeof (a type)
4509// ::= sz <expression> # sizeof (an expression)
4510// ::= at <type> # alignof (a type)
4511// ::= az <expression> # alignof (an expression)
4512// ::= nx <expression> # noexcept (expression)
4513// ::= <template-param>
4514// ::= <function-param>
4515// ::= dt <expression> <unresolved-name> # expr.name
4516// ::= pt <expression> <unresolved-name> # expr->name
4517// ::= ds <expression> <expression> # expr.*expr
4518// ::= sZ <template-param> # size of a parameter pack
4519// ::= sZ <function-param> # size of a function parameter pack
4520// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4521// ::= sp <expression> # pack expansion
4522// ::= tw <expression> # throw expression
4523// ::= tr # throw with no operand (rethrow)
4524// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4525// # freestanding dependent name (e.g., T::x),
4526// # objectless nonstatic member reference
4527// ::= fL <binary-operator-name> <expression> <expression>
4528// ::= fR <binary-operator-name> <expression> <expression>
4529// ::= fl <binary-operator-name> <expression>
4530// ::= fr <binary-operator-name> <expression>
4531// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004532template <typename Derived, typename Alloc>
4533Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004534 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004535
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004536 const auto *Op = parseOperatorEncoding();
4537 if (Op) {
4538 auto Sym = Op->getSymbol();
4539 switch (Op->getKind()) {
4540 case OperatorInfo::Binary:
4541 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004542 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004543 case OperatorInfo::Prefix:
4544 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004545 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004546 case OperatorInfo::Postfix: {
4547 // Postfix unary operator: expr @
4548 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004549 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004550 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004551 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004552 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004553 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004554 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004555 case OperatorInfo::Array: {
4556 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004557 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004558 if (Base == nullptr)
4559 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004560 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004561 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004562 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004563 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004564 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004565 case OperatorInfo::Member: {
4566 // Member access lhs @ rhs
4567 Node *LHS = getDerived().parseExpr();
4568 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004569 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004570 Node *RHS = getDerived().parseExpr();
4571 if (RHS == nullptr)
4572 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004573 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004574 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004575 case OperatorInfo::New: {
4576 // New
4577 // # new (expr-list) type [(init)]
4578 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4579 // # new[] (expr-list) type [(init)]
4580 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004581 size_t Exprs = Names.size();
4582 while (!consumeIf('_')) {
4583 Node *Ex = getDerived().parseExpr();
4584 if (Ex == nullptr)
4585 return nullptr;
4586 Names.push_back(Ex);
4587 }
4588 NodeArray ExprList = popTrailingNodeArray(Exprs);
4589 Node *Ty = getDerived().parseType();
4590 if (Ty == nullptr)
4591 return nullptr;
4592 bool HaveInits = consumeIf("pi");
4593 size_t InitsBegin = Names.size();
4594 while (!consumeIf('E')) {
4595 if (!HaveInits)
4596 return nullptr;
4597 Node *Init = getDerived().parseExpr();
4598 if (Init == nullptr)
4599 return Init;
4600 Names.push_back(Init);
4601 }
4602 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004603 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004604 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004605 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004606 case OperatorInfo::Del: {
4607 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004608 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004609 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004610 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004611 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4612 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004613 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004614 case OperatorInfo::Call: {
4615 // Function Call
4616 Node *Callee = getDerived().parseExpr();
4617 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004618 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004619 size_t ExprsBegin = Names.size();
4620 while (!consumeIf('E')) {
4621 Node *E = getDerived().parseExpr();
4622 if (E == nullptr)
4623 return nullptr;
4624 Names.push_back(E);
4625 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004626 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4627 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004628 }
4629 case OperatorInfo::CCast: {
4630 // C Cast: (type)expr
4631 Node *Ty;
4632 {
4633 SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);
4634 Ty = getDerived().parseType();
4635 }
4636 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004637 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004638
4639 size_t ExprsBegin = Names.size();
4640 bool IsMany = consumeIf('_');
4641 while (!consumeIf('E')) {
4642 Node *E = getDerived().parseExpr();
4643 if (E == nullptr)
4644 return E;
4645 Names.push_back(E);
4646 if (!IsMany)
4647 break;
4648 }
4649 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4650 if (!IsMany && Exprs.size() != 1)
4651 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004652 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004653 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004654 case OperatorInfo::Conditional: {
4655 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004656 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004657 if (Cond == nullptr)
4658 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004659 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004660 if (LHS == nullptr)
4661 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004662 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004663 if (RHS == nullptr)
4664 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004665 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004666 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004667 case OperatorInfo::NamedCast: {
4668 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004669 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004670 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004671 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004672 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004673 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004674 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004675 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004676 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004677 case OperatorInfo::OfIdOp: {
4678 // [sizeof/alignof/typeid] ( <type>|<expr> )
4679 Node *Arg =
4680 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4681 if (!Arg)
4682 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004683 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004684 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004685 case OperatorInfo::NameOnly: {
4686 // Not valid as an expression operand.
4687 return nullptr;
4688 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004689 }
4690 DEMANGLE_UNREACHABLE;
4691 }
4692
4693 if (numLeft() < 2)
4694 return nullptr;
4695
4696 if (look() == 'L')
4697 return getDerived().parseExprPrimary();
4698 if (look() == 'T')
4699 return getDerived().parseTemplateParam();
4700 if (look() == 'f') {
4701 // Disambiguate a fold expression from a <function-param>.
4702 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4703 return getDerived().parseFunctionParam();
4704 return getDerived().parseFoldExpr();
4705 }
4706 if (consumeIf("il")) {
4707 size_t InitsBegin = Names.size();
4708 while (!consumeIf('E')) {
4709 Node *E = getDerived().parseBracedExpr();
4710 if (E == nullptr)
4711 return nullptr;
4712 Names.push_back(E);
4713 }
4714 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4715 }
4716 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004717 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004718 if (consumeIf("nx")) {
4719 Node *Ex = getDerived().parseExpr();
4720 if (Ex == nullptr)
4721 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004722 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004723 }
4724 if (consumeIf("so"))
4725 return parseSubobjectExpr();
4726 if (consumeIf("sp")) {
4727 Node *Child = getDerived().parseExpr();
4728 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004729 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004730 return make<ParameterPackExpansion>(Child);
4731 }
4732 if (consumeIf("sZ")) {
4733 if (look() == 'T') {
4734 Node *R = getDerived().parseTemplateParam();
4735 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004736 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004737 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004738 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004739 Node *FP = getDerived().parseFunctionParam();
4740 if (FP == nullptr)
4741 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004742 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004743 }
4744 if (consumeIf("sP")) {
4745 size_t ArgsBegin = Names.size();
4746 while (!consumeIf('E')) {
4747 Node *Arg = getDerived().parseTemplateArg();
4748 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004749 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004750 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004751 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004752 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4753 if (!Pack)
4754 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004755 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004756 }
4757 if (consumeIf("tl")) {
4758 Node *Ty = getDerived().parseType();
4759 if (Ty == nullptr)
4760 return nullptr;
4761 size_t InitsBegin = Names.size();
4762 while (!consumeIf('E')) {
4763 Node *E = getDerived().parseBracedExpr();
4764 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004765 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004766 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004767 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004768 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4769 }
4770 if (consumeIf("tr"))
4771 return make<NameType>("throw");
4772 if (consumeIf("tw")) {
4773 Node *Ex = getDerived().parseExpr();
4774 if (Ex == nullptr)
4775 return nullptr;
4776 return make<ThrowExpr>(Ex);
4777 }
4778 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004779 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4780 if (!Name)
4781 return nullptr;
4782 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4783 // standard encoding expects a <template-arg>, and would be otherwise be
4784 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4785 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4786 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004787 bool IsUUID = false;
4788 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004789 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004790 if (consumeIf('t')) {
4791 UUID = getDerived().parseType();
4792 IsUUID = true;
4793 } else if (consumeIf('z')) {
4794 UUID = getDerived().parseExpr();
4795 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004796 }
4797 }
4798 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004799 if (IsUUID) {
4800 if (UUID == nullptr)
4801 return nullptr;
4802 Names.push_back(UUID);
4803 } else {
4804 while (!consumeIf('E')) {
4805 Node *E = getDerived().parseTemplateArg();
4806 if (E == nullptr)
4807 return E;
4808 Names.push_back(E);
4809 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004810 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004811 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4812 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004813 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004814
4815 // Only unresolved names remain.
4816 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004817}
4818
4819// <call-offset> ::= h <nv-offset> _
4820// ::= v <v-offset> _
4821//
4822// <nv-offset> ::= <offset number>
4823// # non-virtual base override
4824//
4825// <v-offset> ::= <offset number> _ <virtual offset number>
4826// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004827template <typename Alloc, typename Derived>
4828bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004829 // Just scan through the call offset, we never add this information into the
4830 // output.
4831 if (consumeIf('h'))
4832 return parseNumber(true).empty() || !consumeIf('_');
4833 if (consumeIf('v'))
4834 return parseNumber(true).empty() || !consumeIf('_') ||
4835 parseNumber(true).empty() || !consumeIf('_');
4836 return true;
4837}
4838
4839// <special-name> ::= TV <type> # virtual table
4840// ::= TT <type> # VTT structure (construction vtable index)
4841// ::= TI <type> # typeinfo structure
4842// ::= TS <type> # typeinfo name (null-terminated byte string)
4843// ::= Tc <call-offset> <call-offset> <base encoding>
4844// # base is the nominal target function of thunk
4845// # first call-offset is 'this' adjustment
4846// # second call-offset is result adjustment
4847// ::= T <call-offset> <base encoding>
4848// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004849// # Guard variable for one-time initialization
4850// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004851// # No <type>
4852// ::= TW <object name> # Thread-local wrapper
4853// ::= TH <object name> # Thread-local initialization
4854// ::= GR <object name> _ # First temporary
4855// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004856// # construction vtable for second-in-first
4857// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004858// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004859// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004860template <typename Derived, typename Alloc>
4861Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004862 switch (look()) {
4863 case 'T':
4864 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004865 // TA <template-arg> # template parameter object
4866 //
4867 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4868 case 'A': {
4869 First += 2;
4870 Node *Arg = getDerived().parseTemplateArg();
4871 if (Arg == nullptr)
4872 return nullptr;
4873 return make<SpecialName>("template parameter object for ", Arg);
4874 }
Richard Smithc20d1442018-08-20 20:14:49 +00004875 // TV <type> # virtual table
4876 case 'V': {
4877 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004878 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004879 if (Ty == nullptr)
4880 return nullptr;
4881 return make<SpecialName>("vtable for ", Ty);
4882 }
4883 // TT <type> # VTT structure (construction vtable index)
4884 case 'T': {
4885 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004886 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004887 if (Ty == nullptr)
4888 return nullptr;
4889 return make<SpecialName>("VTT for ", Ty);
4890 }
4891 // TI <type> # typeinfo structure
4892 case 'I': {
4893 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004894 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004895 if (Ty == nullptr)
4896 return nullptr;
4897 return make<SpecialName>("typeinfo for ", Ty);
4898 }
4899 // TS <type> # typeinfo name (null-terminated byte string)
4900 case 'S': {
4901 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004902 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004903 if (Ty == nullptr)
4904 return nullptr;
4905 return make<SpecialName>("typeinfo name for ", Ty);
4906 }
4907 // Tc <call-offset> <call-offset> <base encoding>
4908 case 'c': {
4909 First += 2;
4910 if (parseCallOffset() || parseCallOffset())
4911 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004912 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004913 if (Encoding == nullptr)
4914 return nullptr;
4915 return make<SpecialName>("covariant return thunk to ", Encoding);
4916 }
4917 // extension ::= TC <first type> <number> _ <second type>
4918 // # construction vtable for second-in-first
4919 case 'C': {
4920 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004921 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004922 if (FirstType == nullptr)
4923 return nullptr;
4924 if (parseNumber(true).empty() || !consumeIf('_'))
4925 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004926 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004927 if (SecondType == nullptr)
4928 return nullptr;
4929 return make<CtorVtableSpecialName>(SecondType, FirstType);
4930 }
4931 // TW <object name> # Thread-local wrapper
4932 case 'W': {
4933 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004934 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004935 if (Name == nullptr)
4936 return nullptr;
4937 return make<SpecialName>("thread-local wrapper routine for ", Name);
4938 }
4939 // TH <object name> # Thread-local initialization
4940 case 'H': {
4941 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004942 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004943 if (Name == nullptr)
4944 return nullptr;
4945 return make<SpecialName>("thread-local initialization routine for ", Name);
4946 }
4947 // T <call-offset> <base encoding>
4948 default: {
4949 ++First;
4950 bool IsVirt = look() == 'v';
4951 if (parseCallOffset())
4952 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004953 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004954 if (BaseEncoding == nullptr)
4955 return nullptr;
4956 if (IsVirt)
4957 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4958 else
4959 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4960 }
4961 }
4962 case 'G':
4963 switch (look(1)) {
4964 // GV <object name> # Guard variable for one-time initialization
4965 case 'V': {
4966 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004967 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004968 if (Name == nullptr)
4969 return nullptr;
4970 return make<SpecialName>("guard variable for ", Name);
4971 }
4972 // GR <object name> # reference temporary for object
4973 // GR <object name> _ # First temporary
4974 // GR <object name> <seq-id> _ # Subsequent temporaries
4975 case 'R': {
4976 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004977 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004978 if (Name == nullptr)
4979 return nullptr;
4980 size_t Count;
4981 bool ParsedSeqId = !parseSeqId(&Count);
4982 if (!consumeIf('_') && ParsedSeqId)
4983 return nullptr;
4984 return make<SpecialName>("reference temporary for ", Name);
4985 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004986 // GI <module-name> v
4987 case 'I': {
4988 First += 2;
4989 ModuleName *Module = nullptr;
4990 if (getDerived().parseModuleNameOpt(Module))
4991 return nullptr;
4992 if (Module == nullptr)
4993 return nullptr;
4994 return make<SpecialName>("initializer for module ", Module);
4995 }
Richard Smithc20d1442018-08-20 20:14:49 +00004996 }
4997 }
4998 return nullptr;
4999}
5000
5001// <encoding> ::= <function name> <bare-function-type>
5002// ::= <data name>
5003// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00005004template <typename Derived, typename Alloc>
5005Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07005006 // The template parameters of an encoding are unrelated to those of the
5007 // enclosing context.
5008 class SaveTemplateParams {
5009 AbstractManglingParser *Parser;
5010 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005011 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005012
5013 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005014 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005015 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005016 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005017 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005018 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005019 }
5020 ~SaveTemplateParams() {
5021 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005022 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005023 }
5024 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005025
Richard Smithc20d1442018-08-20 20:14:49 +00005026 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005027 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005028
5029 auto IsEndOfEncoding = [&] {
5030 // The set of chars that can potentially follow an <encoding> (none of which
5031 // can start a <type>). Enumerating these allows us to avoid speculative
5032 // parsing.
5033 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5034 };
5035
5036 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005037 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005038 if (Name == nullptr)
5039 return nullptr;
5040
5041 if (resolveForwardTemplateRefs(NameInfo))
5042 return nullptr;
5043
5044 if (IsEndOfEncoding())
5045 return Name;
5046
5047 Node *Attrs = nullptr;
5048 if (consumeIf("Ua9enable_ifI")) {
5049 size_t BeforeArgs = Names.size();
5050 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005051 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005052 if (Arg == nullptr)
5053 return nullptr;
5054 Names.push_back(Arg);
5055 }
5056 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005057 if (!Attrs)
5058 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005059 }
5060
5061 Node *ReturnType = nullptr;
5062 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005063 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005064 if (ReturnType == nullptr)
5065 return nullptr;
5066 }
5067
5068 if (consumeIf('v'))
5069 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5070 Attrs, NameInfo.CVQualifiers,
5071 NameInfo.ReferenceQualifier);
5072
5073 size_t ParamsBegin = Names.size();
5074 do {
Pavel Labathba825192018-10-16 14:29:14 +00005075 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005076 if (Ty == nullptr)
5077 return nullptr;
5078 Names.push_back(Ty);
5079 } while (!IsEndOfEncoding());
5080
5081 return make<FunctionEncoding>(ReturnType, Name,
5082 popTrailingNodeArray(ParamsBegin),
5083 Attrs, NameInfo.CVQualifiers,
5084 NameInfo.ReferenceQualifier);
5085}
5086
5087template <class Float>
5088struct FloatData;
5089
5090template <>
5091struct FloatData<float>
5092{
5093 static const size_t mangled_size = 8;
5094 static const size_t max_demangled_size = 24;
5095 static constexpr const char* spec = "%af";
5096};
5097
5098template <>
5099struct FloatData<double>
5100{
5101 static const size_t mangled_size = 16;
5102 static const size_t max_demangled_size = 32;
5103 static constexpr const char* spec = "%a";
5104};
5105
5106template <>
5107struct FloatData<long double>
5108{
5109#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5110 defined(__wasm__)
5111 static const size_t mangled_size = 32;
5112#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5113 static const size_t mangled_size = 16;
5114#else
5115 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5116#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005117 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5118 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5119 // Negatives are one character longer than positives.
5120 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5121 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5122 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005123 static constexpr const char *spec = "%LaL";
5124};
5125
Pavel Labathba825192018-10-16 14:29:14 +00005126template <typename Alloc, typename Derived>
5127template <class Float>
5128Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005129 const size_t N = FloatData<Float>::mangled_size;
5130 if (numLeft() <= N)
5131 return nullptr;
5132 StringView Data(First, First + N);
5133 for (char C : Data)
5134 if (!std::isxdigit(C))
5135 return nullptr;
5136 First += N;
5137 if (!consumeIf('E'))
5138 return nullptr;
5139 return make<FloatLiteralImpl<Float>>(Data);
5140}
5141
5142// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005143template <typename Alloc, typename Derived>
5144bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005145 if (!(look() >= '0' && look() <= '9') &&
5146 !(look() >= 'A' && look() <= 'Z'))
5147 return true;
5148
5149 size_t Id = 0;
5150 while (true) {
5151 if (look() >= '0' && look() <= '9') {
5152 Id *= 36;
5153 Id += static_cast<size_t>(look() - '0');
5154 } else if (look() >= 'A' && look() <= 'Z') {
5155 Id *= 36;
5156 Id += static_cast<size_t>(look() - 'A') + 10;
5157 } else {
5158 *Out = Id;
5159 return false;
5160 }
5161 ++First;
5162 }
5163}
5164
5165// <substitution> ::= S <seq-id> _
5166// ::= S_
5167// <substitution> ::= Sa # ::std::allocator
5168// <substitution> ::= Sb # ::std::basic_string
5169// <substitution> ::= Ss # ::std::basic_string < char,
5170// ::std::char_traits<char>,
5171// ::std::allocator<char> >
5172// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5173// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5174// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005175// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005176template <typename Derived, typename Alloc>
5177Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005178 if (!consumeIf('S'))
5179 return nullptr;
5180
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005181 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005182 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005183 switch (look()) {
5184 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005185 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005186 break;
5187 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005188 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005189 break;
5190 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005191 Kind = SpecialSubKind::iostream;
5192 break;
5193 case 'i':
5194 Kind = SpecialSubKind::istream;
5195 break;
5196 case 'o':
5197 Kind = SpecialSubKind::ostream;
5198 break;
5199 case 's':
5200 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005201 break;
5202 default:
5203 return nullptr;
5204 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005205 ++First;
5206 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005207 if (!SpecialSub)
5208 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005209
Richard Smithc20d1442018-08-20 20:14:49 +00005210 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5211 // has ABI tags, the tags are appended to the substitution; the result is a
5212 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005213 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005214 if (WithTags != SpecialSub) {
5215 Subs.push_back(WithTags);
5216 SpecialSub = WithTags;
5217 }
5218 return SpecialSub;
5219 }
5220
5221 // ::= S_
5222 if (consumeIf('_')) {
5223 if (Subs.empty())
5224 return nullptr;
5225 return Subs[0];
5226 }
5227
5228 // ::= S <seq-id> _
5229 size_t Index = 0;
5230 if (parseSeqId(&Index))
5231 return nullptr;
5232 ++Index;
5233 if (!consumeIf('_') || Index >= Subs.size())
5234 return nullptr;
5235 return Subs[Index];
5236}
5237
5238// <template-param> ::= T_ # first template parameter
5239// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005240// ::= TL <level-1> __
5241// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005242template <typename Derived, typename Alloc>
5243Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005244 if (!consumeIf('T'))
5245 return nullptr;
5246
Richard Smithdf1c14c2019-09-06 23:53:21 +00005247 size_t Level = 0;
5248 if (consumeIf('L')) {
5249 if (parsePositiveInteger(&Level))
5250 return nullptr;
5251 ++Level;
5252 if (!consumeIf('_'))
5253 return nullptr;
5254 }
5255
Richard Smithc20d1442018-08-20 20:14:49 +00005256 size_t Index = 0;
5257 if (!consumeIf('_')) {
5258 if (parsePositiveInteger(&Index))
5259 return nullptr;
5260 ++Index;
5261 if (!consumeIf('_'))
5262 return nullptr;
5263 }
5264
Richard Smithc20d1442018-08-20 20:14:49 +00005265 // If we're in a context where this <template-param> refers to a
5266 // <template-arg> further ahead in the mangled name (currently just conversion
5267 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005268 // This can only happen at the outermost level.
5269 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005270 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5271 if (!ForwardRef)
5272 return nullptr;
5273 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5274 ForwardTemplateRefs.push_back(
5275 static_cast<ForwardTemplateReference *>(ForwardRef));
5276 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005277 }
5278
Richard Smithdf1c14c2019-09-06 23:53:21 +00005279 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5280 Index >= TemplateParams[Level]->size()) {
5281 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5282 // list are mangled as the corresponding artificial template type parameter.
5283 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5284 // This will be popped by the ScopedTemplateParamList in
5285 // parseUnnamedTypeName.
5286 if (Level == TemplateParams.size())
5287 TemplateParams.push_back(nullptr);
5288 return make<NameType>("auto");
5289 }
5290
Richard Smithc20d1442018-08-20 20:14:49 +00005291 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005292 }
5293
5294 return (*TemplateParams[Level])[Index];
5295}
5296
5297// <template-param-decl> ::= Ty # type parameter
5298// ::= Tn <type> # non-type parameter
5299// ::= Tt <template-param-decl>* E # template parameter
5300// ::= Tp <template-param-decl> # parameter pack
5301template <typename Derived, typename Alloc>
5302Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5303 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5304 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5305 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5306 if (N) TemplateParams.back()->push_back(N);
5307 return N;
5308 };
5309
5310 if (consumeIf("Ty")) {
5311 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5312 if (!Name)
5313 return nullptr;
5314 return make<TypeTemplateParamDecl>(Name);
5315 }
5316
5317 if (consumeIf("Tn")) {
5318 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5319 if (!Name)
5320 return nullptr;
5321 Node *Type = parseType();
5322 if (!Type)
5323 return nullptr;
5324 return make<NonTypeTemplateParamDecl>(Name, Type);
5325 }
5326
5327 if (consumeIf("Tt")) {
5328 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5329 if (!Name)
5330 return nullptr;
5331 size_t ParamsBegin = Names.size();
5332 ScopedTemplateParamList TemplateTemplateParamParams(this);
5333 while (!consumeIf("E")) {
5334 Node *P = parseTemplateParamDecl();
5335 if (!P)
5336 return nullptr;
5337 Names.push_back(P);
5338 }
5339 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5340 return make<TemplateTemplateParamDecl>(Name, Params);
5341 }
5342
5343 if (consumeIf("Tp")) {
5344 Node *P = parseTemplateParamDecl();
5345 if (!P)
5346 return nullptr;
5347 return make<TemplateParamPackDecl>(P);
5348 }
5349
5350 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005351}
5352
5353// <template-arg> ::= <type> # type or template
5354// ::= X <expression> E # expression
5355// ::= <expr-primary> # simple expressions
5356// ::= J <template-arg>* E # argument pack
5357// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005358template <typename Derived, typename Alloc>
5359Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005360 switch (look()) {
5361 case 'X': {
5362 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005363 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005364 if (Arg == nullptr || !consumeIf('E'))
5365 return nullptr;
5366 return Arg;
5367 }
5368 case 'J': {
5369 ++First;
5370 size_t ArgsBegin = Names.size();
5371 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005372 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005373 if (Arg == nullptr)
5374 return nullptr;
5375 Names.push_back(Arg);
5376 }
5377 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5378 return make<TemplateArgumentPack>(Args);
5379 }
5380 case 'L': {
5381 // ::= LZ <encoding> E # extension
5382 if (look(1) == 'Z') {
5383 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005384 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005385 if (Arg == nullptr || !consumeIf('E'))
5386 return nullptr;
5387 return Arg;
5388 }
5389 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005390 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005391 }
5392 default:
Pavel Labathba825192018-10-16 14:29:14 +00005393 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005394 }
5395}
5396
5397// <template-args> ::= I <template-arg>* E
5398// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005399template <typename Derived, typename Alloc>
5400Node *
5401AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005402 if (!consumeIf('I'))
5403 return nullptr;
5404
5405 // <template-params> refer to the innermost <template-args>. Clear out any
5406 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005407 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005408 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005409 TemplateParams.push_back(&OuterTemplateParams);
5410 OuterTemplateParams.clear();
5411 }
Richard Smithc20d1442018-08-20 20:14:49 +00005412
5413 size_t ArgsBegin = Names.size();
5414 while (!consumeIf('E')) {
5415 if (TagTemplates) {
5416 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005417 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005418 TemplateParams = std::move(OldParams);
5419 if (Arg == nullptr)
5420 return nullptr;
5421 Names.push_back(Arg);
5422 Node *TableEntry = Arg;
5423 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5424 TableEntry = make<ParameterPack>(
5425 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005426 if (!TableEntry)
5427 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005428 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005429 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005430 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005431 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005432 if (Arg == nullptr)
5433 return nullptr;
5434 Names.push_back(Arg);
5435 }
5436 }
5437 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5438}
5439
5440// <mangled-name> ::= _Z <encoding>
5441// ::= <type>
5442// extension ::= ___Z <encoding> _block_invoke
5443// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5444// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005445template <typename Derived, typename Alloc>
5446Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005447 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005448 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005449 if (Encoding == nullptr)
5450 return nullptr;
5451 if (look() == '.') {
5452 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5453 First = Last;
5454 }
5455 if (numLeft() != 0)
5456 return nullptr;
5457 return Encoding;
5458 }
5459
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005460 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005461 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005462 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5463 return nullptr;
5464 bool RequireNumber = consumeIf('_');
5465 if (parseNumber().empty() && RequireNumber)
5466 return nullptr;
5467 if (look() == '.')
5468 First = Last;
5469 if (numLeft() != 0)
5470 return nullptr;
5471 return make<SpecialName>("invocation function for block in ", Encoding);
5472 }
5473
Pavel Labathba825192018-10-16 14:29:14 +00005474 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005475 if (numLeft() != 0)
5476 return nullptr;
5477 return Ty;
5478}
5479
Pavel Labathba825192018-10-16 14:29:14 +00005480template <typename Alloc>
5481struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5482 using AbstractManglingParser<ManglingParser<Alloc>,
5483 Alloc>::AbstractManglingParser;
5484};
5485
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005486DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005487
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005488#endif // DEMANGLE_ITANIUMDEMANGLE_H