blob: 7da823144d8714ca754826cb56e2e2fa68c470bc [file] [log] [blame]
Richard Smithc20d1442018-08-20 20:14:49 +00001//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===//
2//
Chandler Carruth8ee27c32019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Richard Smithc20d1442018-08-20 20:14:49 +00006//
7//===----------------------------------------------------------------------===//
8//
Nathan Sidwell5b0a8cf2022-01-24 06:38:47 -08009// Generic itanium demangler library.
10// There are two copies of this file in the source tree. The one under
11// libcxxabi is the original and the one under llvm is the copy. Use
12// cp-to-llvm.sh to update the copy. See README.txt for more details.
Richard Smithc20d1442018-08-20 20:14:49 +000013//
14//===----------------------------------------------------------------------===//
15
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000016#ifndef DEMANGLE_ITANIUMDEMANGLE_H
17#define DEMANGLE_ITANIUMDEMANGLE_H
Richard Smithc20d1442018-08-20 20:14:49 +000018
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000019#include "DemangleConfig.h"
Richard Smithc20d1442018-08-20 20:14:49 +000020#include "StringView.h"
21#include "Utility.h"
Nathan Sidwellbbc632f2022-01-24 04:11:59 -080022#include <algorithm>
Richard Smithc20d1442018-08-20 20:14:49 +000023#include <cassert>
24#include <cctype>
25#include <cstdio>
26#include <cstdlib>
27#include <cstring>
Nathan Sidwellbbc632f2022-01-24 04:11:59 -080028#include <limits>
Nikolas Klauser62855772022-09-05 00:01:15 +020029#include <new>
Richard Smithc20d1442018-08-20 20:14:49 +000030#include <utility>
31
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +000032DEMANGLE_NAMESPACE_BEGIN
33
Mikhail Borisov8452f062021-08-17 18:06:53 -040034template <class T, size_t N> class PODSmallVector {
35 static_assert(std::is_pod<T>::value,
36 "T is required to be a plain old data type");
37
38 T *First = nullptr;
39 T *Last = nullptr;
40 T *Cap = nullptr;
41 T Inline[N] = {0};
42
43 bool isInline() const { return First == Inline; }
44
45 void clearInline() {
46 First = Inline;
47 Last = Inline;
48 Cap = Inline + N;
49 }
50
51 void reserve(size_t NewCap) {
52 size_t S = size();
53 if (isInline()) {
54 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
55 if (Tmp == nullptr)
56 std::terminate();
57 std::copy(First, Last, Tmp);
58 First = Tmp;
59 } else {
60 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
61 if (First == nullptr)
62 std::terminate();
63 }
64 Last = First + S;
65 Cap = First + NewCap;
66 }
67
68public:
69 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}
70
71 PODSmallVector(const PODSmallVector &) = delete;
72 PODSmallVector &operator=(const PODSmallVector &) = delete;
73
74 PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {
75 if (Other.isInline()) {
76 std::copy(Other.begin(), Other.end(), First);
77 Last = First + Other.size();
78 Other.clear();
79 return;
80 }
81
82 First = Other.First;
83 Last = Other.Last;
84 Cap = Other.Cap;
85 Other.clearInline();
86 }
87
88 PODSmallVector &operator=(PODSmallVector &&Other) {
89 if (Other.isInline()) {
90 if (!isInline()) {
91 std::free(First);
92 clearInline();
93 }
94 std::copy(Other.begin(), Other.end(), First);
95 Last = First + Other.size();
96 Other.clear();
97 return *this;
98 }
99
100 if (isInline()) {
101 First = Other.First;
102 Last = Other.Last;
103 Cap = Other.Cap;
104 Other.clearInline();
105 return *this;
106 }
107
108 std::swap(First, Other.First);
109 std::swap(Last, Other.Last);
110 std::swap(Cap, Other.Cap);
111 Other.clear();
112 return *this;
113 }
114
115 // NOLINTNEXTLINE(readability-identifier-naming)
116 void push_back(const T &Elem) {
117 if (Last == Cap)
118 reserve(size() * 2);
119 *Last++ = Elem;
120 }
121
122 // NOLINTNEXTLINE(readability-identifier-naming)
123 void pop_back() {
124 assert(Last != First && "Popping empty vector!");
125 --Last;
126 }
127
128 void dropBack(size_t Index) {
129 assert(Index <= size() && "dropBack() can't expand!");
130 Last = First + Index;
131 }
132
133 T *begin() { return First; }
134 T *end() { return Last; }
135
136 bool empty() const { return First == Last; }
137 size_t size() const { return static_cast<size_t>(Last - First); }
138 T &back() {
139 assert(Last != First && "Calling back() on empty vector!");
140 return *(Last - 1);
141 }
142 T &operator[](size_t Index) {
143 assert(Index < size() && "Invalid access!");
144 return *(begin() + Index);
145 }
146 void clear() { Last = First; }
147
148 ~PODSmallVector() {
149 if (!isInline())
150 std::free(First);
151 }
152};
153
Richard Smithc20d1442018-08-20 20:14:49 +0000154// Base class of all AST nodes. The AST is built by the parser, then is
155// traversed by the printLeft/Right functions to produce a demangled string.
156class Node {
157public:
158 enum Kind : unsigned char {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -0700159#define NODE(NodeKind) K##NodeKind,
160#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +0000161 };
162
163 /// Three-way bool to track a cached value. Unknown is possible if this node
164 /// has an unexpanded parameter pack below it that may affect this cache.
165 enum class Cache : unsigned char { Yes, No, Unknown, };
166
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800167 /// Operator precedence for expression nodes. Used to determine required
168 /// parens in expression emission.
169 enum class Prec {
170 Primary,
171 Postfix,
172 Unary,
173 Cast,
174 PtrMem,
175 Multiplicative,
176 Additive,
177 Shift,
178 Spaceship,
179 Relational,
180 Equality,
181 And,
182 Xor,
183 Ior,
184 AndIf,
185 OrIf,
186 Conditional,
187 Assign,
188 Comma,
189 Default,
190 };
191
Richard Smithc20d1442018-08-20 20:14:49 +0000192private:
193 Kind K;
194
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800195 Prec Precedence : 6;
196
Richard Smithc20d1442018-08-20 20:14:49 +0000197 // FIXME: Make these protected.
198public:
199 /// Tracks if this node has a component on its right side, in which case we
200 /// need to call printRight.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800201 Cache RHSComponentCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000202
203 /// Track if this node is a (possibly qualified) array type. This can affect
204 /// how we format the output string.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800205 Cache ArrayCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000206
207 /// Track if this node is a (possibly qualified) function type. This can
208 /// affect how we format the output string.
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800209 Cache FunctionCache : 2;
Richard Smithc20d1442018-08-20 20:14:49 +0000210
211public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800212 Node(Kind K_, Prec Precedence_ = Prec::Primary,
213 Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,
214 Cache FunctionCache_ = Cache::No)
215 : K(K_), Precedence(Precedence_), RHSComponentCache(RHSComponentCache_),
216 ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {}
217 Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_ = Cache::No,
218 Cache FunctionCache_ = Cache::No)
219 : Node(K_, Prec::Primary, RHSComponentCache_, ArrayCache_,
220 FunctionCache_) {}
Richard Smithc20d1442018-08-20 20:14:49 +0000221
222 /// Visit the most-derived object corresponding to this object.
223 template<typename Fn> void visit(Fn F) const;
224
225 // The following function is provided by all derived classes:
226 //
227 // Call F with arguments that, when passed to the constructor of this node,
228 // would construct an equivalent node.
229 //template<typename Fn> void match(Fn F) const;
230
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700231 bool hasRHSComponent(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000232 if (RHSComponentCache != Cache::Unknown)
233 return RHSComponentCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700234 return hasRHSComponentSlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000235 }
236
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700237 bool hasArray(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000238 if (ArrayCache != Cache::Unknown)
239 return ArrayCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700240 return hasArraySlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000241 }
242
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700243 bool hasFunction(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000244 if (FunctionCache != Cache::Unknown)
245 return FunctionCache == Cache::Yes;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700246 return hasFunctionSlow(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000247 }
248
249 Kind getKind() const { return K; }
250
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800251 Prec getPrecedence() const { return Precedence; }
252
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700253 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }
254 virtual bool hasArraySlow(OutputBuffer &) const { return false; }
255 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }
Richard Smithc20d1442018-08-20 20:14:49 +0000256
257 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to
258 // get at a node that actually represents some concrete syntax.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700259 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }
Richard Smithc20d1442018-08-20 20:14:49 +0000260
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800261 // Print this node as an expression operand, surrounding it in parentheses if
262 // its precedence is [Strictly] weaker than P.
263 void printAsOperand(OutputBuffer &OB, Prec P = Prec::Default,
264 bool StrictlyWorse = false) const {
265 bool Paren =
266 unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse);
267 if (Paren)
268 OB.printOpen();
269 print(OB);
270 if (Paren)
271 OB.printClose();
272 }
273
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700274 void print(OutputBuffer &OB) const {
275 printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000276 if (RHSComponentCache != Cache::No)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700277 printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000278 }
279
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -0800280 // Print the "left" side of this Node into OutputBuffer.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700281 virtual void printLeft(OutputBuffer &) const = 0;
Richard Smithc20d1442018-08-20 20:14:49 +0000282
283 // Print the "right". This distinction is necessary to represent C++ types
284 // that appear on the RHS of their subtype, such as arrays or functions.
285 // Since most types don't have such a component, provide a default
286 // implementation.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700287 virtual void printRight(OutputBuffer &) const {}
Richard Smithc20d1442018-08-20 20:14:49 +0000288
289 virtual StringView getBaseName() const { return StringView(); }
290
291 // Silence compiler warnings, this dtor will never be called.
292 virtual ~Node() = default;
293
294#ifndef NDEBUG
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +0000295 DEMANGLE_DUMP_METHOD void dump() const;
Richard Smithc20d1442018-08-20 20:14:49 +0000296#endif
297};
298
299class NodeArray {
300 Node **Elements;
301 size_t NumElements;
302
303public:
304 NodeArray() : Elements(nullptr), NumElements(0) {}
305 NodeArray(Node **Elements_, size_t NumElements_)
306 : Elements(Elements_), NumElements(NumElements_) {}
307
308 bool empty() const { return NumElements == 0; }
309 size_t size() const { return NumElements; }
310
311 Node **begin() const { return Elements; }
312 Node **end() const { return Elements + NumElements; }
313
314 Node *operator[](size_t Idx) const { return Elements[Idx]; }
315
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700316 void printWithComma(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000317 bool FirstElement = true;
318 for (size_t Idx = 0; Idx != NumElements; ++Idx) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700319 size_t BeforeComma = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +0000320 if (!FirstElement)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700321 OB += ", ";
322 size_t AfterComma = OB.getCurrentPosition();
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800323 Elements[Idx]->printAsOperand(OB, Node::Prec::Comma);
Richard Smithc20d1442018-08-20 20:14:49 +0000324
325 // Elements[Idx] is an empty parameter pack expansion, we should erase the
326 // comma we just printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700327 if (AfterComma == OB.getCurrentPosition()) {
328 OB.setCurrentPosition(BeforeComma);
Richard Smithc20d1442018-08-20 20:14:49 +0000329 continue;
330 }
331
332 FirstElement = false;
333 }
334 }
335};
336
337struct NodeArrayNode : Node {
338 NodeArray Array;
339 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}
340
341 template<typename Fn> void match(Fn F) const { F(Array); }
342
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700343 void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000344};
345
346class DotSuffix final : public Node {
347 const Node *Prefix;
348 const StringView Suffix;
349
350public:
351 DotSuffix(const Node *Prefix_, StringView Suffix_)
352 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}
353
354 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }
355
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700356 void printLeft(OutputBuffer &OB) const override {
357 Prefix->print(OB);
358 OB += " (";
359 OB += Suffix;
360 OB += ")";
Richard Smithc20d1442018-08-20 20:14:49 +0000361 }
362};
363
364class VendorExtQualType final : public Node {
365 const Node *Ty;
366 StringView Ext;
Alex Orlovf50df922021-03-24 10:21:32 +0400367 const Node *TA;
Richard Smithc20d1442018-08-20 20:14:49 +0000368
369public:
Alex Orlovf50df922021-03-24 10:21:32 +0400370 VendorExtQualType(const Node *Ty_, StringView Ext_, const Node *TA_)
371 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}
Richard Smithc20d1442018-08-20 20:14:49 +0000372
Alex Orlovf50df922021-03-24 10:21:32 +0400373 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }
Richard Smithc20d1442018-08-20 20:14:49 +0000374
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700375 void printLeft(OutputBuffer &OB) const override {
376 Ty->print(OB);
377 OB += " ";
378 OB += Ext;
Alex Orlovf50df922021-03-24 10:21:32 +0400379 if (TA != nullptr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700380 TA->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000381 }
382};
383
384enum FunctionRefQual : unsigned char {
385 FrefQualNone,
386 FrefQualLValue,
387 FrefQualRValue,
388};
389
390enum Qualifiers {
391 QualNone = 0,
392 QualConst = 0x1,
393 QualVolatile = 0x2,
394 QualRestrict = 0x4,
395};
396
397inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {
398 return Q1 = static_cast<Qualifiers>(Q1 | Q2);
399}
400
Richard Smithdf1c14c2019-09-06 23:53:21 +0000401class QualType final : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +0000402protected:
403 const Qualifiers Quals;
404 const Node *Child;
405
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700406 void printQuals(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000407 if (Quals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700408 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000409 if (Quals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700410 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000411 if (Quals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700412 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000413 }
414
415public:
416 QualType(const Node *Child_, Qualifiers Quals_)
417 : Node(KQualType, Child_->RHSComponentCache,
418 Child_->ArrayCache, Child_->FunctionCache),
419 Quals(Quals_), Child(Child_) {}
420
421 template<typename Fn> void match(Fn F) const { F(Child, Quals); }
422
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700423 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
424 return Child->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000425 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700426 bool hasArraySlow(OutputBuffer &OB) const override {
427 return Child->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000428 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700429 bool hasFunctionSlow(OutputBuffer &OB) const override {
430 return Child->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000431 }
432
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700433 void printLeft(OutputBuffer &OB) const override {
434 Child->printLeft(OB);
435 printQuals(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000436 }
437
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700438 void printRight(OutputBuffer &OB) const override { Child->printRight(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000439};
440
441class ConversionOperatorType final : public Node {
442 const Node *Ty;
443
444public:
445 ConversionOperatorType(const Node *Ty_)
446 : Node(KConversionOperatorType), Ty(Ty_) {}
447
448 template<typename Fn> void match(Fn F) const { F(Ty); }
449
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700450 void printLeft(OutputBuffer &OB) const override {
451 OB += "operator ";
452 Ty->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000453 }
454};
455
456class PostfixQualifiedType final : public Node {
457 const Node *Ty;
458 const StringView Postfix;
459
460public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -0700461 PostfixQualifiedType(const Node *Ty_, StringView Postfix_)
Richard Smithc20d1442018-08-20 20:14:49 +0000462 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}
463
464 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }
465
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700466 void printLeft(OutputBuffer &OB) const override {
467 Ty->printLeft(OB);
468 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +0000469 }
470};
471
472class NameType final : public Node {
473 const StringView Name;
474
475public:
476 NameType(StringView Name_) : Node(KNameType), Name(Name_) {}
477
478 template<typename Fn> void match(Fn F) const { F(Name); }
479
480 StringView getName() const { return Name; }
481 StringView getBaseName() const override { return Name; }
482
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700483 void printLeft(OutputBuffer &OB) const override { OB += Name; }
Richard Smithc20d1442018-08-20 20:14:49 +0000484};
485
Senran Zhange025ba52022-03-27 00:04:23 +0800486class BitIntType final : public Node {
487 const Node *Size;
488 bool Signed;
489
490public:
491 BitIntType(const Node *Size_, bool Signed_)
492 : Node(KBitIntType), Size(Size_), Signed(Signed_) {}
493
494 template <typename Fn> void match(Fn F) const { F(Size, Signed); }
495
496 void printLeft(OutputBuffer &OB) const override {
497 if (!Signed)
498 OB += "unsigned ";
499 OB += "_BitInt";
500 OB.printOpen();
501 Size->printAsOperand(OB);
502 OB.printClose();
503 }
504};
505
Richard Smithc20d1442018-08-20 20:14:49 +0000506class ElaboratedTypeSpefType : public Node {
507 StringView Kind;
508 Node *Child;
509public:
510 ElaboratedTypeSpefType(StringView Kind_, Node *Child_)
511 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}
512
513 template<typename Fn> void match(Fn F) const { F(Kind, Child); }
514
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700515 void printLeft(OutputBuffer &OB) const override {
516 OB += Kind;
517 OB += ' ';
518 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000519 }
520};
521
522struct AbiTagAttr : Node {
523 Node *Base;
524 StringView Tag;
525
526 AbiTagAttr(Node* Base_, StringView Tag_)
527 : Node(KAbiTagAttr, Base_->RHSComponentCache,
528 Base_->ArrayCache, Base_->FunctionCache),
529 Base(Base_), Tag(Tag_) {}
530
531 template<typename Fn> void match(Fn F) const { F(Base, Tag); }
532
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700533 void printLeft(OutputBuffer &OB) const override {
534 Base->printLeft(OB);
535 OB += "[abi:";
536 OB += Tag;
537 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +0000538 }
539};
540
541class EnableIfAttr : public Node {
542 NodeArray Conditions;
543public:
544 EnableIfAttr(NodeArray Conditions_)
545 : Node(KEnableIfAttr), Conditions(Conditions_) {}
546
547 template<typename Fn> void match(Fn F) const { F(Conditions); }
548
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700549 void printLeft(OutputBuffer &OB) const override {
550 OB += " [enable_if:";
551 Conditions.printWithComma(OB);
552 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +0000553 }
554};
555
556class ObjCProtoName : public Node {
557 const Node *Ty;
558 StringView Protocol;
559
560 friend class PointerType;
561
562public:
563 ObjCProtoName(const Node *Ty_, StringView Protocol_)
564 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}
565
566 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }
567
568 bool isObjCObject() const {
569 return Ty->getKind() == KNameType &&
570 static_cast<const NameType *>(Ty)->getName() == "objc_object";
571 }
572
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700573 void printLeft(OutputBuffer &OB) const override {
574 Ty->print(OB);
575 OB += "<";
576 OB += Protocol;
577 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +0000578 }
579};
580
581class PointerType final : public Node {
582 const Node *Pointee;
583
584public:
585 PointerType(const Node *Pointee_)
586 : Node(KPointerType, Pointee_->RHSComponentCache),
587 Pointee(Pointee_) {}
588
589 template<typename Fn> void match(Fn F) const { F(Pointee); }
590
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700591 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
592 return Pointee->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000593 }
594
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700595 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000596 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.
597 if (Pointee->getKind() != KObjCProtoName ||
598 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700599 Pointee->printLeft(OB);
600 if (Pointee->hasArray(OB))
601 OB += " ";
602 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
603 OB += "(";
604 OB += "*";
Richard Smithc20d1442018-08-20 20:14:49 +0000605 } else {
606 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700607 OB += "id<";
608 OB += objcProto->Protocol;
609 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +0000610 }
611 }
612
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700613 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000614 if (Pointee->getKind() != KObjCProtoName ||
615 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700616 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))
617 OB += ")";
618 Pointee->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000619 }
620 }
621};
622
623enum class ReferenceKind {
624 LValue,
625 RValue,
626};
627
628// Represents either a LValue or an RValue reference type.
629class ReferenceType : public Node {
630 const Node *Pointee;
631 ReferenceKind RK;
632
633 mutable bool Printing = false;
634
635 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The
636 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any
637 // other combination collapses to a lvalue ref.
Mikhail Borisov05f77222021-08-17 18:10:57 -0400638 //
639 // A combination of a TemplateForwardReference and a back-ref Substitution
640 // from an ill-formed string may have created a cycle; use cycle detection to
641 // avoid looping forever.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700642 std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {
Richard Smithc20d1442018-08-20 20:14:49 +0000643 auto SoFar = std::make_pair(RK, Pointee);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400644 // Track the chain of nodes for the Floyd's 'tortoise and hare'
645 // cycle-detection algorithm, since getSyntaxNode(S) is impure
646 PODSmallVector<const Node *, 8> Prev;
Richard Smithc20d1442018-08-20 20:14:49 +0000647 for (;;) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700648 const Node *SN = SoFar.second->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000649 if (SN->getKind() != KReferenceType)
650 break;
651 auto *RT = static_cast<const ReferenceType *>(SN);
652 SoFar.second = RT->Pointee;
653 SoFar.first = std::min(SoFar.first, RT->RK);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400654
655 // The middle of Prev is the 'slow' pointer moving at half speed
656 Prev.push_back(SoFar.second);
657 if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {
658 // Cycle detected
659 SoFar.second = nullptr;
660 break;
661 }
Richard Smithc20d1442018-08-20 20:14:49 +0000662 }
663 return SoFar;
664 }
665
666public:
667 ReferenceType(const Node *Pointee_, ReferenceKind RK_)
668 : Node(KReferenceType, Pointee_->RHSComponentCache),
669 Pointee(Pointee_), RK(RK_) {}
670
671 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }
672
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700673 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
674 return Pointee->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000675 }
676
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700677 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000678 if (Printing)
679 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -0800680 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700681 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400682 if (!Collapsed.second)
683 return;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700684 Collapsed.second->printLeft(OB);
685 if (Collapsed.second->hasArray(OB))
686 OB += " ";
687 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
688 OB += "(";
Richard Smithc20d1442018-08-20 20:14:49 +0000689
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700690 OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");
Richard Smithc20d1442018-08-20 20:14:49 +0000691 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700692 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000693 if (Printing)
694 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -0800695 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700696 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);
Mikhail Borisov05f77222021-08-17 18:10:57 -0400697 if (!Collapsed.second)
698 return;
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700699 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))
700 OB += ")";
701 Collapsed.second->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000702 }
703};
704
705class PointerToMemberType final : public Node {
706 const Node *ClassType;
707 const Node *MemberType;
708
709public:
710 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)
711 : Node(KPointerToMemberType, MemberType_->RHSComponentCache),
712 ClassType(ClassType_), MemberType(MemberType_) {}
713
714 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }
715
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700716 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
717 return MemberType->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000718 }
719
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700720 void printLeft(OutputBuffer &OB) const override {
721 MemberType->printLeft(OB);
722 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
723 OB += "(";
Richard Smithc20d1442018-08-20 20:14:49 +0000724 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700725 OB += " ";
726 ClassType->print(OB);
727 OB += "::*";
Richard Smithc20d1442018-08-20 20:14:49 +0000728 }
729
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700730 void printRight(OutputBuffer &OB) const override {
731 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))
732 OB += ")";
733 MemberType->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000734 }
735};
736
Richard Smithc20d1442018-08-20 20:14:49 +0000737class ArrayType final : public Node {
738 const Node *Base;
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800739 Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +0000740
741public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800742 ArrayType(const Node *Base_, Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +0000743 : Node(KArrayType,
744 /*RHSComponentCache=*/Cache::Yes,
745 /*ArrayCache=*/Cache::Yes),
746 Base(Base_), Dimension(Dimension_) {}
747
748 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }
749
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700750 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
751 bool hasArraySlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000752
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700753 void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); }
Richard Smithc20d1442018-08-20 20:14:49 +0000754
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700755 void printRight(OutputBuffer &OB) const override {
756 if (OB.back() != ']')
757 OB += " ";
758 OB += "[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -0800759 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700760 Dimension->print(OB);
761 OB += "]";
762 Base->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000763 }
764};
765
766class FunctionType final : public Node {
767 const Node *Ret;
768 NodeArray Params;
769 Qualifiers CVQuals;
770 FunctionRefQual RefQual;
771 const Node *ExceptionSpec;
772
773public:
774 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,
775 FunctionRefQual RefQual_, const Node *ExceptionSpec_)
776 : Node(KFunctionType,
777 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
778 /*FunctionCache=*/Cache::Yes),
779 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),
780 ExceptionSpec(ExceptionSpec_) {}
781
782 template<typename Fn> void match(Fn F) const {
783 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);
784 }
785
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700786 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
787 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000788
789 // Handle C++'s ... quirky decl grammar by using the left & right
790 // distinction. Consider:
791 // int (*f(float))(char) {}
792 // f is a function that takes a float and returns a pointer to a function
793 // that takes a char and returns an int. If we're trying to print f, start
794 // by printing out the return types's left, then print our parameters, then
795 // finally print right of the return type.
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700796 void printLeft(OutputBuffer &OB) const override {
797 Ret->printLeft(OB);
798 OB += " ";
Richard Smithc20d1442018-08-20 20:14:49 +0000799 }
800
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700801 void printRight(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800802 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700803 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800804 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700805 Ret->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000806
807 if (CVQuals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700808 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000809 if (CVQuals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700810 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000811 if (CVQuals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700812 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000813
814 if (RefQual == FrefQualLValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700815 OB += " &";
Richard Smithc20d1442018-08-20 20:14:49 +0000816 else if (RefQual == FrefQualRValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700817 OB += " &&";
Richard Smithc20d1442018-08-20 20:14:49 +0000818
819 if (ExceptionSpec != nullptr) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700820 OB += ' ';
821 ExceptionSpec->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000822 }
823 }
824};
825
826class NoexceptSpec : public Node {
827 const Node *E;
828public:
829 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}
830
831 template<typename Fn> void match(Fn F) const { F(E); }
832
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700833 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800834 OB += "noexcept";
835 OB.printOpen();
836 E->printAsOperand(OB);
837 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000838 }
839};
840
841class DynamicExceptionSpec : public Node {
842 NodeArray Types;
843public:
844 DynamicExceptionSpec(NodeArray Types_)
845 : Node(KDynamicExceptionSpec), Types(Types_) {}
846
847 template<typename Fn> void match(Fn F) const { F(Types); }
848
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700849 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800850 OB += "throw";
851 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700852 Types.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800853 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000854 }
855};
856
857class FunctionEncoding final : public Node {
858 const Node *Ret;
859 const Node *Name;
860 NodeArray Params;
861 const Node *Attrs;
862 Qualifiers CVQuals;
863 FunctionRefQual RefQual;
864
865public:
866 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
867 const Node *Attrs_, Qualifiers CVQuals_,
868 FunctionRefQual RefQual_)
869 : Node(KFunctionEncoding,
870 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
871 /*FunctionCache=*/Cache::Yes),
872 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
873 CVQuals(CVQuals_), RefQual(RefQual_) {}
874
875 template<typename Fn> void match(Fn F) const {
876 F(Ret, Name, Params, Attrs, CVQuals, RefQual);
877 }
878
879 Qualifiers getCVQuals() const { return CVQuals; }
880 FunctionRefQual getRefQual() const { return RefQual; }
881 NodeArray getParams() const { return Params; }
882 const Node *getReturnType() const { return Ret; }
883
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700884 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }
885 bool hasFunctionSlow(OutputBuffer &) const override { return true; }
Richard Smithc20d1442018-08-20 20:14:49 +0000886
887 const Node *getName() const { return Name; }
888
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700889 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +0000890 if (Ret) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700891 Ret->printLeft(OB);
892 if (!Ret->hasRHSComponent(OB))
893 OB += " ";
Richard Smithc20d1442018-08-20 20:14:49 +0000894 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700895 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000896 }
897
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700898 void printRight(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800899 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700900 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -0800901 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +0000902 if (Ret)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700903 Ret->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000904
905 if (CVQuals & QualConst)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700906 OB += " const";
Richard Smithc20d1442018-08-20 20:14:49 +0000907 if (CVQuals & QualVolatile)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700908 OB += " volatile";
Richard Smithc20d1442018-08-20 20:14:49 +0000909 if (CVQuals & QualRestrict)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700910 OB += " restrict";
Richard Smithc20d1442018-08-20 20:14:49 +0000911
912 if (RefQual == FrefQualLValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700913 OB += " &";
Richard Smithc20d1442018-08-20 20:14:49 +0000914 else if (RefQual == FrefQualRValue)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700915 OB += " &&";
Richard Smithc20d1442018-08-20 20:14:49 +0000916
917 if (Attrs != nullptr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700918 Attrs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000919 }
920};
921
922class LiteralOperator : public Node {
923 const Node *OpName;
924
925public:
926 LiteralOperator(const Node *OpName_)
927 : Node(KLiteralOperator), OpName(OpName_) {}
928
929 template<typename Fn> void match(Fn F) const { F(OpName); }
930
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700931 void printLeft(OutputBuffer &OB) const override {
932 OB += "operator\"\" ";
933 OpName->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000934 }
935};
936
937class SpecialName final : public Node {
938 const StringView Special;
939 const Node *Child;
940
941public:
942 SpecialName(StringView Special_, const Node *Child_)
943 : Node(KSpecialName), Special(Special_), Child(Child_) {}
944
945 template<typename Fn> void match(Fn F) const { F(Special, Child); }
946
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700947 void printLeft(OutputBuffer &OB) const override {
948 OB += Special;
949 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000950 }
951};
952
953class CtorVtableSpecialName final : public Node {
954 const Node *FirstType;
955 const Node *SecondType;
956
957public:
958 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)
959 : Node(KCtorVtableSpecialName),
960 FirstType(FirstType_), SecondType(SecondType_) {}
961
962 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }
963
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700964 void printLeft(OutputBuffer &OB) const override {
965 OB += "construction vtable for ";
966 FirstType->print(OB);
967 OB += "-in-";
968 SecondType->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000969 }
970};
971
972struct NestedName : Node {
973 Node *Qual;
974 Node *Name;
975
976 NestedName(Node *Qual_, Node *Name_)
977 : Node(KNestedName), Qual(Qual_), Name(Name_) {}
978
979 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
980
981 StringView getBaseName() const override { return Name->getBaseName(); }
982
Luís Ferreiraa4380e22021-10-21 17:31:53 -0700983 void printLeft(OutputBuffer &OB) const override {
984 Qual->print(OB);
985 OB += "::";
986 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +0000987 }
988};
989
Nathan Sidwelledde7bb2022-01-26 07:22:04 -0800990struct ModuleName : Node {
991 ModuleName *Parent;
992 Node *Name;
993 bool IsPartition;
994
995 ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false)
996 : Node(KModuleName), Parent(Parent_), Name(Name_),
997 IsPartition(IsPartition_) {}
998
Nathan Sidwelldafcca22022-03-29 04:43:16 -0700999 template <typename Fn> void match(Fn F) const {
1000 F(Parent, Name, IsPartition);
1001 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08001002
1003 void printLeft(OutputBuffer &OB) const override {
1004 if (Parent)
1005 Parent->print(OB);
1006 if (Parent || IsPartition)
1007 OB += IsPartition ? ':' : '.';
1008 Name->print(OB);
1009 }
1010};
1011
1012struct ModuleEntity : Node {
1013 ModuleName *Module;
1014 Node *Name;
1015
1016 ModuleEntity(ModuleName *Module_, Node *Name_)
1017 : Node(KModuleEntity), Module(Module_), Name(Name_) {}
1018
1019 template <typename Fn> void match(Fn F) const { F(Module, Name); }
1020
1021 StringView getBaseName() const override { return Name->getBaseName(); }
1022
1023 void printLeft(OutputBuffer &OB) const override {
1024 Name->print(OB);
1025 OB += '@';
1026 Module->print(OB);
1027 }
1028};
1029
Richard Smithc20d1442018-08-20 20:14:49 +00001030struct LocalName : Node {
1031 Node *Encoding;
1032 Node *Entity;
1033
1034 LocalName(Node *Encoding_, Node *Entity_)
1035 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}
1036
1037 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }
1038
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001039 void printLeft(OutputBuffer &OB) const override {
1040 Encoding->print(OB);
1041 OB += "::";
1042 Entity->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001043 }
1044};
1045
1046class QualifiedName final : public Node {
1047 // qualifier::name
1048 const Node *Qualifier;
1049 const Node *Name;
1050
1051public:
1052 QualifiedName(const Node *Qualifier_, const Node *Name_)
1053 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}
1054
1055 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }
1056
1057 StringView getBaseName() const override { return Name->getBaseName(); }
1058
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001059 void printLeft(OutputBuffer &OB) const override {
1060 Qualifier->print(OB);
1061 OB += "::";
1062 Name->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001063 }
1064};
1065
1066class VectorType final : public Node {
1067 const Node *BaseType;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001068 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001069
1070public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001071 VectorType(const Node *BaseType_, const Node *Dimension_)
1072 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001073
1074 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }
1075
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001076 void printLeft(OutputBuffer &OB) const override {
1077 BaseType->print(OB);
1078 OB += " vector[";
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001079 if (Dimension)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001080 Dimension->print(OB);
1081 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001082 }
1083};
1084
1085class PixelVectorType final : public Node {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001086 const Node *Dimension;
Richard Smithc20d1442018-08-20 20:14:49 +00001087
1088public:
Erik Pilkingtond7555e32019-11-04 10:47:44 -08001089 PixelVectorType(const Node *Dimension_)
Richard Smithc20d1442018-08-20 20:14:49 +00001090 : Node(KPixelVectorType), Dimension(Dimension_) {}
1091
1092 template<typename Fn> void match(Fn F) const { F(Dimension); }
1093
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001094 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001095 // FIXME: This should demangle as "vector pixel".
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001096 OB += "pixel vector[";
1097 Dimension->print(OB);
1098 OB += "]";
Richard Smithc20d1442018-08-20 20:14:49 +00001099 }
1100};
1101
Pengfei Wang50e90b82021-09-23 11:02:25 +08001102class BinaryFPType final : public Node {
1103 const Node *Dimension;
1104
1105public:
1106 BinaryFPType(const Node *Dimension_)
1107 : Node(KBinaryFPType), Dimension(Dimension_) {}
1108
1109 template<typename Fn> void match(Fn F) const { F(Dimension); }
1110
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001111 void printLeft(OutputBuffer &OB) const override {
1112 OB += "_Float";
1113 Dimension->print(OB);
Pengfei Wang50e90b82021-09-23 11:02:25 +08001114 }
1115};
1116
Richard Smithdf1c14c2019-09-06 23:53:21 +00001117enum class TemplateParamKind { Type, NonType, Template };
1118
1119/// An invented name for a template parameter for which we don't have a
1120/// corresponding template argument.
1121///
1122/// This node is created when parsing the <lambda-sig> for a lambda with
1123/// explicit template arguments, which might be referenced in the parameter
1124/// types appearing later in the <lambda-sig>.
1125class SyntheticTemplateParamName final : public Node {
1126 TemplateParamKind Kind;
1127 unsigned Index;
1128
1129public:
1130 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)
1131 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}
1132
1133 template<typename Fn> void match(Fn F) const { F(Kind, Index); }
1134
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001135 void printLeft(OutputBuffer &OB) const override {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001136 switch (Kind) {
1137 case TemplateParamKind::Type:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001138 OB += "$T";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001139 break;
1140 case TemplateParamKind::NonType:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001141 OB += "$N";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001142 break;
1143 case TemplateParamKind::Template:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001144 OB += "$TT";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001145 break;
1146 }
1147 if (Index > 0)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001148 OB << Index - 1;
Richard Smithdf1c14c2019-09-06 23:53:21 +00001149 }
1150};
1151
1152/// A template type parameter declaration, 'typename T'.
1153class TypeTemplateParamDecl final : public Node {
1154 Node *Name;
1155
1156public:
1157 TypeTemplateParamDecl(Node *Name_)
1158 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}
1159
1160 template<typename Fn> void match(Fn F) const { F(Name); }
1161
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001162 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001163
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001164 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001165};
1166
1167/// A non-type template parameter declaration, 'int N'.
1168class NonTypeTemplateParamDecl final : public Node {
1169 Node *Name;
1170 Node *Type;
1171
1172public:
1173 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)
1174 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}
1175
1176 template<typename Fn> void match(Fn F) const { F(Name, Type); }
1177
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001178 void printLeft(OutputBuffer &OB) const override {
1179 Type->printLeft(OB);
1180 if (!Type->hasRHSComponent(OB))
1181 OB += " ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001182 }
1183
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001184 void printRight(OutputBuffer &OB) const override {
1185 Name->print(OB);
1186 Type->printRight(OB);
Richard Smithdf1c14c2019-09-06 23:53:21 +00001187 }
1188};
1189
1190/// A template template parameter declaration,
1191/// 'template<typename T> typename N'.
1192class TemplateTemplateParamDecl final : public Node {
1193 Node *Name;
1194 NodeArray Params;
1195
1196public:
1197 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
1198 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1199 Params(Params_) {}
1200
1201 template<typename Fn> void match(Fn F) const { F(Name, Params); }
1202
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001203 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001204 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001205 OB += "template<";
1206 Params.printWithComma(OB);
1207 OB += "> typename ";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001208 }
1209
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001210 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001211};
1212
1213/// A template parameter pack declaration, 'typename ...T'.
1214class TemplateParamPackDecl final : public Node {
1215 Node *Param;
1216
1217public:
1218 TemplateParamPackDecl(Node *Param_)
1219 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}
1220
1221 template<typename Fn> void match(Fn F) const { F(Param); }
1222
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001223 void printLeft(OutputBuffer &OB) const override {
1224 Param->printLeft(OB);
1225 OB += "...";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001226 }
1227
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001228 void printRight(OutputBuffer &OB) const override { Param->printRight(OB); }
Richard Smithdf1c14c2019-09-06 23:53:21 +00001229};
1230
Richard Smithc20d1442018-08-20 20:14:49 +00001231/// An unexpanded parameter pack (either in the expression or type context). If
1232/// this AST is correct, this node will have a ParameterPackExpansion node above
1233/// it.
1234///
1235/// This node is created when some <template-args> are found that apply to an
1236/// <encoding>, and is stored in the TemplateParams table. In order for this to
1237/// appear in the final AST, it has to referenced via a <template-param> (ie,
1238/// T_).
1239class ParameterPack final : public Node {
1240 NodeArray Data;
1241
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08001242 // Setup OutputBuffer for a pack expansion, unless we're already expanding
1243 // one.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001244 void initializePackExpansion(OutputBuffer &OB) const {
1245 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {
1246 OB.CurrentPackMax = static_cast<unsigned>(Data.size());
1247 OB.CurrentPackIndex = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00001248 }
1249 }
1250
1251public:
1252 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {
1253 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;
1254 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1255 return P->ArrayCache == Cache::No;
1256 }))
1257 ArrayCache = Cache::No;
1258 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1259 return P->FunctionCache == Cache::No;
1260 }))
1261 FunctionCache = Cache::No;
1262 if (std::all_of(Data.begin(), Data.end(), [](Node* P) {
1263 return P->RHSComponentCache == Cache::No;
1264 }))
1265 RHSComponentCache = Cache::No;
1266 }
1267
1268 template<typename Fn> void match(Fn F) const { F(Data); }
1269
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001270 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
1271 initializePackExpansion(OB);
1272 size_t Idx = OB.CurrentPackIndex;
1273 return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001274 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001275 bool hasArraySlow(OutputBuffer &OB) const override {
1276 initializePackExpansion(OB);
1277 size_t Idx = OB.CurrentPackIndex;
1278 return Idx < Data.size() && Data[Idx]->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001279 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001280 bool hasFunctionSlow(OutputBuffer &OB) const override {
1281 initializePackExpansion(OB);
1282 size_t Idx = OB.CurrentPackIndex;
1283 return Idx < Data.size() && Data[Idx]->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001284 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001285 const Node *getSyntaxNode(OutputBuffer &OB) const override {
1286 initializePackExpansion(OB);
1287 size_t Idx = OB.CurrentPackIndex;
1288 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;
Richard Smithc20d1442018-08-20 20:14:49 +00001289 }
1290
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001291 void printLeft(OutputBuffer &OB) const override {
1292 initializePackExpansion(OB);
1293 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001294 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001295 Data[Idx]->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001296 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001297 void printRight(OutputBuffer &OB) const override {
1298 initializePackExpansion(OB);
1299 size_t Idx = OB.CurrentPackIndex;
Richard Smithc20d1442018-08-20 20:14:49 +00001300 if (Idx < Data.size())
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001301 Data[Idx]->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001302 }
1303};
1304
1305/// A variadic template argument. This node represents an occurrence of
1306/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1307/// one of it's Elements is. The parser inserts a ParameterPack into the
1308/// TemplateParams table if the <template-args> this pack belongs to apply to an
1309/// <encoding>.
1310class TemplateArgumentPack final : public Node {
1311 NodeArray Elements;
1312public:
1313 TemplateArgumentPack(NodeArray Elements_)
1314 : Node(KTemplateArgumentPack), Elements(Elements_) {}
1315
1316 template<typename Fn> void match(Fn F) const { F(Elements); }
1317
1318 NodeArray getElements() const { return Elements; }
1319
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001320 void printLeft(OutputBuffer &OB) const override {
1321 Elements.printWithComma(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001322 }
1323};
1324
1325/// A pack expansion. Below this node, there are some unexpanded ParameterPacks
1326/// which each have Child->ParameterPackSize elements.
1327class ParameterPackExpansion final : public Node {
1328 const Node *Child;
1329
1330public:
1331 ParameterPackExpansion(const Node *Child_)
1332 : Node(KParameterPackExpansion), Child(Child_) {}
1333
1334 template<typename Fn> void match(Fn F) const { F(Child); }
1335
1336 const Node *getChild() const { return Child; }
1337
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001338 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001339 constexpr unsigned Max = std::numeric_limits<unsigned>::max();
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001340 ScopedOverride<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);
1341 ScopedOverride<unsigned> SavePackMax(OB.CurrentPackMax, Max);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001342 size_t StreamPos = OB.getCurrentPosition();
Richard Smithc20d1442018-08-20 20:14:49 +00001343
1344 // Print the first element in the pack. If Child contains a ParameterPack,
1345 // it will set up S.CurrentPackMax and print the first element.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001346 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001347
1348 // No ParameterPack was found in Child. This can occur if we've found a pack
1349 // expansion on a <function-param>.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001350 if (OB.CurrentPackMax == Max) {
1351 OB += "...";
Richard Smithc20d1442018-08-20 20:14:49 +00001352 return;
1353 }
1354
1355 // We found a ParameterPack, but it has no elements. Erase whatever we may
1356 // of printed.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001357 if (OB.CurrentPackMax == 0) {
1358 OB.setCurrentPosition(StreamPos);
Richard Smithc20d1442018-08-20 20:14:49 +00001359 return;
1360 }
1361
1362 // Else, iterate through the rest of the elements in the pack.
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001363 for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {
1364 OB += ", ";
1365 OB.CurrentPackIndex = I;
1366 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001367 }
1368 }
1369};
1370
1371class TemplateArgs final : public Node {
1372 NodeArray Params;
1373
1374public:
1375 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
1376
1377 template<typename Fn> void match(Fn F) const { F(Params); }
1378
1379 NodeArray getParams() { return Params; }
1380
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001381 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001382 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001383 OB += "<";
1384 Params.printWithComma(OB);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001385 OB += ">";
Richard Smithc20d1442018-08-20 20:14:49 +00001386 }
1387};
1388
Richard Smithb485b352018-08-24 23:30:26 +00001389/// A forward-reference to a template argument that was not known at the point
1390/// where the template parameter name was parsed in a mangling.
1391///
1392/// This is created when demangling the name of a specialization of a
1393/// conversion function template:
1394///
1395/// \code
1396/// struct A {
1397/// template<typename T> operator T*();
1398/// };
1399/// \endcode
1400///
1401/// When demangling a specialization of the conversion function template, we
1402/// encounter the name of the template (including the \c T) before we reach
1403/// the template argument list, so we cannot substitute the parameter name
1404/// for the corresponding argument while parsing. Instead, we create a
1405/// \c ForwardTemplateReference node that is resolved after we parse the
1406/// template arguments.
Richard Smithc20d1442018-08-20 20:14:49 +00001407struct ForwardTemplateReference : Node {
1408 size_t Index;
1409 Node *Ref = nullptr;
1410
1411 // If we're currently printing this node. It is possible (though invalid) for
1412 // a forward template reference to refer to itself via a substitution. This
1413 // creates a cyclic AST, which will stack overflow printing. To fix this, bail
1414 // out if more than one print* function is active.
1415 mutable bool Printing = false;
1416
1417 ForwardTemplateReference(size_t Index_)
1418 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
1419 Cache::Unknown),
1420 Index(Index_) {}
1421
1422 // We don't provide a matcher for these, because the value of the node is
1423 // not determined by its construction parameters, and it generally needs
1424 // special handling.
1425 template<typename Fn> void match(Fn F) const = delete;
1426
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001427 bool hasRHSComponentSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001428 if (Printing)
1429 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001430 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001431 return Ref->hasRHSComponent(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001432 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001433 bool hasArraySlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001434 if (Printing)
1435 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001436 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001437 return Ref->hasArray(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001438 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001439 bool hasFunctionSlow(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001440 if (Printing)
1441 return false;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001442 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001443 return Ref->hasFunction(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001444 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001445 const Node *getSyntaxNode(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001446 if (Printing)
1447 return this;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001448 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001449 return Ref->getSyntaxNode(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001450 }
1451
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001452 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001453 if (Printing)
1454 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001455 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001456 Ref->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001457 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001458 void printRight(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001459 if (Printing)
1460 return;
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001461 ScopedOverride<bool> SavePrinting(Printing, true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001462 Ref->printRight(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001463 }
1464};
1465
1466struct NameWithTemplateArgs : Node {
1467 // name<template_args>
1468 Node *Name;
1469 Node *TemplateArgs;
1470
1471 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)
1472 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}
1473
1474 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }
1475
1476 StringView getBaseName() const override { return Name->getBaseName(); }
1477
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001478 void printLeft(OutputBuffer &OB) const override {
1479 Name->print(OB);
1480 TemplateArgs->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001481 }
1482};
1483
1484class GlobalQualifiedName final : public Node {
1485 Node *Child;
1486
1487public:
1488 GlobalQualifiedName(Node* Child_)
1489 : Node(KGlobalQualifiedName), Child(Child_) {}
1490
1491 template<typename Fn> void match(Fn F) const { F(Child); }
1492
1493 StringView getBaseName() const override { return Child->getBaseName(); }
1494
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001495 void printLeft(OutputBuffer &OB) const override {
1496 OB += "::";
1497 Child->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001498 }
1499};
1500
Richard Smithc20d1442018-08-20 20:14:49 +00001501enum class SpecialSubKind {
1502 allocator,
1503 basic_string,
1504 string,
1505 istream,
1506 ostream,
1507 iostream,
1508};
1509
Nathan Sidwell28201492022-03-28 12:55:45 -07001510class SpecialSubstitution;
1511class ExpandedSpecialSubstitution : public Node {
1512protected:
Richard Smithc20d1442018-08-20 20:14:49 +00001513 SpecialSubKind SSK;
1514
Nathan Sidwell28201492022-03-28 12:55:45 -07001515 ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)
1516 : Node(K_), SSK(SSK_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001517public:
1518 ExpandedSpecialSubstitution(SpecialSubKind SSK_)
Nathan Sidwell28201492022-03-28 12:55:45 -07001519 : ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}
1520 inline ExpandedSpecialSubstitution(SpecialSubstitution const *);
Richard Smithc20d1442018-08-20 20:14:49 +00001521
1522 template<typename Fn> void match(Fn F) const { F(SSK); }
1523
Nathan Sidwell28201492022-03-28 12:55:45 -07001524protected:
1525 bool isInstantiation() const {
1526 return unsigned(SSK) >= unsigned(SpecialSubKind::string);
1527 }
1528
Richard Smithc20d1442018-08-20 20:14:49 +00001529 StringView getBaseName() const override {
1530 switch (SSK) {
1531 case SpecialSubKind::allocator:
1532 return StringView("allocator");
1533 case SpecialSubKind::basic_string:
1534 return StringView("basic_string");
1535 case SpecialSubKind::string:
1536 return StringView("basic_string");
1537 case SpecialSubKind::istream:
1538 return StringView("basic_istream");
1539 case SpecialSubKind::ostream:
1540 return StringView("basic_ostream");
1541 case SpecialSubKind::iostream:
1542 return StringView("basic_iostream");
1543 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00001544 DEMANGLE_UNREACHABLE;
Richard Smithc20d1442018-08-20 20:14:49 +00001545 }
1546
Nathan Sidwell28201492022-03-28 12:55:45 -07001547private:
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001548 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell28201492022-03-28 12:55:45 -07001549 OB << "std::" << getBaseName();
1550 if (isInstantiation()) {
1551 OB << "<char, std::char_traits<char>";
1552 if (SSK == SpecialSubKind::string)
1553 OB << ", std::allocator<char>";
1554 OB << ">";
Richard Smithc20d1442018-08-20 20:14:49 +00001555 }
1556 }
1557};
1558
Nathan Sidwell28201492022-03-28 12:55:45 -07001559class SpecialSubstitution final : public ExpandedSpecialSubstitution {
Richard Smithc20d1442018-08-20 20:14:49 +00001560public:
Richard Smithc20d1442018-08-20 20:14:49 +00001561 SpecialSubstitution(SpecialSubKind SSK_)
Nathan Sidwell28201492022-03-28 12:55:45 -07001562 : ExpandedSpecialSubstitution(SSK_, KSpecialSubstitution) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001563
1564 template<typename Fn> void match(Fn F) const { F(SSK); }
1565
1566 StringView getBaseName() const override {
Nathan Sidwell28201492022-03-28 12:55:45 -07001567 auto SV = ExpandedSpecialSubstitution::getBaseName ();
1568 if (isInstantiation()) {
1569 // The instantiations are typedefs that drop the "basic_" prefix.
1570 assert(SV.startsWith("basic_"));
1571 SV = SV.dropFront(sizeof("basic_") - 1);
Richard Smithc20d1442018-08-20 20:14:49 +00001572 }
Nathan Sidwell28201492022-03-28 12:55:45 -07001573 return SV;
Richard Smithc20d1442018-08-20 20:14:49 +00001574 }
1575
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001576 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell28201492022-03-28 12:55:45 -07001577 OB << "std::" << getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001578 }
1579};
1580
Nathan Sidwell28201492022-03-28 12:55:45 -07001581inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(
1582 SpecialSubstitution const *SS)
1583 : ExpandedSpecialSubstitution(SS->SSK) {}
1584
Richard Smithc20d1442018-08-20 20:14:49 +00001585class CtorDtorName final : public Node {
1586 const Node *Basename;
1587 const bool IsDtor;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001588 const int Variant;
Richard Smithc20d1442018-08-20 20:14:49 +00001589
1590public:
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001591 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)
1592 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),
1593 Variant(Variant_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001594
Pavel Labathf4e67eb2018-10-10 08:39:16 +00001595 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }
Richard Smithc20d1442018-08-20 20:14:49 +00001596
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001597 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001598 if (IsDtor)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001599 OB += "~";
1600 OB += Basename->getBaseName();
Richard Smithc20d1442018-08-20 20:14:49 +00001601 }
1602};
1603
1604class DtorName : public Node {
1605 const Node *Base;
1606
1607public:
1608 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}
1609
1610 template<typename Fn> void match(Fn F) const { F(Base); }
1611
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001612 void printLeft(OutputBuffer &OB) const override {
1613 OB += "~";
1614 Base->printLeft(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001615 }
1616};
1617
1618class UnnamedTypeName : public Node {
1619 const StringView Count;
1620
1621public:
1622 UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}
1623
1624 template<typename Fn> void match(Fn F) const { F(Count); }
1625
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001626 void printLeft(OutputBuffer &OB) const override {
1627 OB += "'unnamed";
1628 OB += Count;
1629 OB += "\'";
Richard Smithc20d1442018-08-20 20:14:49 +00001630 }
1631};
1632
1633class ClosureTypeName : public Node {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001634 NodeArray TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00001635 NodeArray Params;
1636 StringView Count;
1637
1638public:
Richard Smithdf1c14c2019-09-06 23:53:21 +00001639 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1640 StringView Count_)
1641 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1642 Params(Params_), Count(Count_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001643
Richard Smithdf1c14c2019-09-06 23:53:21 +00001644 template<typename Fn> void match(Fn F) const {
1645 F(TemplateParams, Params, Count);
1646 }
1647
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001648 void printDeclarator(OutputBuffer &OB) const {
Richard Smithdf1c14c2019-09-06 23:53:21 +00001649 if (!TemplateParams.empty()) {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001650 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001651 OB += "<";
1652 TemplateParams.printWithComma(OB);
1653 OB += ">";
Richard Smithdf1c14c2019-09-06 23:53:21 +00001654 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001655 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001656 Params.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001657 OB.printClose();
Richard Smithdf1c14c2019-09-06 23:53:21 +00001658 }
Richard Smithc20d1442018-08-20 20:14:49 +00001659
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001660 void printLeft(OutputBuffer &OB) const override {
1661 OB += "\'lambda";
1662 OB += Count;
1663 OB += "\'";
1664 printDeclarator(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001665 }
1666};
1667
1668class StructuredBindingName : public Node {
1669 NodeArray Bindings;
1670public:
1671 StructuredBindingName(NodeArray Bindings_)
1672 : Node(KStructuredBindingName), Bindings(Bindings_) {}
1673
1674 template<typename Fn> void match(Fn F) const { F(Bindings); }
1675
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001676 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001677 OB.printOpen('[');
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001678 Bindings.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001679 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001680 }
1681};
1682
1683// -- Expression Nodes --
1684
1685class BinaryExpr : public Node {
1686 const Node *LHS;
1687 const StringView InfixOperator;
1688 const Node *RHS;
1689
1690public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001691 BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_,
1692 Prec Prec_)
1693 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),
1694 RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001695
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001696 template <typename Fn> void match(Fn F) const {
1697 F(LHS, InfixOperator, RHS, getPrecedence());
1698 }
Richard Smithc20d1442018-08-20 20:14:49 +00001699
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001700 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell18505102022-03-25 04:34:19 -07001701 bool ParenAll = OB.isGtInsideTemplateArgs() &&
1702 (InfixOperator == ">" || InfixOperator == ">>");
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001703 if (ParenAll)
1704 OB.printOpen();
1705 // Assignment is right associative, with special LHS precedence.
1706 bool IsAssign = getPrecedence() == Prec::Assign;
1707 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);
1708 // No space before comma operator
1709 if (!(InfixOperator == ","))
1710 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001711 OB += InfixOperator;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001712 OB += " ";
1713 RHS->printAsOperand(OB, getPrecedence(), IsAssign);
1714 if (ParenAll)
1715 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001716 }
1717};
1718
1719class ArraySubscriptExpr : public Node {
1720 const Node *Op1;
1721 const Node *Op2;
1722
1723public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001724 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)
1725 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001726
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001727 template <typename Fn> void match(Fn F) const {
1728 F(Op1, Op2, getPrecedence());
1729 }
Richard Smithc20d1442018-08-20 20:14:49 +00001730
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001731 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001732 Op1->printAsOperand(OB, getPrecedence());
1733 OB.printOpen('[');
1734 Op2->printAsOperand(OB);
1735 OB.printClose(']');
Richard Smithc20d1442018-08-20 20:14:49 +00001736 }
1737};
1738
1739class PostfixExpr : public Node {
1740 const Node *Child;
1741 const StringView Operator;
1742
1743public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001744 PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_)
1745 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001746
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001747 template <typename Fn> void match(Fn F) const {
1748 F(Child, Operator, getPrecedence());
1749 }
Richard Smithc20d1442018-08-20 20:14:49 +00001750
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001751 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001752 Child->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001753 OB += Operator;
Richard Smithc20d1442018-08-20 20:14:49 +00001754 }
1755};
1756
1757class ConditionalExpr : public Node {
1758 const Node *Cond;
1759 const Node *Then;
1760 const Node *Else;
1761
1762public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001763 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,
1764 Prec Prec_)
1765 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001766
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001767 template <typename Fn> void match(Fn F) const {
1768 F(Cond, Then, Else, getPrecedence());
1769 }
Richard Smithc20d1442018-08-20 20:14:49 +00001770
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001771 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001772 Cond->printAsOperand(OB, getPrecedence());
1773 OB += " ? ";
1774 Then->printAsOperand(OB);
1775 OB += " : ";
1776 Else->printAsOperand(OB, Prec::Assign, true);
Richard Smithc20d1442018-08-20 20:14:49 +00001777 }
1778};
1779
1780class MemberExpr : public Node {
1781 const Node *LHS;
1782 const StringView Kind;
1783 const Node *RHS;
1784
1785public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001786 MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_)
1787 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001788
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001789 template <typename Fn> void match(Fn F) const {
1790 F(LHS, Kind, RHS, getPrecedence());
1791 }
Richard Smithc20d1442018-08-20 20:14:49 +00001792
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001793 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001794 LHS->printAsOperand(OB, getPrecedence(), true);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001795 OB += Kind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001796 RHS->printAsOperand(OB, getPrecedence(), false);
Richard Smithc20d1442018-08-20 20:14:49 +00001797 }
1798};
1799
Richard Smith1865d2f2020-10-22 19:29:36 -07001800class SubobjectExpr : public Node {
1801 const Node *Type;
1802 const Node *SubExpr;
1803 StringView Offset;
1804 NodeArray UnionSelectors;
1805 bool OnePastTheEnd;
1806
1807public:
1808 SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_,
1809 NodeArray UnionSelectors_, bool OnePastTheEnd_)
1810 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),
1811 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}
1812
1813 template<typename Fn> void match(Fn F) const {
1814 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);
1815 }
1816
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001817 void printLeft(OutputBuffer &OB) const override {
1818 SubExpr->print(OB);
1819 OB += ".<";
1820 Type->print(OB);
1821 OB += " at offset ";
Richard Smith1865d2f2020-10-22 19:29:36 -07001822 if (Offset.empty()) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001823 OB += "0";
Richard Smith1865d2f2020-10-22 19:29:36 -07001824 } else if (Offset[0] == 'n') {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001825 OB += "-";
1826 OB += Offset.dropFront();
Richard Smith1865d2f2020-10-22 19:29:36 -07001827 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001828 OB += Offset;
Richard Smith1865d2f2020-10-22 19:29:36 -07001829 }
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001830 OB += ">";
Richard Smith1865d2f2020-10-22 19:29:36 -07001831 }
1832};
1833
Richard Smithc20d1442018-08-20 20:14:49 +00001834class EnclosingExpr : public Node {
1835 const StringView Prefix;
1836 const Node *Infix;
1837 const StringView Postfix;
1838
1839public:
Nathan Sidwelle9c9bdf2022-03-29 06:19:18 -07001840 EnclosingExpr(StringView Prefix_, const Node *Infix_,
1841 Prec Prec_ = Prec::Primary)
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001842 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001843
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001844 template <typename Fn> void match(Fn F) const {
1845 F(Prefix, Infix, getPrecedence());
1846 }
Richard Smithc20d1442018-08-20 20:14:49 +00001847
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001848 void printLeft(OutputBuffer &OB) const override {
1849 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001850 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001851 Infix->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001852 OB.printClose();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001853 OB += Postfix;
Richard Smithc20d1442018-08-20 20:14:49 +00001854 }
1855};
1856
1857class CastExpr : public Node {
1858 // cast_kind<to>(from)
1859 const StringView CastKind;
1860 const Node *To;
1861 const Node *From;
1862
1863public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001864 CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_)
1865 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001866
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001867 template <typename Fn> void match(Fn F) const {
1868 F(CastKind, To, From, getPrecedence());
1869 }
Richard Smithc20d1442018-08-20 20:14:49 +00001870
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001871 void printLeft(OutputBuffer &OB) const override {
1872 OB += CastKind;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001873 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08001874 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001875 OB += "<";
1876 To->printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001877 OB += ">";
1878 }
1879 OB.printOpen();
1880 From->printAsOperand(OB);
1881 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001882 }
1883};
1884
1885class SizeofParamPackExpr : public Node {
1886 const Node *Pack;
1887
1888public:
1889 SizeofParamPackExpr(const Node *Pack_)
1890 : Node(KSizeofParamPackExpr), Pack(Pack_) {}
1891
1892 template<typename Fn> void match(Fn F) const { F(Pack); }
1893
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001894 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001895 OB += "sizeof...";
1896 OB.printOpen();
Richard Smithc20d1442018-08-20 20:14:49 +00001897 ParameterPackExpansion PPE(Pack);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001898 PPE.printLeft(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001899 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001900 }
1901};
1902
1903class CallExpr : public Node {
1904 const Node *Callee;
1905 NodeArray Args;
1906
1907public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001908 CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_)
1909 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001910
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001911 template <typename Fn> void match(Fn F) const {
1912 F(Callee, Args, getPrecedence());
1913 }
Richard Smithc20d1442018-08-20 20:14:49 +00001914
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001915 void printLeft(OutputBuffer &OB) const override {
1916 Callee->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001917 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001918 Args.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001919 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001920 }
1921};
1922
1923class NewExpr : public Node {
1924 // new (expr_list) type(init_list)
1925 NodeArray ExprList;
1926 Node *Type;
1927 NodeArray InitList;
1928 bool IsGlobal; // ::operator new ?
1929 bool IsArray; // new[] ?
1930public:
1931 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001932 bool IsArray_, Prec Prec_)
1933 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),
1934 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001935
1936 template<typename Fn> void match(Fn F) const {
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001937 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00001938 }
1939
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001940 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001941 if (IsGlobal)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001942 OB += "::";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001943 OB += "new";
Richard Smithc20d1442018-08-20 20:14:49 +00001944 if (IsArray)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001945 OB += "[]";
Richard Smithc20d1442018-08-20 20:14:49 +00001946 if (!ExprList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001947 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001948 ExprList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001949 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001950 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001951 OB += " ";
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001952 Type->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001953 if (!InitList.empty()) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001954 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001955 InitList.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001956 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00001957 }
Richard Smithc20d1442018-08-20 20:14:49 +00001958 }
1959};
1960
1961class DeleteExpr : public Node {
1962 Node *Op;
1963 bool IsGlobal;
1964 bool IsArray;
1965
1966public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001967 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)
1968 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),
1969 IsArray(IsArray_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001970
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001971 template <typename Fn> void match(Fn F) const {
1972 F(Op, IsGlobal, IsArray, getPrecedence());
1973 }
Richard Smithc20d1442018-08-20 20:14:49 +00001974
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001975 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00001976 if (IsGlobal)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001977 OB += "::";
1978 OB += "delete";
Richard Smithc20d1442018-08-20 20:14:49 +00001979 if (IsArray)
Nathan Sidwellc69bde22022-01-28 07:09:38 -08001980 OB += "[]";
1981 OB += ' ';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001982 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00001983 }
1984};
1985
1986class PrefixExpr : public Node {
1987 StringView Prefix;
1988 Node *Child;
1989
1990public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08001991 PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_)
1992 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00001993
Nathan Sidwelldafcca22022-03-29 04:43:16 -07001994 template <typename Fn> void match(Fn F) const {
1995 F(Prefix, Child, getPrecedence());
1996 }
Richard Smithc20d1442018-08-20 20:14:49 +00001997
Luís Ferreiraa4380e22021-10-21 17:31:53 -07001998 void printLeft(OutputBuffer &OB) const override {
1999 OB += Prefix;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002000 Child->printAsOperand(OB, getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00002001 }
2002};
2003
2004class FunctionParam : public Node {
2005 StringView Number;
2006
2007public:
2008 FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}
2009
2010 template<typename Fn> void match(Fn F) const { F(Number); }
2011
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002012 void printLeft(OutputBuffer &OB) const override {
2013 OB += "fp";
2014 OB += Number;
Richard Smithc20d1442018-08-20 20:14:49 +00002015 }
2016};
2017
2018class ConversionExpr : public Node {
2019 const Node *Type;
2020 NodeArray Expressions;
2021
2022public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002023 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)
2024 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002025
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002026 template <typename Fn> void match(Fn F) const {
2027 F(Type, Expressions, getPrecedence());
2028 }
Richard Smithc20d1442018-08-20 20:14:49 +00002029
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002030 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002031 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002032 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002033 OB.printClose();
2034 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002035 Expressions.printWithComma(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002036 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002037 }
2038};
2039
Richard Smith1865d2f2020-10-22 19:29:36 -07002040class PointerToMemberConversionExpr : public Node {
2041 const Node *Type;
2042 const Node *SubExpr;
2043 StringView Offset;
2044
2045public:
2046 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002047 StringView Offset_, Prec Prec_)
2048 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),
2049 SubExpr(SubExpr_), Offset(Offset_) {}
Richard Smith1865d2f2020-10-22 19:29:36 -07002050
Nathan Sidwelldafcca22022-03-29 04:43:16 -07002051 template <typename Fn> void match(Fn F) const {
2052 F(Type, SubExpr, Offset, getPrecedence());
2053 }
Richard Smith1865d2f2020-10-22 19:29:36 -07002054
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002055 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002056 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002057 Type->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002058 OB.printClose();
2059 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002060 SubExpr->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002061 OB.printClose();
Richard Smith1865d2f2020-10-22 19:29:36 -07002062 }
2063};
2064
Richard Smithc20d1442018-08-20 20:14:49 +00002065class InitListExpr : public Node {
2066 const Node *Ty;
2067 NodeArray Inits;
2068public:
2069 InitListExpr(const Node *Ty_, NodeArray Inits_)
2070 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}
2071
2072 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }
2073
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002074 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002075 if (Ty)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002076 Ty->print(OB);
2077 OB += '{';
2078 Inits.printWithComma(OB);
2079 OB += '}';
Richard Smithc20d1442018-08-20 20:14:49 +00002080 }
2081};
2082
2083class BracedExpr : public Node {
2084 const Node *Elem;
2085 const Node *Init;
2086 bool IsArray;
2087public:
2088 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)
2089 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}
2090
2091 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }
2092
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002093 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002094 if (IsArray) {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002095 OB += '[';
2096 Elem->print(OB);
2097 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002098 } else {
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002099 OB += '.';
2100 Elem->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002101 }
2102 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002103 OB += " = ";
2104 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002105 }
2106};
2107
2108class BracedRangeExpr : public Node {
2109 const Node *First;
2110 const Node *Last;
2111 const Node *Init;
2112public:
2113 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)
2114 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}
2115
2116 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }
2117
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002118 void printLeft(OutputBuffer &OB) const override {
2119 OB += '[';
2120 First->print(OB);
2121 OB += " ... ";
2122 Last->print(OB);
2123 OB += ']';
Richard Smithc20d1442018-08-20 20:14:49 +00002124 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002125 OB += " = ";
2126 Init->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002127 }
2128};
2129
2130class FoldExpr : public Node {
2131 const Node *Pack, *Init;
2132 StringView OperatorName;
2133 bool IsLeftFold;
2134
2135public:
2136 FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,
2137 const Node *Init_)
2138 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),
2139 IsLeftFold(IsLeftFold_) {}
2140
2141 template<typename Fn> void match(Fn F) const {
2142 F(IsLeftFold, OperatorName, Pack, Init);
2143 }
2144
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002145 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002146 auto PrintPack = [&] {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002147 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002148 ParameterPackExpansion(Pack).print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002149 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002150 };
2151
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002152 OB.printOpen();
2153 // Either '[init op ]... op pack' or 'pack op ...[ op init]'
2154 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'
2155 // Fold expr operands are cast-expressions
2156 if (!IsLeftFold || Init != nullptr) {
2157 // '(init|pack) op '
2158 if (IsLeftFold)
2159 Init->printAsOperand(OB, Prec::Cast, true);
2160 else
2161 PrintPack();
2162 OB << " " << OperatorName << " ";
Richard Smithc20d1442018-08-20 20:14:49 +00002163 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002164 OB << "...";
2165 if (IsLeftFold || Init != nullptr) {
2166 // ' op (init|pack)'
2167 OB << " " << OperatorName << " ";
2168 if (IsLeftFold)
2169 PrintPack();
2170 else
2171 Init->printAsOperand(OB, Prec::Cast, true);
2172 }
2173 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002174 }
2175};
2176
2177class ThrowExpr : public Node {
2178 const Node *Op;
2179
2180public:
2181 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}
2182
2183 template<typename Fn> void match(Fn F) const { F(Op); }
2184
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002185 void printLeft(OutputBuffer &OB) const override {
2186 OB += "throw ";
2187 Op->print(OB);
Richard Smithc20d1442018-08-20 20:14:49 +00002188 }
2189};
2190
2191class BoolExpr : public Node {
2192 bool Value;
2193
2194public:
2195 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}
2196
2197 template<typename Fn> void match(Fn F) const { F(Value); }
2198
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002199 void printLeft(OutputBuffer &OB) const override {
2200 OB += Value ? StringView("true") : StringView("false");
Richard Smithc20d1442018-08-20 20:14:49 +00002201 }
2202};
2203
Richard Smithdf1c14c2019-09-06 23:53:21 +00002204class StringLiteral : public Node {
2205 const Node *Type;
2206
2207public:
2208 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}
2209
2210 template<typename Fn> void match(Fn F) const { F(Type); }
2211
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002212 void printLeft(OutputBuffer &OB) const override {
2213 OB += "\"<";
2214 Type->print(OB);
2215 OB += ">\"";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002216 }
2217};
2218
2219class LambdaExpr : public Node {
2220 const Node *Type;
2221
Richard Smithdf1c14c2019-09-06 23:53:21 +00002222public:
2223 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}
2224
2225 template<typename Fn> void match(Fn F) const { F(Type); }
2226
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002227 void printLeft(OutputBuffer &OB) const override {
2228 OB += "[]";
Richard Smithfb917462019-09-09 22:26:04 +00002229 if (Type->getKind() == KClosureTypeName)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002230 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);
2231 OB += "{...}";
Richard Smithdf1c14c2019-09-06 23:53:21 +00002232 }
2233};
2234
Erik Pilkington0a170f12020-05-13 14:13:37 -04002235class EnumLiteral : public Node {
Richard Smithc20d1442018-08-20 20:14:49 +00002236 // ty(integer)
2237 const Node *Ty;
2238 StringView Integer;
2239
2240public:
Erik Pilkington0a170f12020-05-13 14:13:37 -04002241 EnumLiteral(const Node *Ty_, StringView Integer_)
2242 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
Richard Smithc20d1442018-08-20 20:14:49 +00002243
2244 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
2245
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002246 void printLeft(OutputBuffer &OB) const override {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002247 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002248 Ty->print(OB);
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002249 OB.printClose();
Erik Pilkington0a170f12020-05-13 14:13:37 -04002250
2251 if (Integer[0] == 'n')
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002252 OB << "-" << Integer.dropFront(1);
Erik Pilkington0a170f12020-05-13 14:13:37 -04002253 else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002254 OB << Integer;
Richard Smithc20d1442018-08-20 20:14:49 +00002255 }
2256};
2257
2258class IntegerLiteral : public Node {
2259 StringView Type;
2260 StringView Value;
2261
2262public:
2263 IntegerLiteral(StringView Type_, StringView Value_)
2264 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}
2265
2266 template<typename Fn> void match(Fn F) const { F(Type, Value); }
2267
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002268 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002269 if (Type.size() > 3) {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002270 OB.printOpen();
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002271 OB += Type;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002272 OB.printClose();
Richard Smithc20d1442018-08-20 20:14:49 +00002273 }
2274
2275 if (Value[0] == 'n') {
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002276 OB += '-';
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002277 OB += Value.dropFront(1);
Richard Smithc20d1442018-08-20 20:14:49 +00002278 } else
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002279 OB += Value;
Richard Smithc20d1442018-08-20 20:14:49 +00002280
2281 if (Type.size() <= 3)
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002282 OB += Type;
Richard Smithc20d1442018-08-20 20:14:49 +00002283 }
2284};
2285
2286template <class Float> struct FloatData;
2287
2288namespace float_literal_impl {
2289constexpr Node::Kind getFloatLiteralKind(float *) {
2290 return Node::KFloatLiteral;
2291}
2292constexpr Node::Kind getFloatLiteralKind(double *) {
2293 return Node::KDoubleLiteral;
2294}
2295constexpr Node::Kind getFloatLiteralKind(long double *) {
2296 return Node::KLongDoubleLiteral;
2297}
2298}
2299
2300template <class Float> class FloatLiteralImpl : public Node {
2301 const StringView Contents;
2302
2303 static constexpr Kind KindForClass =
2304 float_literal_impl::getFloatLiteralKind((Float *)nullptr);
2305
2306public:
2307 FloatLiteralImpl(StringView Contents_)
2308 : Node(KindForClass), Contents(Contents_) {}
2309
2310 template<typename Fn> void match(Fn F) const { F(Contents); }
2311
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002312 void printLeft(OutputBuffer &OB) const override {
Richard Smithc20d1442018-08-20 20:14:49 +00002313 const char *first = Contents.begin();
2314 const char *last = Contents.end() + 1;
2315
2316 const size_t N = FloatData<Float>::mangled_size;
2317 if (static_cast<std::size_t>(last - first) > N) {
2318 last = first + N;
2319 union {
2320 Float value;
2321 char buf[sizeof(Float)];
2322 };
2323 const char *t = first;
2324 char *e = buf;
2325 for (; t != last; ++t, ++e) {
2326 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2327 : static_cast<unsigned>(*t - 'a' + 10);
2328 ++t;
2329 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')
2330 : static_cast<unsigned>(*t - 'a' + 10);
2331 *e = static_cast<char>((d1 << 4) + d0);
2332 }
2333#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
2334 std::reverse(buf, e);
2335#endif
2336 char num[FloatData<Float>::max_demangled_size] = {0};
2337 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);
Luís Ferreiraa4380e22021-10-21 17:31:53 -07002338 OB += StringView(num, num + n);
Richard Smithc20d1442018-08-20 20:14:49 +00002339 }
2340 }
2341};
2342
2343using FloatLiteral = FloatLiteralImpl<float>;
2344using DoubleLiteral = FloatLiteralImpl<double>;
2345using LongDoubleLiteral = FloatLiteralImpl<long double>;
2346
2347/// Visit the node. Calls \c F(P), where \c P is the node cast to the
2348/// appropriate derived class.
2349template<typename Fn>
2350void Node::visit(Fn F) const {
2351 switch (K) {
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002352#define NODE(X) \
2353 case K##X: \
2354 return F(static_cast<const X *>(this));
2355#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002356 }
2357 assert(0 && "unknown mangling node kind");
2358}
2359
2360/// Determine the kind of a node from its type.
2361template<typename NodeT> struct NodeKind;
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002362#define NODE(X) \
2363 template <> struct NodeKind<X> { \
2364 static constexpr Node::Kind Kind = Node::K##X; \
2365 static constexpr const char *name() { return #X; } \
Richard Smithc20d1442018-08-20 20:14:49 +00002366 };
Nathan Sidwell8b55cc02022-03-30 05:59:16 -07002367#include "ItaniumNodes.def"
Richard Smithc20d1442018-08-20 20:14:49 +00002368
Pavel Labathba825192018-10-16 14:29:14 +00002369template <typename Derived, typename Alloc> struct AbstractManglingParser {
Richard Smithc20d1442018-08-20 20:14:49 +00002370 const char *First;
2371 const char *Last;
2372
2373 // Name stack, this is used by the parser to hold temporary names that were
2374 // parsed. The parser collapses multiple names into new nodes to construct
2375 // the AST. Once the parser is finished, names.size() == 1.
2376 PODSmallVector<Node *, 32> Names;
2377
2378 // Substitution table. Itanium supports name substitutions as a means of
2379 // compression. The string "S42_" refers to the 44nd entry (base-36) in this
2380 // table.
2381 PODSmallVector<Node *, 32> Subs;
2382
Richard Smithdf1c14c2019-09-06 23:53:21 +00002383 using TemplateParamList = PODSmallVector<Node *, 8>;
2384
2385 class ScopedTemplateParamList {
2386 AbstractManglingParser *Parser;
2387 size_t OldNumTemplateParamLists;
2388 TemplateParamList Params;
2389
2390 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04002391 ScopedTemplateParamList(AbstractManglingParser *TheParser)
2392 : Parser(TheParser),
2393 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {
Richard Smithdf1c14c2019-09-06 23:53:21 +00002394 Parser->TemplateParams.push_back(&Params);
2395 }
2396 ~ScopedTemplateParamList() {
2397 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2398 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2399 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002400 };
2401
Richard Smithc20d1442018-08-20 20:14:49 +00002402 // Template parameter table. Like the above, but referenced like "T42_".
2403 // This has a smaller size compared to Subs and Names because it can be
2404 // stored on the stack.
Richard Smithdf1c14c2019-09-06 23:53:21 +00002405 TemplateParamList OuterTemplateParams;
2406
2407 // Lists of template parameters indexed by template parameter depth,
2408 // referenced like "TL2_4_". If nonempty, element 0 is always
2409 // OuterTemplateParams; inner elements are always template parameter lists of
2410 // lambda expressions. For a generic lambda with no explicit template
2411 // parameter list, the corresponding parameter list pointer will be null.
2412 PODSmallVector<TemplateParamList *, 4> TemplateParams;
Richard Smithc20d1442018-08-20 20:14:49 +00002413
2414 // Set of unresolved forward <template-param> references. These can occur in a
2415 // conversion operator's type, and are resolved in the enclosing <encoding>.
2416 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
2417
Richard Smithc20d1442018-08-20 20:14:49 +00002418 bool TryToParseTemplateArgs = true;
2419 bool PermitForwardTemplateReferences = false;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002420 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
2421
2422 unsigned NumSyntheticTemplateParameters[3] = {};
Richard Smithc20d1442018-08-20 20:14:49 +00002423
2424 Alloc ASTAllocator;
2425
Pavel Labathba825192018-10-16 14:29:14 +00002426 AbstractManglingParser(const char *First_, const char *Last_)
2427 : First(First_), Last(Last_) {}
2428
2429 Derived &getDerived() { return static_cast<Derived &>(*this); }
Richard Smithc20d1442018-08-20 20:14:49 +00002430
2431 void reset(const char *First_, const char *Last_) {
2432 First = First_;
2433 Last = Last_;
2434 Names.clear();
2435 Subs.clear();
2436 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002437 ParsingLambdaParamsAtLevel = (size_t)-1;
Richard Smithc20d1442018-08-20 20:14:49 +00002438 TryToParseTemplateArgs = true;
2439 PermitForwardTemplateReferences = false;
Richard Smith9a2307a2019-09-07 00:11:53 +00002440 for (int I = 0; I != 3; ++I)
2441 NumSyntheticTemplateParameters[I] = 0;
Richard Smithc20d1442018-08-20 20:14:49 +00002442 ASTAllocator.reset();
2443 }
2444
Richard Smithb485b352018-08-24 23:30:26 +00002445 template <class T, class... Args> Node *make(Args &&... args) {
Richard Smithc20d1442018-08-20 20:14:49 +00002446 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);
2447 }
2448
2449 template <class It> NodeArray makeNodeArray(It begin, It end) {
2450 size_t sz = static_cast<size_t>(end - begin);
2451 void *mem = ASTAllocator.allocateNodeArray(sz);
2452 Node **data = new (mem) Node *[sz];
2453 std::copy(begin, end, data);
2454 return NodeArray(data, sz);
2455 }
2456
2457 NodeArray popTrailingNodeArray(size_t FromPosition) {
2458 assert(FromPosition <= Names.size());
2459 NodeArray res =
2460 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2461 Names.dropBack(FromPosition);
2462 return res;
2463 }
2464
2465 bool consumeIf(StringView S) {
2466 if (StringView(First, Last).startsWith(S)) {
2467 First += S.size();
2468 return true;
2469 }
2470 return false;
2471 }
2472
2473 bool consumeIf(char C) {
2474 if (First != Last && *First == C) {
2475 ++First;
2476 return true;
2477 }
2478 return false;
2479 }
2480
2481 char consume() { return First != Last ? *First++ : '\0'; }
2482
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08002483 char look(unsigned Lookahead = 0) const {
Richard Smithc20d1442018-08-20 20:14:49 +00002484 if (static_cast<size_t>(Last - First) <= Lookahead)
2485 return '\0';
2486 return First[Lookahead];
2487 }
2488
2489 size_t numLeft() const { return static_cast<size_t>(Last - First); }
2490
2491 StringView parseNumber(bool AllowNegative = false);
2492 Qualifiers parseCVQualifiers();
2493 bool parsePositiveInteger(size_t *Out);
2494 StringView parseBareSourceName();
2495
2496 bool parseSeqId(size_t *Out);
2497 Node *parseSubstitution();
2498 Node *parseTemplateParam();
Richard Smithdf1c14c2019-09-06 23:53:21 +00002499 Node *parseTemplateParamDecl();
Richard Smithc20d1442018-08-20 20:14:49 +00002500 Node *parseTemplateArgs(bool TagTemplates = false);
2501 Node *parseTemplateArg();
2502
2503 /// Parse the <expr> production.
2504 Node *parseExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002505 Node *parsePrefixExpr(StringView Kind, Node::Prec Prec);
2506 Node *parseBinaryExpr(StringView Kind, Node::Prec Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00002507 Node *parseIntegerLiteral(StringView Lit);
2508 Node *parseExprPrimary();
2509 template <class Float> Node *parseFloatingLiteral();
2510 Node *parseFunctionParam();
Richard Smithc20d1442018-08-20 20:14:49 +00002511 Node *parseConversionExpr();
2512 Node *parseBracedExpr();
2513 Node *parseFoldExpr();
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002514 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07002515 Node *parseSubobjectExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00002516
2517 /// Parse the <type> production.
2518 Node *parseType();
2519 Node *parseFunctionType();
2520 Node *parseVectorType();
2521 Node *parseDecltype();
2522 Node *parseArrayType();
2523 Node *parsePointerToMemberType();
2524 Node *parseClassEnumType();
2525 Node *parseQualifiedType();
2526
2527 Node *parseEncoding();
2528 bool parseCallOffset();
2529 Node *parseSpecialName();
2530
2531 /// Holds some extra information about a <name> that is being parsed. This
2532 /// information is only pertinent if the <name> refers to an <encoding>.
2533 struct NameState {
2534 bool CtorDtorConversion = false;
2535 bool EndsWithTemplateArgs = false;
2536 Qualifiers CVQualifiers = QualNone;
2537 FunctionRefQual ReferenceQualifier = FrefQualNone;
2538 size_t ForwardTemplateRefsBegin;
2539
Pavel Labathba825192018-10-16 14:29:14 +00002540 NameState(AbstractManglingParser *Enclosing)
Richard Smithc20d1442018-08-20 20:14:49 +00002541 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
2542 };
2543
2544 bool resolveForwardTemplateRefs(NameState &State) {
2545 size_t I = State.ForwardTemplateRefsBegin;
2546 size_t E = ForwardTemplateRefs.size();
2547 for (; I < E; ++I) {
2548 size_t Idx = ForwardTemplateRefs[I]->Index;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002549 if (TemplateParams.empty() || !TemplateParams[0] ||
2550 Idx >= TemplateParams[0]->size())
Richard Smithc20d1442018-08-20 20:14:49 +00002551 return true;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002552 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
Richard Smithc20d1442018-08-20 20:14:49 +00002553 }
2554 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2555 return false;
2556 }
2557
2558 /// Parse the <name> production>
2559 Node *parseName(NameState *State = nullptr);
2560 Node *parseLocalName(NameState *State);
2561 Node *parseOperatorName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002562 bool parseModuleNameOpt(ModuleName *&Module);
2563 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);
Richard Smithc20d1442018-08-20 20:14:49 +00002564 Node *parseUnnamedTypeName(NameState *State);
2565 Node *parseSourceName(NameState *State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002566 Node *parseUnscopedName(NameState *State, bool *isSubstName);
Richard Smithc20d1442018-08-20 20:14:49 +00002567 Node *parseNestedName(NameState *State);
2568 Node *parseCtorDtorName(Node *&SoFar, NameState *State);
2569
2570 Node *parseAbiTags(Node *N);
2571
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002572 struct OperatorInfo {
2573 enum OIKind : unsigned char {
2574 Prefix, // Prefix unary: @ expr
2575 Postfix, // Postfix unary: expr @
2576 Binary, // Binary: lhs @ rhs
2577 Array, // Array index: lhs [ rhs ]
2578 Member, // Member access: lhs @ rhs
2579 New, // New
2580 Del, // Delete
2581 Call, // Function call: expr (expr*)
2582 CCast, // C cast: (type)expr
2583 Conditional, // Conditional: expr ? expr : expr
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08002584 NameOnly, // Overload only, not allowed in expression.
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002585 // Below do not have operator names
2586 NamedCast, // Named cast, @<type>(expr)
2587 OfIdOp, // alignof, sizeof, typeid
2588
2589 Unnameable = NamedCast,
2590 };
2591 char Enc[2]; // Encoding
2592 OIKind Kind; // Kind of operator
2593 bool Flag : 1; // Entry-specific flag
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002594 Node::Prec Prec : 7; // Precedence
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002595 const char *Name; // Spelling
2596
2597 public:
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002598 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,
2599 const char *N)
2600 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002601
2602 public:
2603 bool operator<(const OperatorInfo &Other) const {
2604 return *this < Other.Enc;
2605 }
2606 bool operator<(const char *Peek) const {
2607 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);
2608 }
2609 bool operator==(const char *Peek) const {
2610 return Enc[0] == Peek[0] && Enc[1] == Peek[1];
2611 }
2612 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }
2613
2614 public:
2615 StringView getSymbol() const {
2616 StringView Res = Name;
2617 if (Kind < Unnameable) {
2618 assert(Res.startsWith("operator") &&
2619 "operator name does not start with 'operator'");
2620 Res = Res.dropFront(sizeof("operator") - 1);
2621 Res.consumeFront(' ');
2622 }
2623 return Res;
2624 }
2625 StringView getName() const { return Name; }
2626 OIKind getKind() const { return Kind; }
2627 bool getFlag() const { return Flag; }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08002628 Node::Prec getPrecedence() const { return Prec; }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002629 };
Nathan Sidwell7d9bbeb2022-04-08 06:55:31 -07002630 static const OperatorInfo Ops[];
2631 static const size_t NumOps;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08002632 const OperatorInfo *parseOperatorEncoding();
2633
Richard Smithc20d1442018-08-20 20:14:49 +00002634 /// Parse the <unresolved-name> production.
Nathan Sidwell77c52e22022-01-28 11:59:03 -08002635 Node *parseUnresolvedName(bool Global);
Richard Smithc20d1442018-08-20 20:14:49 +00002636 Node *parseSimpleId();
2637 Node *parseBaseUnresolvedName();
2638 Node *parseUnresolvedType();
2639 Node *parseDestructorName();
2640
2641 /// Top-level entry point into the parser.
2642 Node *parse();
2643};
2644
2645const char* parse_discriminator(const char* first, const char* last);
2646
2647// <name> ::= <nested-name> // N
2648// ::= <local-name> # See Scope Encoding below // Z
2649// ::= <unscoped-template-name> <template-args>
2650// ::= <unscoped-name>
2651//
2652// <unscoped-template-name> ::= <unscoped-name>
2653// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00002654template <typename Derived, typename Alloc>
2655Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002656 if (look() == 'N')
Pavel Labathba825192018-10-16 14:29:14 +00002657 return getDerived().parseNestedName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002658 if (look() == 'Z')
Pavel Labathba825192018-10-16 14:29:14 +00002659 return getDerived().parseLocalName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002660
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002661 Node *Result = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002662 bool IsSubst = false;
2663
2664 Result = getDerived().parseUnscopedName(State, &IsSubst);
2665 if (!Result)
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002666 return nullptr;
2667
2668 if (look() == 'I') {
2669 // ::= <unscoped-template-name> <template-args>
2670 if (!IsSubst)
2671 // An unscoped-template-name is substitutable.
2672 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00002673 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00002674 if (TA == nullptr)
2675 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002676 if (State)
2677 State->EndsWithTemplateArgs = true;
2678 Result = make<NameWithTemplateArgs>(Result, TA);
2679 } else if (IsSubst) {
2680 // The substitution case must be followed by <template-args>.
2681 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00002682 }
2683
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002684 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00002685}
2686
2687// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
2688// := Z <function encoding> E s [<discriminator>]
2689// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>
Pavel Labathba825192018-10-16 14:29:14 +00002690template <typename Derived, typename Alloc>
2691Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00002692 if (!consumeIf('Z'))
2693 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002694 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00002695 if (Encoding == nullptr || !consumeIf('E'))
2696 return nullptr;
2697
2698 if (consumeIf('s')) {
2699 First = parse_discriminator(First, Last);
Richard Smithb485b352018-08-24 23:30:26 +00002700 auto *StringLitName = make<NameType>("string literal");
2701 if (!StringLitName)
2702 return nullptr;
2703 return make<LocalName>(Encoding, StringLitName);
Richard Smithc20d1442018-08-20 20:14:49 +00002704 }
2705
2706 if (consumeIf('d')) {
2707 parseNumber(true);
2708 if (!consumeIf('_'))
2709 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00002710 Node *N = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002711 if (N == nullptr)
2712 return nullptr;
2713 return make<LocalName>(Encoding, N);
2714 }
2715
Pavel Labathba825192018-10-16 14:29:14 +00002716 Node *Entity = getDerived().parseName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002717 if (Entity == nullptr)
2718 return nullptr;
2719 First = parse_discriminator(First, Last);
2720 return make<LocalName>(Encoding, Entity);
2721}
2722
Nathan Sidwellac492da2022-04-05 09:25:47 -07002723// <unscoped-name> ::= <unqualified-name>
2724// ::= St <unqualified-name> # ::std::
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08002725// [*] extension
Pavel Labathba825192018-10-16 14:29:14 +00002726template <typename Derived, typename Alloc>
2727Node *
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002728AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2729 bool *IsSubst) {
2730
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002731 Node *Std = nullptr;
2732 if (consumeIf("St")) {
2733 Std = make<NameType>("std");
2734 if (Std == nullptr)
Nathan Sidwell200e97c2022-01-21 11:37:01 -08002735 return nullptr;
2736 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08002737
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002738 Node *Res = nullptr;
2739 ModuleName *Module = nullptr;
2740 if (look() == 'S') {
2741 Node *S = getDerived().parseSubstitution();
2742 if (!S)
2743 return nullptr;
2744 if (S->getKind() == Node::KModuleName)
2745 Module = static_cast<ModuleName *>(S);
2746 else if (IsSubst && Std == nullptr) {
2747 Res = S;
2748 *IsSubst = true;
2749 } else {
2750 return nullptr;
2751 }
2752 }
2753
Nathan Sidwellac492da2022-04-05 09:25:47 -07002754 if (Res == nullptr || Std != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002755 Res = getDerived().parseUnqualifiedName(State, Std, Module);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002756 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002757
2758 return Res;
Richard Smithc20d1442018-08-20 20:14:49 +00002759}
2760
Nathan Sidwellac492da2022-04-05 09:25:47 -07002761// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002762// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
Nathan Sidwellac492da2022-04-05 09:25:47 -07002763// ::= [<module-name>] L? <source-name> [<abi-tags>]
2764// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002765// # structured binding declaration
Nathan Sidwellac492da2022-04-05 09:25:47 -07002766// ::= [<module-name>] L? DC <source-name>+ E
Pavel Labathba825192018-10-16 14:29:14 +00002767template <typename Derived, typename Alloc>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002768Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2769 NameState *State, Node *Scope, ModuleName *Module) {
2770 if (getDerived().parseModuleNameOpt(Module))
2771 return nullptr;
2772
Nathan Sidwellac492da2022-04-05 09:25:47 -07002773 consumeIf('L');
2774
Richard Smithc20d1442018-08-20 20:14:49 +00002775 Node *Result;
Nathan Sidwellac492da2022-04-05 09:25:47 -07002776 if (look() >= '1' && look() <= '9') {
Pavel Labathba825192018-10-16 14:29:14 +00002777 Result = getDerived().parseSourceName(State);
Nathan Sidwellac492da2022-04-05 09:25:47 -07002778 } else if (look() == 'U') {
2779 Result = getDerived().parseUnnamedTypeName(State);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002780 } else if (consumeIf("DC")) {
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002781 // Structured binding
Richard Smithc20d1442018-08-20 20:14:49 +00002782 size_t BindingsBegin = Names.size();
2783 do {
Pavel Labathba825192018-10-16 14:29:14 +00002784 Node *Binding = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00002785 if (Binding == nullptr)
2786 return nullptr;
2787 Names.push_back(Binding);
2788 } while (!consumeIf('E'));
2789 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002790 } else if (look() == 'C' || look() == 'D') {
2791 // A <ctor-dtor-name>.
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002792 if (Scope == nullptr || Module != nullptr)
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002793 return nullptr;
2794 Result = getDerived().parseCtorDtorName(Scope, State);
2795 } else {
Pavel Labathba825192018-10-16 14:29:14 +00002796 Result = getDerived().parseOperatorName(State);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002797 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002798
David Blaikie019fb1b2022-03-30 20:18:40 +00002799 if (Result != nullptr && Module != nullptr)
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002800 Result = make<ModuleEntity>(Module, Result);
Richard Smithc20d1442018-08-20 20:14:49 +00002801 if (Result != nullptr)
Pavel Labathba825192018-10-16 14:29:14 +00002802 Result = getDerived().parseAbiTags(Result);
Nathan Sidwell9a29c972022-01-25 12:23:31 -08002803 if (Result != nullptr && Scope != nullptr)
2804 Result = make<NestedName>(Scope, Result);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002805
Richard Smithc20d1442018-08-20 20:14:49 +00002806 return Result;
2807}
2808
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08002809// <module-name> ::= <module-subname>
2810// ::= <module-name> <module-subname>
2811// ::= <substitution> # passed in by caller
2812// <module-subname> ::= W <source-name>
2813// ::= W P <source-name>
2814template <typename Derived, typename Alloc>
2815bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2816 ModuleName *&Module) {
2817 while (consumeIf('W')) {
2818 bool IsPartition = consumeIf('P');
2819 Node *Sub = getDerived().parseSourceName(nullptr);
2820 if (!Sub)
2821 return true;
2822 Module =
2823 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));
2824 Subs.push_back(Module);
2825 }
2826
2827 return false;
2828}
2829
Richard Smithc20d1442018-08-20 20:14:49 +00002830// <unnamed-type-name> ::= Ut [<nonnegative number>] _
2831// ::= <closure-type-name>
2832//
2833// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2834//
2835// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
Pavel Labathba825192018-10-16 14:29:14 +00002836template <typename Derived, typename Alloc>
2837Node *
Richard Smithdf1c14c2019-09-06 23:53:21 +00002838AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2839 // <template-params> refer to the innermost <template-args>. Clear out any
2840 // outer args that we may have inserted into TemplateParams.
2841 if (State != nullptr)
2842 TemplateParams.clear();
2843
Richard Smithc20d1442018-08-20 20:14:49 +00002844 if (consumeIf("Ut")) {
2845 StringView Count = parseNumber();
2846 if (!consumeIf('_'))
2847 return nullptr;
2848 return make<UnnamedTypeName>(Count);
2849 }
2850 if (consumeIf("Ul")) {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08002851 ScopedOverride<size_t> SwapParams(ParsingLambdaParamsAtLevel,
Richard Smithdf1c14c2019-09-06 23:53:21 +00002852 TemplateParams.size());
2853 ScopedTemplateParamList LambdaTemplateParams(this);
2854
2855 size_t ParamsBegin = Names.size();
2856 while (look() == 'T' &&
2857 StringView("yptn").find(look(1)) != StringView::npos) {
2858 Node *T = parseTemplateParamDecl();
2859 if (!T)
2860 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002861 Names.push_back(T);
2862 }
2863 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);
2864
2865 // FIXME: If TempParams is empty and none of the function parameters
2866 // includes 'auto', we should remove LambdaTemplateParams from the
2867 // TemplateParams list. Unfortunately, we don't find out whether there are
2868 // any 'auto' parameters until too late in an example such as:
2869 //
2870 // template<typename T> void f(
2871 // decltype([](decltype([]<typename T>(T v) {}),
2872 // auto) {})) {}
2873 // template<typename T> void f(
2874 // decltype([](decltype([]<typename T>(T w) {}),
2875 // int) {})) {}
2876 //
2877 // Here, the type of v is at level 2 but the type of w is at level 1. We
2878 // don't find this out until we encounter the type of the next parameter.
2879 //
2880 // However, compilers can't actually cope with the former example in
2881 // practice, and it's likely to be made ill-formed in future, so we don't
2882 // need to support it here.
2883 //
2884 // If we encounter an 'auto' in the function parameter types, we will
2885 // recreate a template parameter scope for it, but any intervening lambdas
2886 // will be parsed in the 'wrong' template parameter depth.
2887 if (TempParams.empty())
2888 TemplateParams.pop_back();
2889
Richard Smithc20d1442018-08-20 20:14:49 +00002890 if (!consumeIf("vE")) {
Richard Smithc20d1442018-08-20 20:14:49 +00002891 do {
Pavel Labathba825192018-10-16 14:29:14 +00002892 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00002893 if (P == nullptr)
2894 return nullptr;
2895 Names.push_back(P);
2896 } while (!consumeIf('E'));
Richard Smithc20d1442018-08-20 20:14:49 +00002897 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00002898 NodeArray Params = popTrailingNodeArray(ParamsBegin);
2899
Richard Smithc20d1442018-08-20 20:14:49 +00002900 StringView Count = parseNumber();
2901 if (!consumeIf('_'))
2902 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00002903 return make<ClosureTypeName>(TempParams, Params, Count);
Richard Smithc20d1442018-08-20 20:14:49 +00002904 }
Erik Pilkington974b6542019-01-17 21:37:51 +00002905 if (consumeIf("Ub")) {
2906 (void)parseNumber();
2907 if (!consumeIf('_'))
2908 return nullptr;
2909 return make<NameType>("'block-literal'");
2910 }
Richard Smithc20d1442018-08-20 20:14:49 +00002911 return nullptr;
2912}
2913
2914// <source-name> ::= <positive length number> <identifier>
Pavel Labathba825192018-10-16 14:29:14 +00002915template <typename Derived, typename Alloc>
2916Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {
Richard Smithc20d1442018-08-20 20:14:49 +00002917 size_t Length = 0;
2918 if (parsePositiveInteger(&Length))
2919 return nullptr;
2920 if (numLeft() < Length || Length == 0)
2921 return nullptr;
2922 StringView Name(First, First + Length);
2923 First += Length;
2924 if (Name.startsWith("_GLOBAL__N"))
2925 return make<NameType>("(anonymous namespace)");
2926 return make<NameType>(Name);
2927}
2928
Nathan Sidwell7d9bbeb2022-04-08 06:55:31 -07002929// Operator encodings
2930template <typename Derived, typename Alloc>
2931const typename AbstractManglingParser<
2932 Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,
2933 Alloc>::Ops[] = {
2934 // Keep ordered by encoding
2935 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},
2936 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},
2937 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},
2938 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},
2939 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},
2940 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},
2941 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,
2942 "operator co_await"},
2943 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},
2944 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},
2945 {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"},
2946 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},
2947 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},
2948 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast
2949 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},
2950 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,
2951 "operator delete[]"},
2952 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},
2953 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},
2954 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,
2955 "operator delete"},
2956 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2957 "operator.*"},
2958 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,
2959 "operator."},
2960 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},
2961 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},
2962 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},
2963 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},
2964 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},
2965 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},
2966 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},
2967 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},
2968 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},
2969 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},
2970 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},
2971 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},
2972 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},
2973 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},
2974 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
2975 "operator*"},
2976 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},
2977 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,
2978 "operator new[]"},
2979 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},
2980 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},
2981 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},
2982 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},
2983 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},
2984 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},
2985 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},
2986 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},
2987 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},
2988 {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,
2989 "operator->*"},
2990 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},
2991 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},
2992 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,
2993 "operator->"},
2994 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,
2995 "operator?"},
2996 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},
2997 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},
2998 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,
2999 "reinterpret_cast"},
3000 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,
3001 "operator%"},
3002 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},
3003 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},
3004 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},
3005 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},
3006 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},
3007 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,
3008 "typeid "},
3009 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},
3010};
3011template <typename Derived, typename Alloc>
3012const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /
3013 sizeof(Ops[0]);
3014
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003015// If the next 2 chars are an operator encoding, consume them and return their
3016// OperatorInfo. Otherwise return nullptr.
3017template <typename Derived, typename Alloc>
3018const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *
3019AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003020 if (numLeft() < 2)
3021 return nullptr;
3022
3023 auto Op = std::lower_bound(
3024 &Ops[0], &Ops[NumOps], First,
3025 [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; });
3026 if (Op == &Ops[NumOps] || *Op != First)
3027 return nullptr;
3028
3029 First += 2;
3030 return Op;
3031}
3032
3033// <operator-name> ::= See parseOperatorEncoding()
Richard Smithc20d1442018-08-20 20:14:49 +00003034// ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003035// ::= v <digit> <source-name> # vendor extended operator
Pavel Labathba825192018-10-16 14:29:14 +00003036template <typename Derived, typename Alloc>
3037Node *
3038AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003039 if (const auto *Op = parseOperatorEncoding()) {
3040 if (Op->getKind() == OperatorInfo::CCast) {
3041 // ::= cv <type> # (cast)
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003042 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);
Richard Smithc20d1442018-08-20 20:14:49 +00003043 // If we're parsing an encoding, State != nullptr and the conversion
3044 // operators' <type> could have a <template-param> that refers to some
3045 // <template-arg>s further ahead in the mangled name.
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003046 ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,
Richard Smithc20d1442018-08-20 20:14:49 +00003047 PermitForwardTemplateReferences ||
3048 State != nullptr);
Pavel Labathba825192018-10-16 14:29:14 +00003049 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003050 if (Ty == nullptr)
3051 return nullptr;
3052 if (State) State->CtorDtorConversion = true;
3053 return make<ConversionOperatorType>(Ty);
3054 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003055
3056 if (Op->getKind() >= OperatorInfo::Unnameable)
3057 /* Not a nameable operator. */
3058 return nullptr;
3059 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())
3060 /* Not a nameable MemberExpr */
3061 return nullptr;
3062
3063 return make<NameType>(Op->getName());
3064 }
3065
3066 if (consumeIf("li")) {
Richard Smithc20d1442018-08-20 20:14:49 +00003067 // ::= li <source-name> # operator ""
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003068 Node *SN = getDerived().parseSourceName(State);
3069 if (SN == nullptr)
3070 return nullptr;
3071 return make<LiteralOperator>(SN);
3072 }
3073
3074 if (consumeIf('v')) {
3075 // ::= v <digit> <source-name> # vendor extended operator
3076 if (look() >= '0' && look() <= '9') {
3077 First++;
Pavel Labathba825192018-10-16 14:29:14 +00003078 Node *SN = getDerived().parseSourceName(State);
Richard Smithc20d1442018-08-20 20:14:49 +00003079 if (SN == nullptr)
3080 return nullptr;
3081 return make<ConversionOperatorType>(SN);
3082 }
3083 return nullptr;
3084 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08003085
Richard Smithc20d1442018-08-20 20:14:49 +00003086 return nullptr;
3087}
3088
3089// <ctor-dtor-name> ::= C1 # complete object constructor
3090// ::= C2 # base object constructor
3091// ::= C3 # complete object allocating constructor
Nico Weber29294792019-04-03 23:14:33 +00003092// extension ::= C4 # gcc old-style "[unified]" constructor
3093// extension ::= C5 # the COMDAT used for ctors
Richard Smithc20d1442018-08-20 20:14:49 +00003094// ::= D0 # deleting destructor
3095// ::= D1 # complete object destructor
3096// ::= D2 # base object destructor
Nico Weber29294792019-04-03 23:14:33 +00003097// extension ::= D4 # gcc old-style "[unified]" destructor
3098// extension ::= D5 # the COMDAT used for dtors
Pavel Labathba825192018-10-16 14:29:14 +00003099template <typename Derived, typename Alloc>
3100Node *
3101AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
3102 NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003103 if (SoFar->getKind() == Node::KSpecialSubstitution) {
Nathan Sidwell28201492022-03-28 12:55:45 -07003104 // Expand the special substitution.
3105 SoFar = make<ExpandedSpecialSubstitution>(
3106 static_cast<SpecialSubstitution *>(SoFar));
3107 if (!SoFar)
3108 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003109 }
3110
3111 if (consumeIf('C')) {
3112 bool IsInherited = consumeIf('I');
Nico Weber29294792019-04-03 23:14:33 +00003113 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&
3114 look() != '5')
Richard Smithc20d1442018-08-20 20:14:49 +00003115 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003116 int Variant = look() - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003117 ++First;
3118 if (State) State->CtorDtorConversion = true;
3119 if (IsInherited) {
Pavel Labathba825192018-10-16 14:29:14 +00003120 if (getDerived().parseName(State) == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003121 return nullptr;
3122 }
Nico Weber29294792019-04-03 23:14:33 +00003123 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003124 }
3125
Nico Weber29294792019-04-03 23:14:33 +00003126 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||
3127 look(1) == '4' || look(1) == '5')) {
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003128 int Variant = look(1) - '0';
Richard Smithc20d1442018-08-20 20:14:49 +00003129 First += 2;
3130 if (State) State->CtorDtorConversion = true;
Nico Weber29294792019-04-03 23:14:33 +00003131 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);
Richard Smithc20d1442018-08-20 20:14:49 +00003132 }
3133
3134 return nullptr;
3135}
3136
Nathan Sidwellac492da2022-04-05 09:25:47 -07003137// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
3138// <unqualified-name> E
3139// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
3140// <template-args> E
Richard Smithc20d1442018-08-20 20:14:49 +00003141//
Nathan Sidwellac492da2022-04-05 09:25:47 -07003142// <prefix> ::= <prefix> <unqualified-name>
Richard Smithc20d1442018-08-20 20:14:49 +00003143// ::= <template-prefix> <template-args>
3144// ::= <template-param>
3145// ::= <decltype>
3146// ::= # empty
3147// ::= <substitution>
3148// ::= <prefix> <data-member-prefix>
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003149// [*] extension
Richard Smithc20d1442018-08-20 20:14:49 +00003150//
3151// <data-member-prefix> := <member source-name> [<template-args>] M
3152//
3153// <template-prefix> ::= <prefix> <template unqualified-name>
3154// ::= <template-param>
3155// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003156template <typename Derived, typename Alloc>
3157Node *
3158AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
Richard Smithc20d1442018-08-20 20:14:49 +00003159 if (!consumeIf('N'))
3160 return nullptr;
3161
3162 Qualifiers CVTmp = parseCVQualifiers();
3163 if (State) State->CVQualifiers = CVTmp;
3164
3165 if (consumeIf('O')) {
3166 if (State) State->ReferenceQualifier = FrefQualRValue;
3167 } else if (consumeIf('R')) {
3168 if (State) State->ReferenceQualifier = FrefQualLValue;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003169 } else {
Richard Smithc20d1442018-08-20 20:14:49 +00003170 if (State) State->ReferenceQualifier = FrefQualNone;
Richard Smithb485b352018-08-24 23:30:26 +00003171 }
Richard Smithc20d1442018-08-20 20:14:49 +00003172
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003173 Node *SoFar = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003174 while (!consumeIf('E')) {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003175 if (State)
3176 // Only set end-with-template on the case that does that.
3177 State->EndsWithTemplateArgs = false;
3178
Richard Smithc20d1442018-08-20 20:14:49 +00003179 if (look() == 'T') {
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003180 // ::= <template-param>
3181 if (SoFar != nullptr)
3182 return nullptr; // Cannot have a prefix.
3183 SoFar = getDerived().parseTemplateParam();
3184 } else if (look() == 'I') {
3185 // ::= <template-prefix> <template-args>
3186 if (SoFar == nullptr)
3187 return nullptr; // Must have a prefix.
Pavel Labathba825192018-10-16 14:29:14 +00003188 Node *TA = getDerived().parseTemplateArgs(State != nullptr);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003189 if (TA == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003190 return nullptr;
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003191 if (SoFar->getKind() == Node::KNameWithTemplateArgs)
3192 // Semantically <template-args> <template-args> cannot be generated by a
3193 // C++ entity. There will always be [something like] a name between
3194 // them.
3195 return nullptr;
3196 if (State)
3197 State->EndsWithTemplateArgs = true;
Richard Smithc20d1442018-08-20 20:14:49 +00003198 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003199 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {
3200 // ::= <decltype>
3201 if (SoFar != nullptr)
3202 return nullptr; // Cannot have a prefix.
3203 SoFar = getDerived().parseDecltype();
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003204 } else {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003205 ModuleName *Module = nullptr;
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003206
3207 if (look() == 'S') {
3208 // ::= <substitution>
3209 Node *S = nullptr;
3210 if (look(1) == 't') {
3211 First += 2;
3212 S = make<NameType>("std");
3213 } else {
3214 S = getDerived().parseSubstitution();
3215 }
3216 if (!S)
3217 return nullptr;
3218 if (S->getKind() == Node::KModuleName) {
3219 Module = static_cast<ModuleName *>(S);
Nathan Sidwellac492da2022-04-05 09:25:47 -07003220 } else if (SoFar != nullptr) {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003221 return nullptr; // Cannot have a prefix.
3222 } else {
3223 SoFar = S;
3224 continue; // Do not push a new substitution.
3225 }
3226 }
3227
Nathan Sidwell9a29c972022-01-25 12:23:31 -08003228 // ::= [<prefix>] <unqualified-name>
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003229 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);
Richard Smithc20d1442018-08-20 20:14:49 +00003230 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08003231
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08003232 if (SoFar == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00003233 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003234 Subs.push_back(SoFar);
Nathan Sidwelle6545292022-01-25 12:31:01 -08003235
3236 // No longer used.
3237 // <data-member-prefix> := <member source-name> [<template-args>] M
3238 consumeIf('M');
Richard Smithc20d1442018-08-20 20:14:49 +00003239 }
3240
3241 if (SoFar == nullptr || Subs.empty())
3242 return nullptr;
3243
3244 Subs.pop_back();
3245 return SoFar;
3246}
3247
3248// <simple-id> ::= <source-name> [ <template-args> ]
Pavel Labathba825192018-10-16 14:29:14 +00003249template <typename Derived, typename Alloc>
3250Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {
3251 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003252 if (SN == nullptr)
3253 return nullptr;
3254 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003255 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003256 if (TA == nullptr)
3257 return nullptr;
3258 return make<NameWithTemplateArgs>(SN, TA);
3259 }
3260 return SN;
3261}
3262
3263// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())
3264// ::= <simple-id> # e.g., ~A<2*N>
Pavel Labathba825192018-10-16 14:29:14 +00003265template <typename Derived, typename Alloc>
3266Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003267 Node *Result;
3268 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003269 Result = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003270 else
Pavel Labathba825192018-10-16 14:29:14 +00003271 Result = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003272 if (Result == nullptr)
3273 return nullptr;
3274 return make<DtorName>(Result);
3275}
3276
3277// <unresolved-type> ::= <template-param>
3278// ::= <decltype>
3279// ::= <substitution>
Pavel Labathba825192018-10-16 14:29:14 +00003280template <typename Derived, typename Alloc>
3281Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003282 if (look() == 'T') {
Pavel Labathba825192018-10-16 14:29:14 +00003283 Node *TP = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003284 if (TP == nullptr)
3285 return nullptr;
3286 Subs.push_back(TP);
3287 return TP;
3288 }
3289 if (look() == 'D') {
Pavel Labathba825192018-10-16 14:29:14 +00003290 Node *DT = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003291 if (DT == nullptr)
3292 return nullptr;
3293 Subs.push_back(DT);
3294 return DT;
3295 }
Pavel Labathba825192018-10-16 14:29:14 +00003296 return getDerived().parseSubstitution();
Richard Smithc20d1442018-08-20 20:14:49 +00003297}
3298
3299// <base-unresolved-name> ::= <simple-id> # unresolved name
3300// extension ::= <operator-name> # unresolved operator-function-id
3301// extension ::= <operator-name> <template-args> # unresolved operator template-id
3302// ::= on <operator-name> # unresolved operator-function-id
3303// ::= on <operator-name> <template-args> # unresolved operator template-id
3304// ::= dn <destructor-name> # destructor or pseudo-destructor;
3305// # e.g. ~X or ~X<N-1>
Pavel Labathba825192018-10-16 14:29:14 +00003306template <typename Derived, typename Alloc>
3307Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003308 if (std::isdigit(look()))
Pavel Labathba825192018-10-16 14:29:14 +00003309 return getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003310
3311 if (consumeIf("dn"))
Pavel Labathba825192018-10-16 14:29:14 +00003312 return getDerived().parseDestructorName();
Richard Smithc20d1442018-08-20 20:14:49 +00003313
3314 consumeIf("on");
3315
Pavel Labathba825192018-10-16 14:29:14 +00003316 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003317 if (Oper == nullptr)
3318 return nullptr;
3319 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003320 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003321 if (TA == nullptr)
3322 return nullptr;
3323 return make<NameWithTemplateArgs>(Oper, TA);
3324 }
3325 return Oper;
3326}
3327
3328// <unresolved-name>
3329// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3330// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x
3331// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3332// # A::x, N::y, A<T>::z; "gs" means leading "::"
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003333// [gs] has been parsed by caller.
Richard Smithc20d1442018-08-20 20:14:49 +00003334// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x
3335// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>
3336// # T::N::x /decltype(p)::N::x
3337// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3338//
3339// <unresolved-qualifier-level> ::= <simple-id>
Pavel Labathba825192018-10-16 14:29:14 +00003340template <typename Derived, typename Alloc>
Nathan Sidwell77c52e22022-01-28 11:59:03 -08003341Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
Richard Smithc20d1442018-08-20 20:14:49 +00003342 Node *SoFar = nullptr;
3343
3344 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>
3345 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>
3346 if (consumeIf("srN")) {
Pavel Labathba825192018-10-16 14:29:14 +00003347 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003348 if (SoFar == nullptr)
3349 return nullptr;
3350
3351 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003352 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003353 if (TA == nullptr)
3354 return nullptr;
3355 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003356 if (!SoFar)
3357 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003358 }
3359
3360 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003361 Node *Qual = getDerived().parseSimpleId();
Richard Smithc20d1442018-08-20 20:14:49 +00003362 if (Qual == nullptr)
3363 return nullptr;
3364 SoFar = make<QualifiedName>(SoFar, Qual);
Richard Smithb485b352018-08-24 23:30:26 +00003365 if (!SoFar)
3366 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003367 }
3368
Pavel Labathba825192018-10-16 14:29:14 +00003369 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003370 if (Base == nullptr)
3371 return nullptr;
3372 return make<QualifiedName>(SoFar, Base);
3373 }
3374
Richard Smithc20d1442018-08-20 20:14:49 +00003375 // [gs] <base-unresolved-name> # x or (with "gs") ::x
3376 if (!consumeIf("sr")) {
Pavel Labathba825192018-10-16 14:29:14 +00003377 SoFar = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003378 if (SoFar == nullptr)
3379 return nullptr;
3380 if (Global)
3381 SoFar = make<GlobalQualifiedName>(SoFar);
3382 return SoFar;
3383 }
3384
3385 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>
3386 if (std::isdigit(look())) {
3387 do {
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 if (SoFar)
3392 SoFar = make<QualifiedName>(SoFar, Qual);
3393 else if (Global)
3394 SoFar = make<GlobalQualifiedName>(Qual);
3395 else
3396 SoFar = Qual;
Richard Smithb485b352018-08-24 23:30:26 +00003397 if (!SoFar)
3398 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003399 } while (!consumeIf('E'));
3400 }
3401 // sr <unresolved-type> <base-unresolved-name>
3402 // sr <unresolved-type> <template-args> <base-unresolved-name>
3403 else {
Pavel Labathba825192018-10-16 14:29:14 +00003404 SoFar = getDerived().parseUnresolvedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003405 if (SoFar == nullptr)
3406 return nullptr;
3407
3408 if (look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00003409 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00003410 if (TA == nullptr)
3411 return nullptr;
3412 SoFar = make<NameWithTemplateArgs>(SoFar, TA);
Richard Smithb485b352018-08-24 23:30:26 +00003413 if (!SoFar)
3414 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003415 }
3416 }
3417
3418 assert(SoFar != nullptr);
3419
Pavel Labathba825192018-10-16 14:29:14 +00003420 Node *Base = getDerived().parseBaseUnresolvedName();
Richard Smithc20d1442018-08-20 20:14:49 +00003421 if (Base == nullptr)
3422 return nullptr;
3423 return make<QualifiedName>(SoFar, Base);
3424}
3425
3426// <abi-tags> ::= <abi-tag> [<abi-tags>]
3427// <abi-tag> ::= B <source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003428template <typename Derived, typename Alloc>
3429Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {
Richard Smithc20d1442018-08-20 20:14:49 +00003430 while (consumeIf('B')) {
3431 StringView SN = parseBareSourceName();
3432 if (SN.empty())
3433 return nullptr;
3434 N = make<AbiTagAttr>(N, SN);
Richard Smithb485b352018-08-24 23:30:26 +00003435 if (!N)
3436 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003437 }
3438 return N;
3439}
3440
3441// <number> ::= [n] <non-negative decimal integer>
Pavel Labathba825192018-10-16 14:29:14 +00003442template <typename Alloc, typename Derived>
3443StringView
3444AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {
Richard Smithc20d1442018-08-20 20:14:49 +00003445 const char *Tmp = First;
3446 if (AllowNegative)
3447 consumeIf('n');
3448 if (numLeft() == 0 || !std::isdigit(*First))
3449 return StringView();
3450 while (numLeft() != 0 && std::isdigit(*First))
3451 ++First;
3452 return StringView(Tmp, First);
3453}
3454
3455// <positive length number> ::= [0-9]*
Pavel Labathba825192018-10-16 14:29:14 +00003456template <typename Alloc, typename Derived>
3457bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00003458 *Out = 0;
3459 if (look() < '0' || look() > '9')
3460 return true;
3461 while (look() >= '0' && look() <= '9') {
3462 *Out *= 10;
3463 *Out += static_cast<size_t>(consume() - '0');
3464 }
3465 return false;
3466}
3467
Pavel Labathba825192018-10-16 14:29:14 +00003468template <typename Alloc, typename Derived>
3469StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {
Richard Smithc20d1442018-08-20 20:14:49 +00003470 size_t Int = 0;
3471 if (parsePositiveInteger(&Int) || numLeft() < Int)
3472 return StringView();
3473 StringView R(First, First + Int);
3474 First += Int;
3475 return R;
3476}
3477
3478// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E
3479//
3480// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())
3481// ::= DO <expression> E # computed (instantiation-dependent) noexcept
3482// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types
3483//
3484// <ref-qualifier> ::= R # & ref-qualifier
3485// <ref-qualifier> ::= O # && ref-qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003486template <typename Derived, typename Alloc>
3487Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003488 Qualifiers CVQuals = parseCVQualifiers();
3489
3490 Node *ExceptionSpec = nullptr;
3491 if (consumeIf("Do")) {
3492 ExceptionSpec = make<NameType>("noexcept");
Richard Smithb485b352018-08-24 23:30:26 +00003493 if (!ExceptionSpec)
3494 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003495 } else if (consumeIf("DO")) {
Pavel Labathba825192018-10-16 14:29:14 +00003496 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003497 if (E == nullptr || !consumeIf('E'))
3498 return nullptr;
3499 ExceptionSpec = make<NoexceptSpec>(E);
Richard Smithb485b352018-08-24 23:30:26 +00003500 if (!ExceptionSpec)
3501 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003502 } else if (consumeIf("Dw")) {
3503 size_t SpecsBegin = Names.size();
3504 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00003505 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003506 if (T == nullptr)
3507 return nullptr;
3508 Names.push_back(T);
3509 }
3510 ExceptionSpec =
3511 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));
Richard Smithb485b352018-08-24 23:30:26 +00003512 if (!ExceptionSpec)
3513 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003514 }
3515
3516 consumeIf("Dx"); // transaction safe
3517
3518 if (!consumeIf('F'))
3519 return nullptr;
3520 consumeIf('Y'); // extern "C"
Pavel Labathba825192018-10-16 14:29:14 +00003521 Node *ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003522 if (ReturnType == nullptr)
3523 return nullptr;
3524
3525 FunctionRefQual ReferenceQualifier = FrefQualNone;
3526 size_t ParamsBegin = Names.size();
3527 while (true) {
3528 if (consumeIf('E'))
3529 break;
3530 if (consumeIf('v'))
3531 continue;
3532 if (consumeIf("RE")) {
3533 ReferenceQualifier = FrefQualLValue;
3534 break;
3535 }
3536 if (consumeIf("OE")) {
3537 ReferenceQualifier = FrefQualRValue;
3538 break;
3539 }
Pavel Labathba825192018-10-16 14:29:14 +00003540 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003541 if (T == nullptr)
3542 return nullptr;
3543 Names.push_back(T);
3544 }
3545
3546 NodeArray Params = popTrailingNodeArray(ParamsBegin);
3547 return make<FunctionType>(ReturnType, Params, CVQuals,
3548 ReferenceQualifier, ExceptionSpec);
3549}
3550
3551// extension:
3552// <vector-type> ::= Dv <positive dimension number> _ <extended element type>
3553// ::= Dv [<dimension expression>] _ <element type>
3554// <extended element type> ::= <element type>
3555// ::= p # AltiVec vector pixel
Pavel Labathba825192018-10-16 14:29:14 +00003556template <typename Derived, typename Alloc>
3557Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003558 if (!consumeIf("Dv"))
3559 return nullptr;
3560 if (look() >= '1' && look() <= '9') {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003561 Node *DimensionNumber = make<NameType>(parseNumber());
3562 if (!DimensionNumber)
3563 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003564 if (!consumeIf('_'))
3565 return nullptr;
3566 if (consumeIf('p'))
3567 return make<PixelVectorType>(DimensionNumber);
Pavel Labathba825192018-10-16 14:29:14 +00003568 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003569 if (ElemType == nullptr)
3570 return nullptr;
3571 return make<VectorType>(ElemType, DimensionNumber);
3572 }
3573
3574 if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003575 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003576 if (!DimExpr)
3577 return nullptr;
3578 if (!consumeIf('_'))
3579 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003580 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003581 if (!ElemType)
3582 return nullptr;
3583 return make<VectorType>(ElemType, DimExpr);
3584 }
Pavel Labathba825192018-10-16 14:29:14 +00003585 Node *ElemType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003586 if (!ElemType)
3587 return nullptr;
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003588 return make<VectorType>(ElemType, /*Dimension=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00003589}
3590
3591// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)
3592// ::= DT <expression> E # decltype of an expression (C++0x)
Pavel Labathba825192018-10-16 14:29:14 +00003593template <typename Derived, typename Alloc>
3594Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {
Richard Smithc20d1442018-08-20 20:14:49 +00003595 if (!consumeIf('D'))
3596 return nullptr;
3597 if (!consumeIf('t') && !consumeIf('T'))
3598 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003599 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003600 if (E == nullptr)
3601 return nullptr;
3602 if (!consumeIf('E'))
3603 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08003604 return make<EnclosingExpr>("decltype", E);
Richard Smithc20d1442018-08-20 20:14:49 +00003605}
3606
3607// <array-type> ::= A <positive dimension number> _ <element type>
3608// ::= A [<dimension expression>] _ <element type>
Pavel Labathba825192018-10-16 14:29:14 +00003609template <typename Derived, typename Alloc>
3610Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003611 if (!consumeIf('A'))
3612 return nullptr;
3613
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003614 Node *Dimension = nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003615
Richard Smithc20d1442018-08-20 20:14:49 +00003616 if (std::isdigit(look())) {
Erik Pilkingtond7555e32019-11-04 10:47:44 -08003617 Dimension = make<NameType>(parseNumber());
3618 if (!Dimension)
3619 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00003620 if (!consumeIf('_'))
3621 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003622 } else if (!consumeIf('_')) {
Pavel Labathba825192018-10-16 14:29:14 +00003623 Node *DimExpr = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00003624 if (DimExpr == nullptr)
3625 return nullptr;
3626 if (!consumeIf('_'))
3627 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003628 Dimension = DimExpr;
Richard Smithc20d1442018-08-20 20:14:49 +00003629 }
3630
Pavel Labathba825192018-10-16 14:29:14 +00003631 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003632 if (Ty == nullptr)
3633 return nullptr;
Pavel Labathf4e67eb2018-10-10 08:39:16 +00003634 return make<ArrayType>(Ty, Dimension);
Richard Smithc20d1442018-08-20 20:14:49 +00003635}
3636
3637// <pointer-to-member-type> ::= M <class type> <member type>
Pavel Labathba825192018-10-16 14:29:14 +00003638template <typename Derived, typename Alloc>
3639Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003640 if (!consumeIf('M'))
3641 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003642 Node *ClassType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003643 if (ClassType == nullptr)
3644 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003645 Node *MemberType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003646 if (MemberType == nullptr)
3647 return nullptr;
3648 return make<PointerToMemberType>(ClassType, MemberType);
3649}
3650
3651// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier
3652// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'
3653// ::= Tu <name> # dependent elaborated type specifier using 'union'
3654// ::= Te <name> # dependent elaborated type specifier using 'enum'
Pavel Labathba825192018-10-16 14:29:14 +00003655template <typename Derived, typename Alloc>
3656Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003657 StringView ElabSpef;
3658 if (consumeIf("Ts"))
3659 ElabSpef = "struct";
3660 else if (consumeIf("Tu"))
3661 ElabSpef = "union";
3662 else if (consumeIf("Te"))
3663 ElabSpef = "enum";
3664
Pavel Labathba825192018-10-16 14:29:14 +00003665 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00003666 if (Name == nullptr)
3667 return nullptr;
3668
3669 if (!ElabSpef.empty())
3670 return make<ElaboratedTypeSpefType>(ElabSpef, Name);
3671
3672 return Name;
3673}
3674
3675// <qualified-type> ::= <qualifiers> <type>
3676// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>
3677// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier
Pavel Labathba825192018-10-16 14:29:14 +00003678template <typename Derived, typename Alloc>
3679Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003680 if (consumeIf('U')) {
3681 StringView Qual = parseBareSourceName();
3682 if (Qual.empty())
3683 return nullptr;
3684
Richard Smithc20d1442018-08-20 20:14:49 +00003685 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3686 if (Qual.startsWith("objcproto")) {
3687 StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));
3688 StringView Proto;
3689 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08003690 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.begin()),
3691 SaveLast(Last, ProtoSourceName.end());
Richard Smithc20d1442018-08-20 20:14:49 +00003692 Proto = parseBareSourceName();
3693 }
3694 if (Proto.empty())
3695 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00003696 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003697 if (Child == nullptr)
3698 return nullptr;
3699 return make<ObjCProtoName>(Child, Proto);
3700 }
3701
Alex Orlovf50df922021-03-24 10:21:32 +04003702 Node *TA = nullptr;
3703 if (look() == 'I') {
3704 TA = getDerived().parseTemplateArgs();
3705 if (TA == nullptr)
3706 return nullptr;
3707 }
3708
Pavel Labathba825192018-10-16 14:29:14 +00003709 Node *Child = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003710 if (Child == nullptr)
3711 return nullptr;
Alex Orlovf50df922021-03-24 10:21:32 +04003712 return make<VendorExtQualType>(Child, Qual, TA);
Richard Smithc20d1442018-08-20 20:14:49 +00003713 }
3714
3715 Qualifiers Quals = parseCVQualifiers();
Pavel Labathba825192018-10-16 14:29:14 +00003716 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003717 if (Ty == nullptr)
3718 return nullptr;
3719 if (Quals != QualNone)
3720 Ty = make<QualType>(Ty, Quals);
3721 return Ty;
3722}
3723
3724// <type> ::= <builtin-type>
3725// ::= <qualified-type>
3726// ::= <function-type>
3727// ::= <class-enum-type>
3728// ::= <array-type>
3729// ::= <pointer-to-member-type>
3730// ::= <template-param>
3731// ::= <template-template-param> <template-args>
3732// ::= <decltype>
3733// ::= P <type> # pointer
3734// ::= R <type> # l-value reference
3735// ::= O <type> # r-value reference (C++11)
3736// ::= C <type> # complex pair (C99)
3737// ::= G <type> # imaginary (C99)
3738// ::= <substitution> # See Compression below
3739// extension ::= U <objc-name> <objc-type> # objc-type<identifier>
3740// extension ::= <vector-type> # <vector-type> starts with Dv
3741//
3742// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1
3743// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>
Pavel Labathba825192018-10-16 14:29:14 +00003744template <typename Derived, typename Alloc>
3745Node *AbstractManglingParser<Derived, Alloc>::parseType() {
Richard Smithc20d1442018-08-20 20:14:49 +00003746 Node *Result = nullptr;
3747
Richard Smithc20d1442018-08-20 20:14:49 +00003748 switch (look()) {
3749 // ::= <qualified-type>
3750 case 'r':
3751 case 'V':
3752 case 'K': {
3753 unsigned AfterQuals = 0;
3754 if (look(AfterQuals) == 'r') ++AfterQuals;
3755 if (look(AfterQuals) == 'V') ++AfterQuals;
3756 if (look(AfterQuals) == 'K') ++AfterQuals;
3757
3758 if (look(AfterQuals) == 'F' ||
3759 (look(AfterQuals) == 'D' &&
3760 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||
3761 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {
Pavel Labathba825192018-10-16 14:29:14 +00003762 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003763 break;
3764 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00003765 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00003766 }
3767 case 'U': {
Pavel Labathba825192018-10-16 14:29:14 +00003768 Result = getDerived().parseQualifiedType();
Richard Smithc20d1442018-08-20 20:14:49 +00003769 break;
3770 }
3771 // <builtin-type> ::= v # void
3772 case 'v':
3773 ++First;
3774 return make<NameType>("void");
3775 // ::= w # wchar_t
3776 case 'w':
3777 ++First;
3778 return make<NameType>("wchar_t");
3779 // ::= b # bool
3780 case 'b':
3781 ++First;
3782 return make<NameType>("bool");
3783 // ::= c # char
3784 case 'c':
3785 ++First;
3786 return make<NameType>("char");
3787 // ::= a # signed char
3788 case 'a':
3789 ++First;
3790 return make<NameType>("signed char");
3791 // ::= h # unsigned char
3792 case 'h':
3793 ++First;
3794 return make<NameType>("unsigned char");
3795 // ::= s # short
3796 case 's':
3797 ++First;
3798 return make<NameType>("short");
3799 // ::= t # unsigned short
3800 case 't':
3801 ++First;
3802 return make<NameType>("unsigned short");
3803 // ::= i # int
3804 case 'i':
3805 ++First;
3806 return make<NameType>("int");
3807 // ::= j # unsigned int
3808 case 'j':
3809 ++First;
3810 return make<NameType>("unsigned int");
3811 // ::= l # long
3812 case 'l':
3813 ++First;
3814 return make<NameType>("long");
3815 // ::= m # unsigned long
3816 case 'm':
3817 ++First;
3818 return make<NameType>("unsigned long");
3819 // ::= x # long long, __int64
3820 case 'x':
3821 ++First;
3822 return make<NameType>("long long");
3823 // ::= y # unsigned long long, __int64
3824 case 'y':
3825 ++First;
3826 return make<NameType>("unsigned long long");
3827 // ::= n # __int128
3828 case 'n':
3829 ++First;
3830 return make<NameType>("__int128");
3831 // ::= o # unsigned __int128
3832 case 'o':
3833 ++First;
3834 return make<NameType>("unsigned __int128");
3835 // ::= f # float
3836 case 'f':
3837 ++First;
3838 return make<NameType>("float");
3839 // ::= d # double
3840 case 'd':
3841 ++First;
3842 return make<NameType>("double");
3843 // ::= e # long double, __float80
3844 case 'e':
3845 ++First;
3846 return make<NameType>("long double");
3847 // ::= g # __float128
3848 case 'g':
3849 ++First;
3850 return make<NameType>("__float128");
3851 // ::= z # ellipsis
3852 case 'z':
3853 ++First;
3854 return make<NameType>("...");
3855
3856 // <builtin-type> ::= u <source-name> # vendor extended type
3857 case 'u': {
3858 ++First;
3859 StringView Res = parseBareSourceName();
3860 if (Res.empty())
3861 return nullptr;
Erik Pilkingtonb94a1f42019-06-10 21:02:39 +00003862 // Typically, <builtin-type>s are not considered substitution candidates,
3863 // but the exception to that exception is vendor extended types (Itanium C++
3864 // ABI 5.9.1).
3865 Result = make<NameType>(Res);
3866 break;
Richard Smithc20d1442018-08-20 20:14:49 +00003867 }
3868 case 'D':
3869 switch (look(1)) {
3870 // ::= Dd # IEEE 754r decimal floating point (64 bits)
3871 case 'd':
3872 First += 2;
3873 return make<NameType>("decimal64");
3874 // ::= De # IEEE 754r decimal floating point (128 bits)
3875 case 'e':
3876 First += 2;
3877 return make<NameType>("decimal128");
3878 // ::= Df # IEEE 754r decimal floating point (32 bits)
3879 case 'f':
3880 First += 2;
3881 return make<NameType>("decimal32");
3882 // ::= Dh # IEEE 754r half-precision floating point (16 bits)
3883 case 'h':
3884 First += 2;
Stuart Bradye8bf5772021-06-07 16:30:22 +01003885 return make<NameType>("half");
Pengfei Wang50e90b82021-09-23 11:02:25 +08003886 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)
3887 case 'F': {
3888 First += 2;
3889 Node *DimensionNumber = make<NameType>(parseNumber());
3890 if (!DimensionNumber)
3891 return nullptr;
3892 if (!consumeIf('_'))
3893 return nullptr;
3894 return make<BinaryFPType>(DimensionNumber);
3895 }
Senran Zhange025ba52022-03-27 00:04:23 +08003896 // ::= DB <number> _ # C23 signed _BitInt(N)
3897 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)
3898 // ::= DU <number> _ # C23 unsigned _BitInt(N)
3899 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)
3900 case 'B':
3901 case 'U': {
3902 bool Signed = look(1) == 'B';
3903 First += 2;
3904 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())
3905 : getDerived().parseExpr();
3906 if (!Size)
3907 return nullptr;
3908 if (!consumeIf('_'))
3909 return nullptr;
3910 return make<BitIntType>(Size, Signed);
3911 }
Richard Smithc20d1442018-08-20 20:14:49 +00003912 // ::= Di # char32_t
3913 case 'i':
3914 First += 2;
3915 return make<NameType>("char32_t");
3916 // ::= Ds # char16_t
3917 case 's':
3918 First += 2;
3919 return make<NameType>("char16_t");
Erik Pilkingtonc3780e82019-06-28 19:54:19 +00003920 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)
3921 case 'u':
3922 First += 2;
3923 return make<NameType>("char8_t");
Richard Smithc20d1442018-08-20 20:14:49 +00003924 // ::= Da # auto (in dependent new-expressions)
3925 case 'a':
3926 First += 2;
3927 return make<NameType>("auto");
3928 // ::= Dc # decltype(auto)
3929 case 'c':
3930 First += 2;
3931 return make<NameType>("decltype(auto)");
3932 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3933 case 'n':
3934 First += 2;
3935 return make<NameType>("std::nullptr_t");
3936
3937 // ::= <decltype>
3938 case 't':
3939 case 'T': {
Pavel Labathba825192018-10-16 14:29:14 +00003940 Result = getDerived().parseDecltype();
Richard Smithc20d1442018-08-20 20:14:49 +00003941 break;
3942 }
3943 // extension ::= <vector-type> # <vector-type> starts with Dv
3944 case 'v': {
Pavel Labathba825192018-10-16 14:29:14 +00003945 Result = getDerived().parseVectorType();
Richard Smithc20d1442018-08-20 20:14:49 +00003946 break;
3947 }
3948 // ::= Dp <type> # pack expansion (C++0x)
3949 case 'p': {
3950 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00003951 Node *Child = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00003952 if (!Child)
3953 return nullptr;
3954 Result = make<ParameterPackExpansion>(Child);
3955 break;
3956 }
3957 // Exception specifier on a function type.
3958 case 'o':
3959 case 'O':
3960 case 'w':
3961 // Transaction safe function type.
3962 case 'x':
Pavel Labathba825192018-10-16 14:29:14 +00003963 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003964 break;
3965 }
3966 break;
3967 // ::= <function-type>
3968 case 'F': {
Pavel Labathba825192018-10-16 14:29:14 +00003969 Result = getDerived().parseFunctionType();
Richard Smithc20d1442018-08-20 20:14:49 +00003970 break;
3971 }
3972 // ::= <array-type>
3973 case 'A': {
Pavel Labathba825192018-10-16 14:29:14 +00003974 Result = getDerived().parseArrayType();
Richard Smithc20d1442018-08-20 20:14:49 +00003975 break;
3976 }
3977 // ::= <pointer-to-member-type>
3978 case 'M': {
Pavel Labathba825192018-10-16 14:29:14 +00003979 Result = getDerived().parsePointerToMemberType();
Richard Smithc20d1442018-08-20 20:14:49 +00003980 break;
3981 }
3982 // ::= <template-param>
3983 case 'T': {
3984 // This could be an elaborate type specifier on a <class-enum-type>.
3985 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {
Pavel Labathba825192018-10-16 14:29:14 +00003986 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00003987 break;
3988 }
3989
Pavel Labathba825192018-10-16 14:29:14 +00003990 Result = getDerived().parseTemplateParam();
Richard Smithc20d1442018-08-20 20:14:49 +00003991 if (Result == nullptr)
3992 return nullptr;
3993
3994 // Result could be either of:
3995 // <type> ::= <template-param>
3996 // <type> ::= <template-template-param> <template-args>
3997 //
3998 // <template-template-param> ::= <template-param>
3999 // ::= <substitution>
4000 //
4001 // If this is followed by some <template-args>, and we're permitted to
4002 // parse them, take the second production.
4003
4004 if (TryToParseTemplateArgs && look() == 'I') {
Pavel Labathba825192018-10-16 14:29:14 +00004005 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004006 if (TA == nullptr)
4007 return nullptr;
4008 Result = make<NameWithTemplateArgs>(Result, TA);
4009 }
4010 break;
4011 }
4012 // ::= P <type> # pointer
4013 case 'P': {
4014 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004015 Node *Ptr = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004016 if (Ptr == nullptr)
4017 return nullptr;
4018 Result = make<PointerType>(Ptr);
4019 break;
4020 }
4021 // ::= R <type> # l-value reference
4022 case 'R': {
4023 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004024 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004025 if (Ref == nullptr)
4026 return nullptr;
4027 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);
4028 break;
4029 }
4030 // ::= O <type> # r-value reference (C++11)
4031 case 'O': {
4032 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004033 Node *Ref = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004034 if (Ref == nullptr)
4035 return nullptr;
4036 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);
4037 break;
4038 }
4039 // ::= C <type> # complex pair (C99)
4040 case 'C': {
4041 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004042 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004043 if (P == nullptr)
4044 return nullptr;
4045 Result = make<PostfixQualifiedType>(P, " complex");
4046 break;
4047 }
4048 // ::= G <type> # imaginary (C99)
4049 case 'G': {
4050 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004051 Node *P = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004052 if (P == nullptr)
4053 return P;
4054 Result = make<PostfixQualifiedType>(P, " imaginary");
4055 break;
4056 }
4057 // ::= <substitution> # See Compression below
4058 case 'S': {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004059 if (look(1) != 't') {
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004060 bool IsSubst = false;
4061 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);
4062 if (!Result)
Richard Smithc20d1442018-08-20 20:14:49 +00004063 return nullptr;
4064
4065 // Sub could be either of:
4066 // <type> ::= <substitution>
4067 // <type> ::= <template-template-param> <template-args>
4068 //
4069 // <template-template-param> ::= <template-param>
4070 // ::= <substitution>
4071 //
4072 // If this is followed by some <template-args>, and we're permitted to
4073 // parse them, take the second production.
4074
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004075 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {
4076 if (!IsSubst)
4077 Subs.push_back(Result);
Pavel Labathba825192018-10-16 14:29:14 +00004078 Node *TA = getDerived().parseTemplateArgs();
Richard Smithc20d1442018-08-20 20:14:49 +00004079 if (TA == nullptr)
4080 return nullptr;
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004081 Result = make<NameWithTemplateArgs>(Result, TA);
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004082 } else if (IsSubst) {
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004083 // If all we parsed was a substitution, don't re-insert into the
4084 // substitution table.
4085 return Result;
Richard Smithc20d1442018-08-20 20:14:49 +00004086 }
Nathan Sidwelle4cc3532022-01-24 04:28:09 -08004087 break;
Richard Smithc20d1442018-08-20 20:14:49 +00004088 }
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00004089 DEMANGLE_FALLTHROUGH;
Richard Smithc20d1442018-08-20 20:14:49 +00004090 }
4091 // ::= <class-enum-type>
4092 default: {
Pavel Labathba825192018-10-16 14:29:14 +00004093 Result = getDerived().parseClassEnumType();
Richard Smithc20d1442018-08-20 20:14:49 +00004094 break;
4095 }
4096 }
4097
4098 // If we parsed a type, insert it into the substitution table. Note that all
4099 // <builtin-type>s and <substitution>s have already bailed out, because they
4100 // don't get substitutions.
4101 if (Result != nullptr)
4102 Subs.push_back(Result);
4103 return Result;
4104}
4105
Pavel Labathba825192018-10-16 14:29:14 +00004106template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004107Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind,
4108 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004109 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004110 if (E == nullptr)
4111 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004112 return make<PrefixExpr>(Kind, E, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004113}
4114
Pavel Labathba825192018-10-16 14:29:14 +00004115template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004116Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind,
4117 Node::Prec Prec) {
Pavel Labathba825192018-10-16 14:29:14 +00004118 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004119 if (LHS == nullptr)
4120 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004121 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004122 if (RHS == nullptr)
4123 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004124 return make<BinaryExpr>(LHS, Kind, RHS, Prec);
Richard Smithc20d1442018-08-20 20:14:49 +00004125}
4126
Pavel Labathba825192018-10-16 14:29:14 +00004127template <typename Derived, typename Alloc>
4128Node *
4129AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {
Richard Smithc20d1442018-08-20 20:14:49 +00004130 StringView Tmp = parseNumber(true);
4131 if (!Tmp.empty() && consumeIf('E'))
4132 return make<IntegerLiteral>(Lit, Tmp);
4133 return nullptr;
4134}
4135
4136// <CV-Qualifiers> ::= [r] [V] [K]
Pavel Labathba825192018-10-16 14:29:14 +00004137template <typename Alloc, typename Derived>
4138Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
Richard Smithc20d1442018-08-20 20:14:49 +00004139 Qualifiers CVR = QualNone;
4140 if (consumeIf('r'))
4141 CVR |= QualRestrict;
4142 if (consumeIf('V'))
4143 CVR |= QualVolatile;
4144 if (consumeIf('K'))
4145 CVR |= QualConst;
4146 return CVR;
4147}
4148
4149// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter
4150// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
4151// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
4152// ::= 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 -04004153// ::= fpT # 'this' expression (not part of standard?)
Pavel Labathba825192018-10-16 14:29:14 +00004154template <typename Derived, typename Alloc>
4155Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
Erik Pilkington91c24af2020-05-13 22:19:45 -04004156 if (consumeIf("fpT"))
4157 return make<NameType>("this");
Richard Smithc20d1442018-08-20 20:14:49 +00004158 if (consumeIf("fp")) {
4159 parseCVQualifiers();
4160 StringView Num = parseNumber();
4161 if (!consumeIf('_'))
4162 return nullptr;
4163 return make<FunctionParam>(Num);
4164 }
4165 if (consumeIf("fL")) {
4166 if (parseNumber().empty())
4167 return nullptr;
4168 if (!consumeIf('p'))
4169 return nullptr;
4170 parseCVQualifiers();
4171 StringView Num = parseNumber();
4172 if (!consumeIf('_'))
4173 return nullptr;
4174 return make<FunctionParam>(Num);
4175 }
4176 return nullptr;
4177}
4178
Richard Smithc20d1442018-08-20 20:14:49 +00004179// cv <type> <expression> # conversion with one argument
4180// cv <type> _ <expression>* E # conversion with a different number of arguments
Pavel Labathba825192018-10-16 14:29:14 +00004181template <typename Derived, typename Alloc>
4182Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004183 if (!consumeIf("cv"))
4184 return nullptr;
4185 Node *Ty;
4186 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004187 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Pavel Labathba825192018-10-16 14:29:14 +00004188 Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004189 }
4190
4191 if (Ty == nullptr)
4192 return nullptr;
4193
4194 if (consumeIf('_')) {
4195 size_t ExprsBegin = Names.size();
4196 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00004197 Node *E = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004198 if (E == nullptr)
4199 return E;
4200 Names.push_back(E);
4201 }
4202 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4203 return make<ConversionExpr>(Ty, Exprs);
4204 }
4205
Pavel Labathba825192018-10-16 14:29:14 +00004206 Node *E[1] = {getDerived().parseExpr()};
Richard Smithc20d1442018-08-20 20:14:49 +00004207 if (E[0] == nullptr)
4208 return nullptr;
4209 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));
4210}
4211
4212// <expr-primary> ::= L <type> <value number> E # integer literal
4213// ::= L <type> <value float> E # floating literal
4214// ::= L <string type> E # string literal
4215// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")
Richard Smithdf1c14c2019-09-06 23:53:21 +00004216// ::= L <lambda type> E # lambda expression
Richard Smithc20d1442018-08-20 20:14:49 +00004217// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)
4218// ::= L <mangled-name> E # external name
Pavel Labathba825192018-10-16 14:29:14 +00004219template <typename Derived, typename Alloc>
4220Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Richard Smithc20d1442018-08-20 20:14:49 +00004221 if (!consumeIf('L'))
4222 return nullptr;
4223 switch (look()) {
4224 case 'w':
4225 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004226 return getDerived().parseIntegerLiteral("wchar_t");
Richard Smithc20d1442018-08-20 20:14:49 +00004227 case 'b':
4228 if (consumeIf("b0E"))
4229 return make<BoolExpr>(0);
4230 if (consumeIf("b1E"))
4231 return make<BoolExpr>(1);
4232 return nullptr;
4233 case 'c':
4234 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004235 return getDerived().parseIntegerLiteral("char");
Richard Smithc20d1442018-08-20 20:14:49 +00004236 case 'a':
4237 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004238 return getDerived().parseIntegerLiteral("signed char");
Richard Smithc20d1442018-08-20 20:14:49 +00004239 case 'h':
4240 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004241 return getDerived().parseIntegerLiteral("unsigned char");
Richard Smithc20d1442018-08-20 20:14:49 +00004242 case 's':
4243 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004244 return getDerived().parseIntegerLiteral("short");
Richard Smithc20d1442018-08-20 20:14:49 +00004245 case 't':
4246 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004247 return getDerived().parseIntegerLiteral("unsigned short");
Richard Smithc20d1442018-08-20 20:14:49 +00004248 case 'i':
4249 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004250 return getDerived().parseIntegerLiteral("");
Richard Smithc20d1442018-08-20 20:14:49 +00004251 case 'j':
4252 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004253 return getDerived().parseIntegerLiteral("u");
Richard Smithc20d1442018-08-20 20:14:49 +00004254 case 'l':
4255 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004256 return getDerived().parseIntegerLiteral("l");
Richard Smithc20d1442018-08-20 20:14:49 +00004257 case 'm':
4258 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004259 return getDerived().parseIntegerLiteral("ul");
Richard Smithc20d1442018-08-20 20:14:49 +00004260 case 'x':
4261 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004262 return getDerived().parseIntegerLiteral("ll");
Richard Smithc20d1442018-08-20 20:14:49 +00004263 case 'y':
4264 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004265 return getDerived().parseIntegerLiteral("ull");
Richard Smithc20d1442018-08-20 20:14:49 +00004266 case 'n':
4267 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004268 return getDerived().parseIntegerLiteral("__int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004269 case 'o':
4270 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004271 return getDerived().parseIntegerLiteral("unsigned __int128");
Richard Smithc20d1442018-08-20 20:14:49 +00004272 case 'f':
4273 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004274 return getDerived().template parseFloatingLiteral<float>();
Richard Smithc20d1442018-08-20 20:14:49 +00004275 case 'd':
4276 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00004277 return getDerived().template parseFloatingLiteral<double>();
Richard Smithc20d1442018-08-20 20:14:49 +00004278 case 'e':
4279 ++First;
Xing Xue3dc5e082020-04-15 09:59:06 -04004280#if defined(__powerpc__) || defined(__s390__)
4281 // Handle cases where long doubles encoded with e have the same size
4282 // and representation as doubles.
4283 return getDerived().template parseFloatingLiteral<double>();
4284#else
Pavel Labathba825192018-10-16 14:29:14 +00004285 return getDerived().template parseFloatingLiteral<long double>();
Xing Xue3dc5e082020-04-15 09:59:06 -04004286#endif
Richard Smithc20d1442018-08-20 20:14:49 +00004287 case '_':
4288 if (consumeIf("_Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00004289 Node *R = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004290 if (R != nullptr && consumeIf('E'))
4291 return R;
4292 }
4293 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00004294 case 'A': {
4295 Node *T = getDerived().parseType();
4296 if (T == nullptr)
4297 return nullptr;
4298 // FIXME: We need to include the string contents in the mangling.
4299 if (consumeIf('E'))
4300 return make<StringLiteral>(T);
4301 return nullptr;
4302 }
4303 case 'D':
gbreynooc0559322022-04-28 15:55:26 +01004304 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))
Richard Smithdf1c14c2019-09-06 23:53:21 +00004305 return make<NameType>("nullptr");
4306 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004307 case 'T':
4308 // Invalid mangled name per
4309 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
4310 return nullptr;
Richard Smithfb917462019-09-09 22:26:04 +00004311 case 'U': {
4312 // FIXME: Should we support LUb... for block literals?
4313 if (look(1) != 'l')
4314 return nullptr;
4315 Node *T = parseUnnamedTypeName(nullptr);
4316 if (!T || !consumeIf('E'))
4317 return nullptr;
4318 return make<LambdaExpr>(T);
4319 }
Richard Smithc20d1442018-08-20 20:14:49 +00004320 default: {
4321 // might be named type
Pavel Labathba825192018-10-16 14:29:14 +00004322 Node *T = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004323 if (T == nullptr)
4324 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004325 StringView N = parseNumber(/*AllowNegative=*/true);
Richard Smithfb917462019-09-09 22:26:04 +00004326 if (N.empty())
4327 return nullptr;
4328 if (!consumeIf('E'))
4329 return nullptr;
Erik Pilkington0a170f12020-05-13 14:13:37 -04004330 return make<EnumLiteral>(T, N);
Richard Smithc20d1442018-08-20 20:14:49 +00004331 }
4332 }
4333}
4334
4335// <braced-expression> ::= <expression>
4336// ::= di <field source-name> <braced-expression> # .name = expr
4337// ::= dx <index expression> <braced-expression> # [expr] = expr
4338// ::= dX <range begin expression> <range end expression> <braced-expression>
Pavel Labathba825192018-10-16 14:29:14 +00004339template <typename Derived, typename Alloc>
4340Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004341 if (look() == 'd') {
4342 switch (look(1)) {
4343 case 'i': {
4344 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004345 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);
Richard Smithc20d1442018-08-20 20:14:49 +00004346 if (Field == nullptr)
4347 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004348 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004349 if (Init == nullptr)
4350 return nullptr;
4351 return make<BracedExpr>(Field, Init, /*isArray=*/false);
4352 }
4353 case 'x': {
4354 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004355 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004356 if (Index == nullptr)
4357 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004358 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004359 if (Init == nullptr)
4360 return nullptr;
4361 return make<BracedExpr>(Index, Init, /*isArray=*/true);
4362 }
4363 case 'X': {
4364 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004365 Node *RangeBegin = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004366 if (RangeBegin == nullptr)
4367 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004368 Node *RangeEnd = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004369 if (RangeEnd == nullptr)
4370 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004371 Node *Init = getDerived().parseBracedExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004372 if (Init == nullptr)
4373 return nullptr;
4374 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);
4375 }
4376 }
4377 }
Pavel Labathba825192018-10-16 14:29:14 +00004378 return getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004379}
4380
4381// (not yet in the spec)
4382// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>
4383// ::= fR <binary-operator-name> <expression> <expression>
4384// ::= fl <binary-operator-name> <expression>
4385// ::= fr <binary-operator-name> <expression>
Pavel Labathba825192018-10-16 14:29:14 +00004386template <typename Derived, typename Alloc>
4387Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004388 if (!consumeIf('f'))
4389 return nullptr;
4390
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004391 bool IsLeftFold = false, HasInitializer = false;
4392 switch (look()) {
4393 default:
Richard Smithc20d1442018-08-20 20:14:49 +00004394 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004395 case 'L':
4396 IsLeftFold = true;
4397 HasInitializer = true;
4398 break;
4399 case 'R':
4400 HasInitializer = true;
4401 break;
4402 case 'l':
4403 IsLeftFold = true;
4404 break;
4405 case 'r':
4406 break;
4407 }
Richard Smithc20d1442018-08-20 20:14:49 +00004408 ++First;
4409
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004410 const auto *Op = parseOperatorEncoding();
Nathan Sidwellce967252022-02-18 11:06:58 -08004411 if (!Op)
4412 return nullptr;
4413 if (!(Op->getKind() == OperatorInfo::Binary
4414 || (Op->getKind() == OperatorInfo::Member
4415 && Op->getName().back() == '*')))
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004416 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004417
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004418 Node *Pack = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004419 if (Pack == nullptr)
4420 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004421
4422 Node *Init = nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00004423 if (HasInitializer) {
Pavel Labathba825192018-10-16 14:29:14 +00004424 Init = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004425 if (Init == nullptr)
4426 return nullptr;
4427 }
4428
4429 if (IsLeftFold && Init)
4430 std::swap(Pack, Init);
4431
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004432 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);
Richard Smithc20d1442018-08-20 20:14:49 +00004433}
4434
Richard Smith1865d2f2020-10-22 19:29:36 -07004435// <expression> ::= mc <parameter type> <expr> [<offset number>] E
4436//
4437// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4438template <typename Derived, typename Alloc>
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004439Node *
4440AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(
4441 Node::Prec Prec) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004442 Node *Ty = getDerived().parseType();
4443 if (!Ty)
4444 return nullptr;
4445 Node *Expr = getDerived().parseExpr();
4446 if (!Expr)
4447 return nullptr;
4448 StringView Offset = getDerived().parseNumber(true);
4449 if (!consumeIf('E'))
4450 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004451 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);
Richard Smith1865d2f2020-10-22 19:29:36 -07004452}
4453
4454// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E
4455// <union-selector> ::= _ [<number>]
4456//
4457// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47
4458template <typename Derived, typename Alloc>
4459Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4460 Node *Ty = getDerived().parseType();
4461 if (!Ty)
4462 return nullptr;
4463 Node *Expr = getDerived().parseExpr();
4464 if (!Expr)
4465 return nullptr;
4466 StringView Offset = getDerived().parseNumber(true);
4467 size_t SelectorsBegin = Names.size();
4468 while (consumeIf('_')) {
4469 Node *Selector = make<NameType>(parseNumber());
4470 if (!Selector)
4471 return nullptr;
4472 Names.push_back(Selector);
4473 }
4474 bool OnePastTheEnd = consumeIf('p');
4475 if (!consumeIf('E'))
4476 return nullptr;
4477 return make<SubobjectExpr>(
4478 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4479}
4480
Richard Smithc20d1442018-08-20 20:14:49 +00004481// <expression> ::= <unary operator-name> <expression>
4482// ::= <binary operator-name> <expression> <expression>
4483// ::= <ternary operator-name> <expression> <expression> <expression>
4484// ::= cl <expression>+ E # call
4485// ::= cv <type> <expression> # conversion with one argument
4486// ::= cv <type> _ <expression>* E # conversion with a different number of arguments
4487// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type
4488// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
4489// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type
4490// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
4491// ::= [gs] dl <expression> # delete expression
4492// ::= [gs] da <expression> # delete[] expression
4493// ::= pp_ <expression> # prefix ++
4494// ::= mm_ <expression> # prefix --
4495// ::= ti <type> # typeid (type)
4496// ::= te <expression> # typeid (expression)
4497// ::= dc <type> <expression> # dynamic_cast<type> (expression)
4498// ::= sc <type> <expression> # static_cast<type> (expression)
4499// ::= cc <type> <expression> # const_cast<type> (expression)
4500// ::= rc <type> <expression> # reinterpret_cast<type> (expression)
4501// ::= st <type> # sizeof (a type)
4502// ::= sz <expression> # sizeof (an expression)
4503// ::= at <type> # alignof (a type)
4504// ::= az <expression> # alignof (an expression)
4505// ::= nx <expression> # noexcept (expression)
4506// ::= <template-param>
4507// ::= <function-param>
4508// ::= dt <expression> <unresolved-name> # expr.name
4509// ::= pt <expression> <unresolved-name> # expr->name
4510// ::= ds <expression> <expression> # expr.*expr
4511// ::= sZ <template-param> # size of a parameter pack
4512// ::= sZ <function-param> # size of a function parameter pack
4513// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template
4514// ::= sp <expression> # pack expansion
4515// ::= tw <expression> # throw expression
4516// ::= tr # throw with no operand (rethrow)
4517// ::= <unresolved-name> # f(p), N::f(p), ::f(p),
4518// # freestanding dependent name (e.g., T::x),
4519// # objectless nonstatic member reference
4520// ::= fL <binary-operator-name> <expression> <expression>
4521// ::= fR <binary-operator-name> <expression> <expression>
4522// ::= fl <binary-operator-name> <expression>
4523// ::= fr <binary-operator-name> <expression>
4524// ::= <expr-primary>
Pavel Labathba825192018-10-16 14:29:14 +00004525template <typename Derived, typename Alloc>
4526Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
Richard Smithc20d1442018-08-20 20:14:49 +00004527 bool Global = consumeIf("gs");
Richard Smithc20d1442018-08-20 20:14:49 +00004528
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004529 const auto *Op = parseOperatorEncoding();
4530 if (Op) {
4531 auto Sym = Op->getSymbol();
4532 switch (Op->getKind()) {
4533 case OperatorInfo::Binary:
4534 // Binary operator: lhs @ rhs
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004535 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004536 case OperatorInfo::Prefix:
4537 // Prefix unary operator: @ expr
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004538 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004539 case OperatorInfo::Postfix: {
4540 // Postfix unary operator: expr @
4541 if (consumeIf('_'))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004542 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());
Pavel Labathba825192018-10-16 14:29:14 +00004543 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004544 if (Ex == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004545 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004546 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004547 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004548 case OperatorInfo::Array: {
4549 // Array Index: lhs [ rhs ]
Pavel Labathba825192018-10-16 14:29:14 +00004550 Node *Base = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004551 if (Base == nullptr)
4552 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004553 Node *Index = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004554 if (Index == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004555 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004556 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004557 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004558 case OperatorInfo::Member: {
4559 // Member access lhs @ rhs
4560 Node *LHS = getDerived().parseExpr();
4561 if (LHS == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004562 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004563 Node *RHS = getDerived().parseExpr();
4564 if (RHS == nullptr)
4565 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004566 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004567 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004568 case OperatorInfo::New: {
4569 // New
4570 // # new (expr-list) type [(init)]
4571 // [gs] nw <expression>* _ <type> [pi <expression>*] E
4572 // # new[] (expr-list) type [(init)]
4573 // [gs] na <expression>* _ <type> [pi <expression>*] E
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004574 size_t Exprs = Names.size();
4575 while (!consumeIf('_')) {
4576 Node *Ex = getDerived().parseExpr();
4577 if (Ex == nullptr)
4578 return nullptr;
4579 Names.push_back(Ex);
4580 }
4581 NodeArray ExprList = popTrailingNodeArray(Exprs);
4582 Node *Ty = getDerived().parseType();
4583 if (Ty == nullptr)
4584 return nullptr;
4585 bool HaveInits = consumeIf("pi");
4586 size_t InitsBegin = Names.size();
4587 while (!consumeIf('E')) {
4588 if (!HaveInits)
4589 return nullptr;
4590 Node *Init = getDerived().parseExpr();
4591 if (Init == nullptr)
4592 return Init;
4593 Names.push_back(Init);
4594 }
4595 NodeArray Inits = popTrailingNodeArray(InitsBegin);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004596 return make<NewExpr>(ExprList, Ty, Inits, Global,
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004597 /*IsArray=*/Op->getFlag(), Op->getPrecedence());
Nathan Sidwellc69bde22022-01-28 07:09:38 -08004598 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004599 case OperatorInfo::Del: {
4600 // Delete
Pavel Labathba825192018-10-16 14:29:14 +00004601 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004602 if (Ex == nullptr)
Nathan Sidwellc6483042022-01-28 09:27:28 -08004603 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004604 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),
4605 Op->getPrecedence());
Nathan Sidwellc6483042022-01-28 09:27:28 -08004606 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004607 case OperatorInfo::Call: {
4608 // Function Call
4609 Node *Callee = getDerived().parseExpr();
4610 if (Callee == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004611 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004612 size_t ExprsBegin = Names.size();
4613 while (!consumeIf('E')) {
4614 Node *E = getDerived().parseExpr();
4615 if (E == nullptr)
4616 return nullptr;
4617 Names.push_back(E);
4618 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004619 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),
4620 Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004621 }
4622 case OperatorInfo::CCast: {
4623 // C Cast: (type)expr
4624 Node *Ty;
4625 {
Nathan Sidwellf6358c42022-02-28 10:18:14 -08004626 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004627 Ty = getDerived().parseType();
4628 }
4629 if (Ty == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004630 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004631
4632 size_t ExprsBegin = Names.size();
4633 bool IsMany = consumeIf('_');
4634 while (!consumeIf('E')) {
4635 Node *E = getDerived().parseExpr();
4636 if (E == nullptr)
4637 return E;
4638 Names.push_back(E);
4639 if (!IsMany)
4640 break;
4641 }
4642 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);
4643 if (!IsMany && Exprs.size() != 1)
4644 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004645 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004646 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004647 case OperatorInfo::Conditional: {
4648 // Conditional operator: expr ? expr : expr
Pavel Labathba825192018-10-16 14:29:14 +00004649 Node *Cond = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004650 if (Cond == nullptr)
4651 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004652 Node *LHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004653 if (LHS == nullptr)
4654 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004655 Node *RHS = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004656 if (RHS == nullptr)
4657 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004658 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004659 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004660 case OperatorInfo::NamedCast: {
4661 // Named cast operation, @<type>(expr)
Pavel Labathba825192018-10-16 14:29:14 +00004662 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004663 if (Ty == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004664 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004665 Node *Ex = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00004666 if (Ex == nullptr)
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004667 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004668 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());
Richard Smithc20d1442018-08-20 20:14:49 +00004669 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004670 case OperatorInfo::OfIdOp: {
4671 // [sizeof/alignof/typeid] ( <type>|<expr> )
4672 Node *Arg =
4673 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();
4674 if (!Arg)
4675 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004676 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004677 }
Nathan Sidwell0dda3d42022-02-18 09:51:24 -08004678 case OperatorInfo::NameOnly: {
4679 // Not valid as an expression operand.
4680 return nullptr;
4681 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004682 }
4683 DEMANGLE_UNREACHABLE;
4684 }
4685
4686 if (numLeft() < 2)
4687 return nullptr;
4688
4689 if (look() == 'L')
4690 return getDerived().parseExprPrimary();
4691 if (look() == 'T')
4692 return getDerived().parseTemplateParam();
4693 if (look() == 'f') {
4694 // Disambiguate a fold expression from a <function-param>.
4695 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))
4696 return getDerived().parseFunctionParam();
4697 return getDerived().parseFoldExpr();
4698 }
4699 if (consumeIf("il")) {
4700 size_t InitsBegin = Names.size();
4701 while (!consumeIf('E')) {
4702 Node *E = getDerived().parseBracedExpr();
4703 if (E == nullptr)
4704 return nullptr;
4705 Names.push_back(E);
4706 }
4707 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));
4708 }
4709 if (consumeIf("mc"))
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004710 return parsePointerToMemberConversionExpr(Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004711 if (consumeIf("nx")) {
4712 Node *Ex = getDerived().parseExpr();
4713 if (Ex == nullptr)
4714 return Ex;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004715 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004716 }
4717 if (consumeIf("so"))
4718 return parseSubobjectExpr();
4719 if (consumeIf("sp")) {
4720 Node *Child = getDerived().parseExpr();
4721 if (Child == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004722 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004723 return make<ParameterPackExpansion>(Child);
4724 }
4725 if (consumeIf("sZ")) {
4726 if (look() == 'T') {
4727 Node *R = getDerived().parseTemplateParam();
4728 if (R == nullptr)
Richard Smithb485b352018-08-24 23:30:26 +00004729 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004730 return make<SizeofParamPackExpr>(R);
Richard Smithc20d1442018-08-20 20:14:49 +00004731 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004732 Node *FP = getDerived().parseFunctionParam();
4733 if (FP == nullptr)
4734 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004735 return make<EnclosingExpr>("sizeof... ", FP);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004736 }
4737 if (consumeIf("sP")) {
4738 size_t ArgsBegin = Names.size();
4739 while (!consumeIf('E')) {
4740 Node *Arg = getDerived().parseTemplateArg();
4741 if (Arg == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004742 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004743 Names.push_back(Arg);
Richard Smithc20d1442018-08-20 20:14:49 +00004744 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004745 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));
4746 if (!Pack)
4747 return nullptr;
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004748 return make<EnclosingExpr>("sizeof... ", Pack);
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004749 }
4750 if (consumeIf("tl")) {
4751 Node *Ty = getDerived().parseType();
4752 if (Ty == nullptr)
4753 return nullptr;
4754 size_t InitsBegin = Names.size();
4755 while (!consumeIf('E')) {
4756 Node *E = getDerived().parseBracedExpr();
4757 if (E == nullptr)
Richard Smithc20d1442018-08-20 20:14:49 +00004758 return nullptr;
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004759 Names.push_back(E);
Richard Smithc20d1442018-08-20 20:14:49 +00004760 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004761 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));
4762 }
4763 if (consumeIf("tr"))
4764 return make<NameType>("throw");
4765 if (consumeIf("tw")) {
4766 Node *Ex = getDerived().parseExpr();
4767 if (Ex == nullptr)
4768 return nullptr;
4769 return make<ThrowExpr>(Ex);
4770 }
4771 if (consumeIf('u')) {
James Y Knight4a60efc2020-12-07 10:26:49 -05004772 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);
4773 if (!Name)
4774 return nullptr;
4775 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the
4776 // standard encoding expects a <template-arg>, and would be otherwise be
4777 // interpreted as <type> node 'short' or 'ellipsis'. However, neither
4778 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no
4779 // actual conflict here.
Nathan Sidwella3b59002022-02-11 05:54:40 -08004780 bool IsUUID = false;
4781 Node *UUID = nullptr;
James Y Knight4a60efc2020-12-07 10:26:49 -05004782 if (Name->getBaseName() == "__uuidof") {
Nathan Sidwella3b59002022-02-11 05:54:40 -08004783 if (consumeIf('t')) {
4784 UUID = getDerived().parseType();
4785 IsUUID = true;
4786 } else if (consumeIf('z')) {
4787 UUID = getDerived().parseExpr();
4788 IsUUID = true;
James Y Knight4a60efc2020-12-07 10:26:49 -05004789 }
4790 }
4791 size_t ExprsBegin = Names.size();
Nathan Sidwella3b59002022-02-11 05:54:40 -08004792 if (IsUUID) {
4793 if (UUID == nullptr)
4794 return nullptr;
4795 Names.push_back(UUID);
4796 } else {
4797 while (!consumeIf('E')) {
4798 Node *E = getDerived().parseTemplateArg();
4799 if (E == nullptr)
4800 return E;
4801 Names.push_back(E);
4802 }
James Y Knight4a60efc2020-12-07 10:26:49 -05004803 }
Nathan Sidwell458a94f2022-02-04 11:45:23 -08004804 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),
4805 Node::Prec::Postfix);
James Y Knight4a60efc2020-12-07 10:26:49 -05004806 }
Nathan Sidwell12b2ce72022-01-27 13:23:16 -08004807
4808 // Only unresolved names remain.
4809 return getDerived().parseUnresolvedName(Global);
Richard Smithc20d1442018-08-20 20:14:49 +00004810}
4811
4812// <call-offset> ::= h <nv-offset> _
4813// ::= v <v-offset> _
4814//
4815// <nv-offset> ::= <offset number>
4816// # non-virtual base override
4817//
4818// <v-offset> ::= <offset number> _ <virtual offset number>
4819// # virtual base override, with vcall offset
Pavel Labathba825192018-10-16 14:29:14 +00004820template <typename Alloc, typename Derived>
4821bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {
Richard Smithc20d1442018-08-20 20:14:49 +00004822 // Just scan through the call offset, we never add this information into the
4823 // output.
4824 if (consumeIf('h'))
4825 return parseNumber(true).empty() || !consumeIf('_');
4826 if (consumeIf('v'))
4827 return parseNumber(true).empty() || !consumeIf('_') ||
4828 parseNumber(true).empty() || !consumeIf('_');
4829 return true;
4830}
4831
4832// <special-name> ::= TV <type> # virtual table
4833// ::= TT <type> # VTT structure (construction vtable index)
4834// ::= TI <type> # typeinfo structure
4835// ::= TS <type> # typeinfo name (null-terminated byte string)
4836// ::= Tc <call-offset> <call-offset> <base encoding>
4837// # base is the nominal target function of thunk
4838// # first call-offset is 'this' adjustment
4839// # second call-offset is result adjustment
4840// ::= T <call-offset> <base encoding>
4841// # base is the nominal target function of thunk
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004842// # Guard variable for one-time initialization
4843// ::= GV <object name>
Richard Smithc20d1442018-08-20 20:14:49 +00004844// # No <type>
4845// ::= TW <object name> # Thread-local wrapper
4846// ::= TH <object name> # Thread-local initialization
4847// ::= GR <object name> _ # First temporary
4848// ::= GR <object name> <seq-id> _ # Subsequent temporaries
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004849// # construction vtable for second-in-first
4850// extension ::= TC <first type> <number> _ <second type>
Richard Smithc20d1442018-08-20 20:14:49 +00004851// extension ::= GR <object name> # reference temporary for object
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004852// extension ::= GI <module name> # module global initializer
Pavel Labathba825192018-10-16 14:29:14 +00004853template <typename Derived, typename Alloc>
4854Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
Richard Smithc20d1442018-08-20 20:14:49 +00004855 switch (look()) {
4856 case 'T':
4857 switch (look(1)) {
Richard Smith1865d2f2020-10-22 19:29:36 -07004858 // TA <template-arg> # template parameter object
4859 //
4860 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63
4861 case 'A': {
4862 First += 2;
4863 Node *Arg = getDerived().parseTemplateArg();
4864 if (Arg == nullptr)
4865 return nullptr;
4866 return make<SpecialName>("template parameter object for ", Arg);
4867 }
Richard Smithc20d1442018-08-20 20:14:49 +00004868 // TV <type> # virtual table
4869 case 'V': {
4870 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004871 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004872 if (Ty == nullptr)
4873 return nullptr;
4874 return make<SpecialName>("vtable for ", Ty);
4875 }
4876 // TT <type> # VTT structure (construction vtable index)
4877 case 'T': {
4878 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004879 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004880 if (Ty == nullptr)
4881 return nullptr;
4882 return make<SpecialName>("VTT for ", Ty);
4883 }
4884 // TI <type> # typeinfo structure
4885 case 'I': {
4886 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004887 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004888 if (Ty == nullptr)
4889 return nullptr;
4890 return make<SpecialName>("typeinfo for ", Ty);
4891 }
4892 // TS <type> # typeinfo name (null-terminated byte string)
4893 case 'S': {
4894 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004895 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004896 if (Ty == nullptr)
4897 return nullptr;
4898 return make<SpecialName>("typeinfo name for ", Ty);
4899 }
4900 // Tc <call-offset> <call-offset> <base encoding>
4901 case 'c': {
4902 First += 2;
4903 if (parseCallOffset() || parseCallOffset())
4904 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004905 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004906 if (Encoding == nullptr)
4907 return nullptr;
4908 return make<SpecialName>("covariant return thunk to ", Encoding);
4909 }
4910 // extension ::= TC <first type> <number> _ <second type>
4911 // # construction vtable for second-in-first
4912 case 'C': {
4913 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004914 Node *FirstType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004915 if (FirstType == nullptr)
4916 return nullptr;
4917 if (parseNumber(true).empty() || !consumeIf('_'))
4918 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004919 Node *SecondType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00004920 if (SecondType == nullptr)
4921 return nullptr;
4922 return make<CtorVtableSpecialName>(SecondType, FirstType);
4923 }
4924 // TW <object name> # Thread-local wrapper
4925 case 'W': {
4926 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004927 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004928 if (Name == nullptr)
4929 return nullptr;
4930 return make<SpecialName>("thread-local wrapper routine for ", Name);
4931 }
4932 // TH <object name> # Thread-local initialization
4933 case 'H': {
4934 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004935 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004936 if (Name == nullptr)
4937 return nullptr;
4938 return make<SpecialName>("thread-local initialization routine for ", Name);
4939 }
4940 // T <call-offset> <base encoding>
4941 default: {
4942 ++First;
4943 bool IsVirt = look() == 'v';
4944 if (parseCallOffset())
4945 return nullptr;
Pavel Labathba825192018-10-16 14:29:14 +00004946 Node *BaseEncoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00004947 if (BaseEncoding == nullptr)
4948 return nullptr;
4949 if (IsVirt)
4950 return make<SpecialName>("virtual thunk to ", BaseEncoding);
4951 else
4952 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);
4953 }
4954 }
4955 case 'G':
4956 switch (look(1)) {
4957 // GV <object name> # Guard variable for one-time initialization
4958 case 'V': {
4959 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004960 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004961 if (Name == nullptr)
4962 return nullptr;
4963 return make<SpecialName>("guard variable for ", Name);
4964 }
4965 // GR <object name> # reference temporary for object
4966 // GR <object name> _ # First temporary
4967 // GR <object name> <seq-id> _ # Subsequent temporaries
4968 case 'R': {
4969 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00004970 Node *Name = getDerived().parseName();
Richard Smithc20d1442018-08-20 20:14:49 +00004971 if (Name == nullptr)
4972 return nullptr;
4973 size_t Count;
4974 bool ParsedSeqId = !parseSeqId(&Count);
4975 if (!consumeIf('_') && ParsedSeqId)
4976 return nullptr;
4977 return make<SpecialName>("reference temporary for ", Name);
4978 }
Nathan Sidwelledde7bb2022-01-26 07:22:04 -08004979 // GI <module-name> v
4980 case 'I': {
4981 First += 2;
4982 ModuleName *Module = nullptr;
4983 if (getDerived().parseModuleNameOpt(Module))
4984 return nullptr;
4985 if (Module == nullptr)
4986 return nullptr;
4987 return make<SpecialName>("initializer for module ", Module);
4988 }
Richard Smithc20d1442018-08-20 20:14:49 +00004989 }
4990 }
4991 return nullptr;
4992}
4993
4994// <encoding> ::= <function name> <bare-function-type>
4995// ::= <data name>
4996// ::= <special-name>
Pavel Labathba825192018-10-16 14:29:14 +00004997template <typename Derived, typename Alloc>
4998Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
Richard Smithfac39712020-07-09 21:08:39 -07004999 // The template parameters of an encoding are unrelated to those of the
5000 // enclosing context.
5001 class SaveTemplateParams {
5002 AbstractManglingParser *Parser;
5003 decltype(TemplateParams) OldParams;
Justin Lebar2c536232021-06-09 16:57:22 -07005004 decltype(OuterTemplateParams) OldOuterParams;
Richard Smithfac39712020-07-09 21:08:39 -07005005
5006 public:
Louis Dionnec1fe8672020-10-30 17:33:02 -04005007 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
Richard Smithfac39712020-07-09 21:08:39 -07005008 OldParams = std::move(Parser->TemplateParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005009 OldOuterParams = std::move(Parser->OuterTemplateParams);
Richard Smithfac39712020-07-09 21:08:39 -07005010 Parser->TemplateParams.clear();
Justin Lebar2c536232021-06-09 16:57:22 -07005011 Parser->OuterTemplateParams.clear();
Richard Smithfac39712020-07-09 21:08:39 -07005012 }
5013 ~SaveTemplateParams() {
5014 Parser->TemplateParams = std::move(OldParams);
Justin Lebar2c536232021-06-09 16:57:22 -07005015 Parser->OuterTemplateParams = std::move(OldOuterParams);
Richard Smithfac39712020-07-09 21:08:39 -07005016 }
5017 } SaveTemplateParams(this);
Richard Smithfd434322020-07-09 20:36:04 -07005018
Richard Smithc20d1442018-08-20 20:14:49 +00005019 if (look() == 'G' || look() == 'T')
Pavel Labathba825192018-10-16 14:29:14 +00005020 return getDerived().parseSpecialName();
Richard Smithc20d1442018-08-20 20:14:49 +00005021
5022 auto IsEndOfEncoding = [&] {
5023 // The set of chars that can potentially follow an <encoding> (none of which
5024 // can start a <type>). Enumerating these allows us to avoid speculative
5025 // parsing.
5026 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
5027 };
5028
5029 NameState NameInfo(this);
Pavel Labathba825192018-10-16 14:29:14 +00005030 Node *Name = getDerived().parseName(&NameInfo);
Richard Smithc20d1442018-08-20 20:14:49 +00005031 if (Name == nullptr)
5032 return nullptr;
5033
5034 if (resolveForwardTemplateRefs(NameInfo))
5035 return nullptr;
5036
5037 if (IsEndOfEncoding())
5038 return Name;
5039
5040 Node *Attrs = nullptr;
5041 if (consumeIf("Ua9enable_ifI")) {
5042 size_t BeforeArgs = Names.size();
5043 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005044 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005045 if (Arg == nullptr)
5046 return nullptr;
5047 Names.push_back(Arg);
5048 }
5049 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));
Richard Smithb485b352018-08-24 23:30:26 +00005050 if (!Attrs)
5051 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005052 }
5053
5054 Node *ReturnType = nullptr;
5055 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {
Pavel Labathba825192018-10-16 14:29:14 +00005056 ReturnType = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005057 if (ReturnType == nullptr)
5058 return nullptr;
5059 }
5060
5061 if (consumeIf('v'))
5062 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5063 Attrs, NameInfo.CVQualifiers,
5064 NameInfo.ReferenceQualifier);
5065
5066 size_t ParamsBegin = Names.size();
5067 do {
Pavel Labathba825192018-10-16 14:29:14 +00005068 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005069 if (Ty == nullptr)
5070 return nullptr;
5071 Names.push_back(Ty);
5072 } while (!IsEndOfEncoding());
5073
5074 return make<FunctionEncoding>(ReturnType, Name,
5075 popTrailingNodeArray(ParamsBegin),
5076 Attrs, NameInfo.CVQualifiers,
5077 NameInfo.ReferenceQualifier);
5078}
5079
5080template <class Float>
5081struct FloatData;
5082
5083template <>
5084struct FloatData<float>
5085{
5086 static const size_t mangled_size = 8;
5087 static const size_t max_demangled_size = 24;
5088 static constexpr const char* spec = "%af";
5089};
5090
5091template <>
5092struct FloatData<double>
5093{
5094 static const size_t mangled_size = 16;
5095 static const size_t max_demangled_size = 32;
5096 static constexpr const char* spec = "%a";
5097};
5098
5099template <>
5100struct FloatData<long double>
5101{
5102#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
Piggy NL8b1770b2022-05-26 22:59:49 +08005103 defined(__wasm__) || defined(__riscv)
Richard Smithc20d1442018-08-20 20:14:49 +00005104 static const size_t mangled_size = 32;
5105#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5106 static const size_t mangled_size = 16;
5107#else
5108 static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms
5109#endif
Elliott Hughes5a360ea2020-04-10 17:42:00 -07005110 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.
5111 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.
5112 // Negatives are one character longer than positives.
5113 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the
5114 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.
5115 static const size_t max_demangled_size = 42;
Richard Smithc20d1442018-08-20 20:14:49 +00005116 static constexpr const char *spec = "%LaL";
5117};
5118
Pavel Labathba825192018-10-16 14:29:14 +00005119template <typename Alloc, typename Derived>
5120template <class Float>
5121Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {
Richard Smithc20d1442018-08-20 20:14:49 +00005122 const size_t N = FloatData<Float>::mangled_size;
5123 if (numLeft() <= N)
5124 return nullptr;
5125 StringView Data(First, First + N);
5126 for (char C : Data)
5127 if (!std::isxdigit(C))
5128 return nullptr;
5129 First += N;
5130 if (!consumeIf('E'))
5131 return nullptr;
5132 return make<FloatLiteralImpl<Float>>(Data);
5133}
5134
5135// <seq-id> ::= <0-9A-Z>+
Pavel Labathba825192018-10-16 14:29:14 +00005136template <typename Alloc, typename Derived>
5137bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {
Richard Smithc20d1442018-08-20 20:14:49 +00005138 if (!(look() >= '0' && look() <= '9') &&
5139 !(look() >= 'A' && look() <= 'Z'))
5140 return true;
5141
5142 size_t Id = 0;
5143 while (true) {
5144 if (look() >= '0' && look() <= '9') {
5145 Id *= 36;
5146 Id += static_cast<size_t>(look() - '0');
5147 } else if (look() >= 'A' && look() <= 'Z') {
5148 Id *= 36;
5149 Id += static_cast<size_t>(look() - 'A') + 10;
5150 } else {
5151 *Out = Id;
5152 return false;
5153 }
5154 ++First;
5155 }
5156}
5157
5158// <substitution> ::= S <seq-id> _
5159// ::= S_
5160// <substitution> ::= Sa # ::std::allocator
5161// <substitution> ::= Sb # ::std::basic_string
5162// <substitution> ::= Ss # ::std::basic_string < char,
5163// ::std::char_traits<char>,
5164// ::std::allocator<char> >
5165// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >
5166// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >
5167// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >
Nathan Sidwelle12f7bd2022-01-21 11:00:56 -08005168// The St case is handled specially in parseNestedName.
Pavel Labathba825192018-10-16 14:29:14 +00005169template <typename Derived, typename Alloc>
5170Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
Richard Smithc20d1442018-08-20 20:14:49 +00005171 if (!consumeIf('S'))
5172 return nullptr;
5173
Nathan Sidwellfd0ef6d2022-01-20 07:40:12 -08005174 if (look() >= 'a' && look() <= 'z') {
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005175 SpecialSubKind Kind;
Richard Smithc20d1442018-08-20 20:14:49 +00005176 switch (look()) {
5177 case 'a':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005178 Kind = SpecialSubKind::allocator;
Richard Smithc20d1442018-08-20 20:14:49 +00005179 break;
5180 case 'b':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005181 Kind = SpecialSubKind::basic_string;
Richard Smithc20d1442018-08-20 20:14:49 +00005182 break;
5183 case 'd':
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005184 Kind = SpecialSubKind::iostream;
5185 break;
5186 case 'i':
5187 Kind = SpecialSubKind::istream;
5188 break;
5189 case 'o':
5190 Kind = SpecialSubKind::ostream;
5191 break;
5192 case 's':
5193 Kind = SpecialSubKind::string;
Richard Smithc20d1442018-08-20 20:14:49 +00005194 break;
5195 default:
5196 return nullptr;
5197 }
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005198 ++First;
5199 auto *SpecialSub = make<SpecialSubstitution>(Kind);
Richard Smithb485b352018-08-24 23:30:26 +00005200 if (!SpecialSub)
5201 return nullptr;
Nathan Sidwelldf43e1b2022-01-24 07:59:57 -08005202
Richard Smithc20d1442018-08-20 20:14:49 +00005203 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>
5204 // has ABI tags, the tags are appended to the substitution; the result is a
5205 // substitutable component.
Pavel Labathba825192018-10-16 14:29:14 +00005206 Node *WithTags = getDerived().parseAbiTags(SpecialSub);
Richard Smithc20d1442018-08-20 20:14:49 +00005207 if (WithTags != SpecialSub) {
5208 Subs.push_back(WithTags);
5209 SpecialSub = WithTags;
5210 }
5211 return SpecialSub;
5212 }
5213
5214 // ::= S_
5215 if (consumeIf('_')) {
5216 if (Subs.empty())
5217 return nullptr;
5218 return Subs[0];
5219 }
5220
5221 // ::= S <seq-id> _
5222 size_t Index = 0;
5223 if (parseSeqId(&Index))
5224 return nullptr;
5225 ++Index;
5226 if (!consumeIf('_') || Index >= Subs.size())
5227 return nullptr;
5228 return Subs[Index];
5229}
5230
5231// <template-param> ::= T_ # first template parameter
5232// ::= T <parameter-2 non-negative number> _
Richard Smithdf1c14c2019-09-06 23:53:21 +00005233// ::= TL <level-1> __
5234// ::= TL <level-1> _ <parameter-2 non-negative number> _
Pavel Labathba825192018-10-16 14:29:14 +00005235template <typename Derived, typename Alloc>
5236Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Richard Smithc20d1442018-08-20 20:14:49 +00005237 if (!consumeIf('T'))
5238 return nullptr;
5239
Richard Smithdf1c14c2019-09-06 23:53:21 +00005240 size_t Level = 0;
5241 if (consumeIf('L')) {
5242 if (parsePositiveInteger(&Level))
5243 return nullptr;
5244 ++Level;
5245 if (!consumeIf('_'))
5246 return nullptr;
5247 }
5248
Richard Smithc20d1442018-08-20 20:14:49 +00005249 size_t Index = 0;
5250 if (!consumeIf('_')) {
5251 if (parsePositiveInteger(&Index))
5252 return nullptr;
5253 ++Index;
5254 if (!consumeIf('_'))
5255 return nullptr;
5256 }
5257
Richard Smithc20d1442018-08-20 20:14:49 +00005258 // If we're in a context where this <template-param> refers to a
5259 // <template-arg> further ahead in the mangled name (currently just conversion
5260 // operator types), then we should only look it up in the right context.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005261 // This can only happen at the outermost level.
5262 if (PermitForwardTemplateReferences && Level == 0) {
Richard Smithb485b352018-08-24 23:30:26 +00005263 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5264 if (!ForwardRef)
5265 return nullptr;
5266 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5267 ForwardTemplateRefs.push_back(
5268 static_cast<ForwardTemplateReference *>(ForwardRef));
5269 return ForwardRef;
Richard Smithc20d1442018-08-20 20:14:49 +00005270 }
5271
Richard Smithdf1c14c2019-09-06 23:53:21 +00005272 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||
5273 Index >= TemplateParams[Level]->size()) {
5274 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter
5275 // list are mangled as the corresponding artificial template type parameter.
5276 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {
5277 // This will be popped by the ScopedTemplateParamList in
5278 // parseUnnamedTypeName.
5279 if (Level == TemplateParams.size())
5280 TemplateParams.push_back(nullptr);
5281 return make<NameType>("auto");
5282 }
5283
Richard Smithc20d1442018-08-20 20:14:49 +00005284 return nullptr;
Richard Smithdf1c14c2019-09-06 23:53:21 +00005285 }
5286
5287 return (*TemplateParams[Level])[Index];
5288}
5289
5290// <template-param-decl> ::= Ty # type parameter
5291// ::= Tn <type> # non-type parameter
5292// ::= Tt <template-param-decl>* E # template parameter
5293// ::= Tp <template-param-decl> # parameter pack
5294template <typename Derived, typename Alloc>
5295Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5296 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5297 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5298 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5299 if (N) TemplateParams.back()->push_back(N);
5300 return N;
5301 };
5302
5303 if (consumeIf("Ty")) {
5304 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5305 if (!Name)
5306 return nullptr;
5307 return make<TypeTemplateParamDecl>(Name);
5308 }
5309
5310 if (consumeIf("Tn")) {
5311 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5312 if (!Name)
5313 return nullptr;
5314 Node *Type = parseType();
5315 if (!Type)
5316 return nullptr;
5317 return make<NonTypeTemplateParamDecl>(Name, Type);
5318 }
5319
5320 if (consumeIf("Tt")) {
5321 Node *Name = InventTemplateParamName(TemplateParamKind::Template);
5322 if (!Name)
5323 return nullptr;
5324 size_t ParamsBegin = Names.size();
5325 ScopedTemplateParamList TemplateTemplateParamParams(this);
5326 while (!consumeIf("E")) {
5327 Node *P = parseTemplateParamDecl();
5328 if (!P)
5329 return nullptr;
5330 Names.push_back(P);
5331 }
5332 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5333 return make<TemplateTemplateParamDecl>(Name, Params);
5334 }
5335
5336 if (consumeIf("Tp")) {
5337 Node *P = parseTemplateParamDecl();
5338 if (!P)
5339 return nullptr;
5340 return make<TemplateParamPackDecl>(P);
5341 }
5342
5343 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005344}
5345
5346// <template-arg> ::= <type> # type or template
5347// ::= X <expression> E # expression
5348// ::= <expr-primary> # simple expressions
5349// ::= J <template-arg>* E # argument pack
5350// ::= LZ <encoding> E # extension
Pavel Labathba825192018-10-16 14:29:14 +00005351template <typename Derived, typename Alloc>
5352Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
Richard Smithc20d1442018-08-20 20:14:49 +00005353 switch (look()) {
5354 case 'X': {
5355 ++First;
Pavel Labathba825192018-10-16 14:29:14 +00005356 Node *Arg = getDerived().parseExpr();
Richard Smithc20d1442018-08-20 20:14:49 +00005357 if (Arg == nullptr || !consumeIf('E'))
5358 return nullptr;
5359 return Arg;
5360 }
5361 case 'J': {
5362 ++First;
5363 size_t ArgsBegin = Names.size();
5364 while (!consumeIf('E')) {
Pavel Labathba825192018-10-16 14:29:14 +00005365 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005366 if (Arg == nullptr)
5367 return nullptr;
5368 Names.push_back(Arg);
5369 }
5370 NodeArray Args = popTrailingNodeArray(ArgsBegin);
5371 return make<TemplateArgumentPack>(Args);
5372 }
5373 case 'L': {
5374 // ::= LZ <encoding> E # extension
5375 if (look(1) == 'Z') {
5376 First += 2;
Pavel Labathba825192018-10-16 14:29:14 +00005377 Node *Arg = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005378 if (Arg == nullptr || !consumeIf('E'))
5379 return nullptr;
5380 return Arg;
5381 }
5382 // ::= <expr-primary> # simple expressions
Pavel Labathba825192018-10-16 14:29:14 +00005383 return getDerived().parseExprPrimary();
Richard Smithc20d1442018-08-20 20:14:49 +00005384 }
5385 default:
Pavel Labathba825192018-10-16 14:29:14 +00005386 return getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005387 }
5388}
5389
5390// <template-args> ::= I <template-arg>* E
5391// extension, the abi says <template-arg>+
Pavel Labathba825192018-10-16 14:29:14 +00005392template <typename Derived, typename Alloc>
5393Node *
5394AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005395 if (!consumeIf('I'))
5396 return nullptr;
5397
5398 // <template-params> refer to the innermost <template-args>. Clear out any
5399 // outer args that we may have inserted into TemplateParams.
Richard Smithdf1c14c2019-09-06 23:53:21 +00005400 if (TagTemplates) {
Richard Smithc20d1442018-08-20 20:14:49 +00005401 TemplateParams.clear();
Richard Smithdf1c14c2019-09-06 23:53:21 +00005402 TemplateParams.push_back(&OuterTemplateParams);
5403 OuterTemplateParams.clear();
5404 }
Richard Smithc20d1442018-08-20 20:14:49 +00005405
5406 size_t ArgsBegin = Names.size();
5407 while (!consumeIf('E')) {
5408 if (TagTemplates) {
5409 auto OldParams = std::move(TemplateParams);
Pavel Labathba825192018-10-16 14:29:14 +00005410 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005411 TemplateParams = std::move(OldParams);
5412 if (Arg == nullptr)
5413 return nullptr;
5414 Names.push_back(Arg);
5415 Node *TableEntry = Arg;
5416 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5417 TableEntry = make<ParameterPack>(
5418 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
Richard Smithb485b352018-08-24 23:30:26 +00005419 if (!TableEntry)
5420 return nullptr;
Richard Smithc20d1442018-08-20 20:14:49 +00005421 }
Richard Smithdf1c14c2019-09-06 23:53:21 +00005422 TemplateParams.back()->push_back(TableEntry);
Richard Smithc20d1442018-08-20 20:14:49 +00005423 } else {
Pavel Labathba825192018-10-16 14:29:14 +00005424 Node *Arg = getDerived().parseTemplateArg();
Richard Smithc20d1442018-08-20 20:14:49 +00005425 if (Arg == nullptr)
5426 return nullptr;
5427 Names.push_back(Arg);
5428 }
5429 }
5430 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5431}
5432
5433// <mangled-name> ::= _Z <encoding>
5434// ::= <type>
5435// extension ::= ___Z <encoding> _block_invoke
5436// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5437// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
Pavel Labathba825192018-10-16 14:29:14 +00005438template <typename Derived, typename Alloc>
5439Node *AbstractManglingParser<Derived, Alloc>::parse() {
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005440 if (consumeIf("_Z") || consumeIf("__Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005441 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005442 if (Encoding == nullptr)
5443 return nullptr;
5444 if (look() == '.') {
5445 Encoding = make<DotSuffix>(Encoding, StringView(First, Last));
5446 First = Last;
5447 }
5448 if (numLeft() != 0)
5449 return nullptr;
5450 return Encoding;
5451 }
5452
Erik Pilkingtonc0df1582019-01-17 21:37:36 +00005453 if (consumeIf("___Z") || consumeIf("____Z")) {
Pavel Labathba825192018-10-16 14:29:14 +00005454 Node *Encoding = getDerived().parseEncoding();
Richard Smithc20d1442018-08-20 20:14:49 +00005455 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5456 return nullptr;
5457 bool RequireNumber = consumeIf('_');
5458 if (parseNumber().empty() && RequireNumber)
5459 return nullptr;
5460 if (look() == '.')
5461 First = Last;
5462 if (numLeft() != 0)
5463 return nullptr;
5464 return make<SpecialName>("invocation function for block in ", Encoding);
5465 }
5466
Pavel Labathba825192018-10-16 14:29:14 +00005467 Node *Ty = getDerived().parseType();
Richard Smithc20d1442018-08-20 20:14:49 +00005468 if (numLeft() != 0)
5469 return nullptr;
5470 return Ty;
5471}
5472
Pavel Labathba825192018-10-16 14:29:14 +00005473template <typename Alloc>
5474struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
5475 using AbstractManglingParser<ManglingParser<Alloc>,
5476 Alloc>::AbstractManglingParser;
5477};
5478
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005479DEMANGLE_NAMESPACE_END
Richard Smithc20d1442018-08-20 20:14:49 +00005480
Erik Pilkingtonf70e4d82019-01-17 20:37:51 +00005481#endif // DEMANGLE_ITANIUMDEMANGLE_H